In this article, I am going to implement something interesting! I am interested to implement image processing in the images from the raspi camera. Because we can install python virtualenv and manage libraries in isolation, it makes vary easy to use the power of opencv in raspberry pi.

Creating Virtualenv

sudo apt install python3-pip
sudo pip3 install virtualenv
virtualenv VENV
#Activate 
source VENV/bin/activate
#deactivate
deactivate

Installation of Opencv

sudo apt install python3-opencv #activate Virtual Environment
source VENV/bin/activate
pip3 install numpy
pip3 install opencv-python
pip3 install opencv-contrib-python
pip3 install imutils
deactivate

Installation of Flask

pip3 install flask
pip3 install flask-socketio (optional, needed for websocket)

I have written a class with the help of ChatGPT, to read images from webcam and serve.

import cv2
import threading

class Camera:
    def __init__(self) -> None:
        # Global camera object and lock
        self.camera = None
        self.camera_lock = threading.Lock()
        self.active_clients = 0
        self.camera_address=0

    def open_camera(self):    
        if self.camera is None:
            self.camera = cv2.VideoCapture(self.camera_address)

    def close_camera(self):
        if self.camera is not None:
            self.camera.release()
            self.camera = None
        
    def generate_frames(self):
        # Lock the camera and increment active client count
        with self.camera_lock:
            self.active_clients += 1
            self.open_camera()

        try:
            while True:
                with self.camera_lock:
                    # Capture frame-by-frame
                    success, frame = self.camera.read()
                    if not success:
                        break
                    else:
                        # Encode frame in JPEG format
                        ret, buffer = cv2.imencode('.jpg', frame)
                        frame = buffer.tobytes()

                        # Send the frame to the client
                        yield (b'--frame\r\n'
                               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
        except GeneratorExit:
            # This block is executed when the generator is closed
            with self.camera_lock:
                self.active_clients -= 1
                if self.active_clients == 0:
                    self.close_camera()
                print(f"Client disconnected. Active clients: {self.active_clients}")        

We call the method “generate_frames” in route, and return it as a response. This route endpoint can be placed in html in <img> tag. This will display the image frames obtained from the webcam. The reading of images from camera is stopped when the browser is closed which is crucial for a low resources device like raspi. This implementation of stopping reading images when no browsers are active, kept raspi from overheating and shutting down.

In routes.py

@app.route('/video_feed')
def video_feed():
    # Stream video frames to the client
    return Response(camera.generate_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')

In index.html

<img src="{{ url_for('app.video_feed')}}"></p>

So, the index.html page will show the videos obtained from the webcam.

Running the App

app.py

from flask import Flask
app = Flask(__name__)
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, threaded=True, debug=True)

“python app.py” will run the flask and the content is available in port 5000, can be accessed locally using the following link

http://localhost:5000

The index.html will be server with the videos obtained from webcam.

FAQs

  1. How to get the camera address?
  2. How to check if the camera is working?

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *