Xây dựng Hệ Thống Web Xem Trực Tiếp Camera và Xem Lại (Python, OpenCV, YOLO, FFmpeg)

 

Xây dựng Hệ Thống Web Xem Trực Tiếp Camera và Xem Lại (Python, OpenCV, YOLO, FFmpeg)

Hệ thống này sẽ sử dụng Python kết hợp với OpenCV, YOLO, và FFmpeg để xử lý video, nhận diện đối tượng, và xây dựng giao diện web xem trực tiếp và xem lại camera với khả năng mở rộng cao.

Kiến trúc hệ thống:

  • Phần cứng:

    • Camera IP (hỗ trợ RTSP)

    • Máy chủ (cấu hình mạnh, dung lượng lưu trữ lớn)

  • Phần mềm:

    • Hệ điều hành: Ubuntu Server (khuyến nghị)

    • Backend: Python, Flask, OpenCV, FFmpeg, YOLOv5

    • Database: PostgreSQL (lưu trữ thông tin camera, video, sự kiện)

    • Message broker: Redis (xử lý bất đồng bộ, mở rộng scale)

    • Frontend: HTML, CSS, JavaScript (và thư viện như Video.js, Chart.js)

  • Giao thức:

    • RTSP: Truyền phát video trực tiếp từ camera.

    • HTTP: Giao tiếp giữa client và server.

    • WebSockets: Cập nhật trạng thái, thông báo từ server đến client (realtime).

Các bước triển khai:

1. Cài đặt môi trường:

      # Cài đặt Python và các thư viện cần thiết
sudo apt update
sudo apt install python3 python3-pip python3-venv
python3 -m venv env
source env/bin/activate
pip install flask opencv-python numpy imutils ffmpeg-python redis yolov5 torch torchvision torchaudio psycopg2-binary

# Tải YOLOv5
git clone https://github.com/ultralytics/yolov5.git
cd yolov5
pip install -r requirements.txt
    

2. Cấu hình Camera IP:

  • Kết nối camera với mạng và thiết lập địa chỉ IP tĩnh.

  • Kiểm tra thông tin RTSP stream URL của camera.

3. Xây dựng Backend (Python - Flask):

      import cv2
import time
import threading
from flask import Flask, render_template, Response, jsonify
from imutils.video import VideoStream
import ffmpeg
import redis
import psycopg2
from yolov5 import detect

# Cấu hình kết nối database
DATABASE_URL = "postgresql://user:password@host:port/database"

# Kết nối Redis
r = redis.Redis(host='localhost', port=6379, db=0)

app = Flask(__name__)

# Thông tin camera (lấy từ database)
cameras = {}

# Hàm tải thông tin camera từ database
def load_cameras():
    with psycopg2.connect(DATABASE_URL) as conn:
        with conn.cursor() as cur:
            cur.execute("SELECT id, name, rtsp_url FROM cameras")
            for row in cur:
                cameras[row[0]] = {
                    'name': row[1],
                    'rtsp_url': row[2],
                    'stream': None,
                    'last_frame': None
                }

# Hàm xử lý stream video
def process_stream(camera_id):
    camera_info = cameras[camera_id]
    cap = VideoStream(camera_info['rtsp_url']).start()
    while True:
        frame = cap.read()
        if frame is None:
            break

        # Xử lý YOLOv5
        results = detect.run(weights='yolov5s.pt', source=frame)
        # ... Xử lý kết quả detect và vẽ lên frame ...

        # Lưu frame mới nhất
        camera_info['last_frame'] = frame

        # Lưu trữ video, xử lý sự kiện (nếu cần)
        # ...

        # Gửi thông báo đến Redis (realtime update)
        r.publish(f'camera_{camera_id}', 'new_frame')

        time.sleep(0.01)

    cap.stop()

# Khởi tạo stream cho mỗi camera
@app.before_first_request
def init_streams():
    load_cameras()
    for camera_id in cameras:
        t = threading.Thread(target=process_stream, args=(camera_id,))
        t.daemon = True
        t.start()

# Route: Trang chủ, hiển thị danh sách camera
@app.route('/')
def index():
    return render_template('index.html', cameras=cameras)

# Route: Xem trực tiếp camera
@app.route('/video_feed/<int:camera_id>')
def video_feed(camera_id):
    return Response(generate_frames(camera_id),
                    mimetype='multipart/x-mixed-replace; boundary=frame')

# Hàm generate frame cho stream MJPEG
def generate_frames(camera_id):
    while True:
        frame = cameras[camera_id]['last_frame']
        if frame is not None:
            ret, buffer = cv2.imencode('.jpg', frame)
            frame = buffer.tobytes()
            yield (b'--frame\r\n'
                   b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
        time.sleep(0.01)

# Route: API lấy danh sách video đã lưu
@app.route('/api/videos/<int:camera_id>')
def get_videos(camera_id):
    # Lấy danh sách video từ database
    # ...
    return jsonify(videos)

# ... Các route khác cho chức năng xem lại, tìm kiếm, phân tích ...

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)
    

4. Tạo Frontend:

  • Tạo file index.html (sử dụng JavaScript và thư viện Video.js để nhúng video stream)

  • Tạo các trang HTML, CSS, JavaScript cho chức năng xem lại, quản lý camera...

5. Lưu trữ video và xử lý sự kiện:

  • Lưu trữ video: Sử dụng FFmpeg để lưu trữ video theo thời gian, sự kiện hoặc chuyển động.

  • Xử lý sự kiện: Sử dụng Redis để gửi thông báo về các sự kiện đến client (real-time) hoặc lưu trữ vào database để phân tích sau.

Khả năng mở rộng:

  • Scale theo chiều ngang: Sử dụng load balancer để phân phối tải cho nhiều máy chủ backend.

  • Xử lý bất đồng bộ: Sử dụng Redis và Celery để xử lý các tác vụ nặng, tốn thời gian như lưu trữ video, phân tích YOLO...

  • Cơ sở dữ liệu: Sử dụng PostgreSQL cho khả năng lưu trữ lớn và truy vấn hiệu quả.

Lưu ý:

  • Bảo mật: Cấu hình HTTPS, xác thực người dùng, phân quyền truy cập.

  • Tối ưu hóa: Sử dụng kỹ thuật nén video, giảm frame rate, cache dữ liệu để giảm tải cho hệ thống.

  • Kiểm tra và xử lý lỗi: Xây dựng cơ chế xử lý lỗi, ghi log để dễ dàng theo dõi và khắc phục sự cố.

Kết luận:
Hệ thống web xem camera trực tiếp và xem lại sử dụng Python, OpenCV, YOLO, FFmpeg có khả năng mở rộng cao, đáp ứng nhu cầu giám sát, bảo mật, phân tích video phức tạp.

Mới hơn Cũ hơn