2

I have a view home:

def home(request):
    return render(request, 'detection/home.html')

And here is its' template templates/detection/home.html:

{% extends "detection/base.html" %}

{% block content %}

<h1>Camera View</h1>

<img src="{% url 'cam-feed' %}"></img>

{% endblock content %}

which is based on templates/detection/base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    {% block content %}
    {% endblock content %}
</body>
</html>

In this page, as can be seen from home.html, I show camera output using view cam_feed:

def cam_feed(request):
    return StreamingHttpResponse(gen(VideoCamera(), content_type="multipart/x-mixed-replace;boundary=frame")

which uses the class VideoCamera which is an openCV class to show the camera and which outputs a prediction variable in get_frame:

class VideoCamera(object):
    def __init__(self):
        self.video = cv2.VideoCapture(0)

    def __del__(self):
        self.video.release()

    def get_frame(self):
        _, image = self.video.read()

        ### All the detections

        # Person Existence Classification
        # RGB_img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        im = Image.fromarray(image)
        im = im.resize((128, 128))
        img_array = np.array(im)
        img_array = np.expand_dims(img_array, axis=0)
        prediction = int(model.predict(img_array)[0][0])
        
        _, jpeg = cv2.imencode('.jpg', image)
        return jpeg.tobytes()

cam_feed also uses function gen which passes the camera output in the appropriate form:

def gen(camera):
    while True:
        frame = camera.get_frame()
        yield(b'--frame\r\n'
              b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')

How can I send the variable prediction returned from VideoCamera class above (preferably every time a new frame is received and the prediction is made), to template home.html, so that I can output it for the user to see. I know that I can normally pass a dictionary context to home.html but I cannot see a way to pass it from function gen to view home as it is called inside StreamingHttpResponse which is called in <img> tag of home.html.

Sayyor Y
  • 1,130
  • 2
  • 14
  • 27

1 Answers1

1

If you only want to get the prediction for one frame, can't you just add a method for the prediction and call that method in the template-view like this?:

# where VideoCamera is defined:
class VideoCamera(object):
    def __init__(self):
        self.video = cv2.VideoCapture(0)

    def __del__(self):
        self.video.release()

    def get_frame(self):
        # unchanged...

    def get_prediction(self):
        _, image = self.video.read()

        ### All the detections

        # Person Existence Classification
        # RGB_img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        im = Image.fromarray(image)
        im = im.resize((128, 128))
        img_array = np.array(im)
        img_array = np.expand_dims(img_array, axis=0)
        prediction = int(model.predict(img_array)[0][0])
        return prediction

# in views.py:
def home(request):
    cam = VideoCamera()
    prediction = cam.get_prediction()
    return render(request, 'detection/home.html', context={'prediction': prediction})

Also you might want to look at django-channels

SMoenig
  • 486
  • 3
  • 11
  • I actually don't want to get a prediction for just a single frame. I want to get predictions printed every time camera gets the next frame (or at least every certain time interval). But your solution only prints a prediction of the first frame. Sorry if I was not clear in my question. – Sayyor Y Mar 17 '21 at 18:26
  • Yes, I am looking into django-channels. Would be great if you could show me how to set it all up for this specific problem. – Sayyor Y Mar 17 '21 at 18:30
  • I'm really no expert on any of this, but I found the Installation-chapter in the channels documentation to be sufficiently easy to follow, if you only want to experiment with it. – SMoenig Mar 17 '21 at 23:12
  • 1
    If you want to continuously update the prediction for the client, maybe you can somehow encode it with the frame and separate it again on the clientside with js or whatever you want to use there. – SMoenig Mar 17 '21 at 23:16