Сохранение изображения, полученного с веб-камеры

Я создаю проект Django, в котором мне нужно сделать снимок с веб-камеры, а затем сохранить его в базе данных и в виде файла. Я сохраняю исходный текст в базе данных, но у меня возникают проблемы с сохранением его в файл. Вот мой код:

html:

<form method="POST" action="{% url 'takePhoto' %}" enctype="multipart/form-data">
    {% csrf_token %}
                                     
            <video id="video" autoplay ></video>                               
            <canvas id="canvas"></canvas>                                
                     
            <input type="hidden" name="photo" id="photo" value=""/>
            <button id="startbutton1" class="btn btn-outline-secondary btn-sm">Take Photo</button>
            <button id="submit" type="submit">submit</button>
            <script src="{% static 'scripts/script.js' %}"></script>             

javascript:

(function() {

var width = 320;    
  var height = 0;    
  var streaming = false;  
  var video = null;
  var canvas = null;
  var photo = null;
  var startbutton1 = null;

  function startup() {
    video = document.getElementById('video');
    canvas = document.getElementById('canvas');

photo = document.getElementById('photo');
startbutton1 = document.getElementById('startbutton1');

navigator.mediaDevices.getUserMedia({video: true, audio: false})
.then(function(stream) {
  video.srcObject = stream;
  video.play();
})
.catch(function(err) {
  console.log("An error occurred: " + err);
});

video.addEventListener('canplay', function(ev){
  if (!streaming) {
    height = video.videoHeight / (video.videoWidth/width);


    if (isNaN(height)) {
      height = width / (4/3);
    }

    video.setAttribute('width', width);
    video.setAttribute('height', height);
    canvas.setAttribute('width', width);
    canvas.setAttribute('height', height);
    streaming = true;
  }
}, false);

startbutton1.addEventListener('click', function(ev){
  takepicture();
  ev.preventDefault();
}, false);

clearphoto();


}
  



function clearphoto() {
    var context = canvas.getContext('2d');
    context.fillStyle = "#AAA";
    context.fillRect(0, 0, canvas.width, canvas.height);
var data = canvas.toDataURL('image/png');
photo.setAttribute('src', data);


 }

  function takepicture() {
    var context = canvas.getContext('2d');
    if (width && height) {
  canvas.width = width;
  canvas.height = height;
  context.drawImage(video, 0, 0, width, height);

  var data = canvas.toDataURL('image/png');
  photo.value=data;
} else {
  clearphoto();


 } 


}



window.addEventListener('load', startup, false);
})();

просмотров:

def takePhoto(request):
   print("works")
   if not request.session.get('logged_in'):
       return redirect('/appChallenge/login')
   if request.method== 'POST':        
       user = User.objects.get(username=request.session["username"])
       img = request.POST.get("photo")
       image = img
       imagePath="/media"
       a=str(img)
       image = image.save(f"{imagePath}/{a}.png")
       imgInfo= Image(user=user, img=img)
       imgInfo.save()    
       print("works")
       return render(request, 'page.html')

Когда я нажимаю кнопку submit, появляется сообщение "'str' object has no attribute 'save'". Пожалуйста, помогите. Спасибо.

Если ваш js/html код работает, вы получите необработанные данные изображения, закодированные в base64 в вашем представлении 'takePhoto'. Попробуйте print(img), чтобы увидеть что-то вроде "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAADwCAYAA...."

Возможно, вы увидите только "iVBORw0KGgoAAAANSUhEUgAAAUAAAADwCAYAA...." без метаданных.

Так что ваш 'img' - это просто строка с base64 закодированным значением, у которой нет метода 'save'.

Во-первых, вам нужно избавиться от "data:image/png;base64," в необработанных данных изображения, если строка изображения содержит его. Это метаданные, и base64 не может их декодировать. Это можно сделать на стороне front end:

var data = canvas.toDataURL('image/png').replace(/^data:image\/png;base64,/, "")

Or back end:

img = request.POST.get("photo").replace('data:image/png;base64,', '')

Далее необходимо использовать django ContentFile для создания файлоподобного объекта. Вам нужно имитировать файл с помощью его метода .read(). Также необходимо декодировать данные изображения в кодировке base64:

import base64
from django.core.files.base import ContentFile
    
def takePhoto(request):
   print("works")
   if not request.session.get('logged_in'):
       return redirect('/appChallenge/login')
   if request.method== 'POST':        
       user = request.user
       
       # remove meta data from base64 encoded data, you can also 
       # use 'split(',')[1]' to remove all before ','
       img = request.POST.get("photo").replace('data:image/png;base64,', '')
       # create a file-like object with your image data 
       image_file_like = ContentFile(base64.b64decode(img))
       imagePath="/media"
       
       # first you need to create object
       image = Image(user=user)
       
       # and then save image into your model object
       # note: only if your 'img' field is 'ImageField' or similar 
       image.img.save(f"{imagePath}/{a}.png", image_file_like)
       image.save() 

       print("works")
       return render(request, 'page.html') 

Надеюсь, я ничего не забыл

Вернуться на верх