Stream OpenCV frame to HTML in Python

16,430

I am sure you have solved your error by now but this is for other people who visit this question:

write this is your camera.py file

don't get confused by draw_box method, it's just custom square I am using. You can use normal cv2.rectangle for making rectangles on faces.

import cv2


WHITE = [255, 255, 255]
face_cascade = cv2.CascadeClassifier('Haar/haarcascade_frontalcatface.xml')
eye_cascade = cv2.CascadeClassifier('Haar/haarcascade_eye.xml')


def draw_box(Image, x, y, w, h):
    cv2.line(Image, (x, y), (x + int(w / 5), y), WHITE, 2)
    cv2.line(Image, (x + int((w / 5) * 4), y), (x + w, y), WHITE, 2)
    cv2.line(Image, (x, y), (x, y + int(h / 5)), WHITE, 2)
    cv2.line(Image, (x + w, y), (x + w, y + int(h / 5)), WHITE, 2)
    cv2.line(Image, (x, (y + int(h / 5 * 4))), (x, y + h), WHITE, 2)
    cv2.line(Image, (x, (y + h)), (x + int(w / 5), y + h), WHITE, 2)
    cv2.line(Image, (x + int((w / 5) * 4), y + h), (x + w, y + h), WHITE, 2)
    cv2.line(Image, (x + w, (y + int(h / 5 * 4))), (x + w, y + h), WHITE, 2)


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

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

    def get_frame(self):
        success, image = self.video.read()
        # We are using Motion JPEG, but OpenCV defaults to capture raw images,
        # so we must encode it into JPEG in order to correctly display the
        # video stream.

        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        faces = face_cascade.detectMultiScale(gray, 1.3, 5)
        for (x, y, w, h) in faces:
           gray_face = cv2.resize((gray[y:y + h, x:x + w]), (110, 110))
            eyes = eye_cascade.detectMultiScale(gray_face)
            for (ex, ey, ew, eh) in eyes:

                draw_box(gray, x, y, w, h)

        ret, jpeg = cv2.imencode('.jpg', gray)

        return jpeg.tobytes()
Share:
16,430
Obiii
Author by

Obiii

Updated on June 11, 2022

Comments

  • Obiii
    Obiii about 2 years

    I am trying to read a video from a URL in opencv(Python) and then process it frame by frame and then send it to an HTML page.

    But I am only getting the first frame, after that the program gives the following error enter image description here

    This is my main file (main.py)

    from flask import Flask, render_template, Response
    from camera import VideoCamera
    import pdb
    app = Flask(__name__)
    
    @app.route('/')
    def index():
        return render_template('index.html')
    
    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')
    
    @app.route('/video_feed')
    def video_feed():
        return Response(gen(VideoCamera()),
                        mimetype='multipart/x-mixed-replace; boundary=frame')
    
    if __name__ == '__main__':
        app.run(host='127.0.0.1', debug=True)
    

    And this is the camera.py file:

        import cv2
        import urllib
        import pdb
        import numpy as np
    
        face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
        #https://github.com/Itseez/opencv/blob/master/data/haarcascades/haarcascade_eye.xml
        eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
    
        class VideoCamera(object):
            def __init__(self):
                # Using OpenCV to capture from device 0. If you have trouble capturing
                # from a webcam, comment the line below out and use a video file
                # instead.
                self.video = urllib.urlopen('http://192.168.10.12:8080/video')   #cv2.VideoCapture(0)
                # If you decide to use video.mp4, you must have this file in the folder
                # as the main.py.
                # self.video = cv2.VideoCapture('video.mp4')
    
            def __del__(self):
                self.video.release()
    
            def get_frame(self):
    
                bytes=''
                while True:
                    # pdb.set_trace()
                    bytes+=self.video.read(1024)
                    a = bytes.find('\xff\xd8')
                    b = bytes.find('\xff\xd9')
                    if a!=-1 and b!=-1:
                        jpg = bytes[a:b+2]
                        bytes= bytes[b+2:]
    
                        img = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8),cv2.IMREAD_COLOR) 
                        # pdb.set_trace()
                        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
                        faces = face_cascade.detectMultiScale(gray, 1.3, 5)
                        for (x,y,w,h) in faces:
                            cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
                            roi_gray = gray[y:y+h, x:x+w]
                            roi_color = img[y:y+h, x:x+w]
    
                        ret, jpeg = cv2.imencode('.jpg', img)
                        return jpeg.tobytes()
    

    I only get the first frame( Shown below): enter image description here