zynq环境用opencv测摄像头

参考

sdl安装测试-mingw32环境

mingW32环境用opencv测摄像头

ubuntu18.04环境用opencv测摄像头

摄像头发现

bash 复制代码
root@ant:~# lsusb
Bus 001 Device 003: ID 1bcf:2281 Sunplus Innovation Technology Inc.
Bus 001 Device 002: ID 05e3:0608 Genesys Logic, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
root@ant:~# ls /dev/video*
/dev/video0  /dev/video1  /dev/video2


root@ant:~# v4l2-ctl --list-devices
vcap_dvp output 0 (platform:vcap_dvp:0):
        /dev/video0

Q8 HD Webcam: Q8 HD Webcam (usb-ci_hdrc.0-1.4):
        /dev/video2
        /dev/video3

简单测试

cam_test.py 拍照

bash 复制代码
import cv2
cap = cv2.VideoCapture(2)
# 强制 MJPEG(很多USB摄像头必须)
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'MJPG'))
ret, frame = cap.read()
if ret:
    cv2.imwrite("test.jpg", frame)
    print("OK")
else:
    print("FAIL")
cap.release()

录像

bash 复制代码
#!/usr/bin/env python3
"""
ZYNQ 摄像头无显示器版本(稳定版)
- SSH/CLI 环境完全适配
- 支持命令行传入摄像头号
- 单帧、批量、录像、连续监控
"""

import cv2
import sys
import time
import json
import os
from pathlib import Path
from datetime import datetime

# ---------------------------
# 获取摄像头号
# ---------------------------
CAM_ID = int(sys.argv[1]) if len(sys.argv) > 1 else 1

# ---------------------------
# 摄像头类
# ---------------------------
class HeadlessCameraCapture:
    def __init__(self, camera_id=1, output_dir="./captures", enable_metadata=True, verbose=True):
        self.camera_id = camera_id
        self.output_dir = output_dir
        self.enable_metadata = enable_metadata
        self.verbose = verbose
        self.cap = None
        self.frame_count = 0
        Path(self.output_dir).mkdir(parents=True, exist_ok=True)

    def log(self, msg, level="INFO"):
        if not self.verbose:
            return
        levels = {"INFO": "✓", "WARN": "⚠", "ERROR": "❌"}
        prefix = levels.get(level, "•")
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        print(f"[{timestamp}] {prefix} {msg}")

    def open_camera(self, width=640, height=480, fps=10, retries=5):
        self.log(f"正在打开摄像头 {self.camera_id}...")
        self.cap = cv2.VideoCapture(f"/dev/video{self.camera_id}")
        if not self.cap.isOpened():
            self.log("❌ 无法打开摄像头", "ERROR")
            return False

        # 强制 MJPG + 分辨率 + FPS
        self.cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'MJPG'))
        self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
        self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
        self.cap.set(cv2.CAP_PROP_FPS, fps)
        time.sleep(0.5)  # 等待摄像头稳定

        # 尝试读取一帧
        for i in range(retries):
            ret, frame = self.cap.read()
            if ret:
                self.log(f"✓ 摄像头打开成功,分辨率: {frame.shape[1]}x{frame.shape[0]}")
                return True
            time.sleep(0.1)
        self.log("❌ 摄像头读取失败", "ERROR")
        self.cap.release()
        self.cap = None
        return False

    def capture_single_frame(self, filename=None):
        if not self.cap:
            self.log("❌ 摄像头未打开", "ERROR")
            return None
        ret, frame = self.cap.read()
        if not ret or frame is None:
            self.log("❌ 读取失败", "WARN")
            return None
        self.frame_count += 1
        if filename is None:
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")[:-3]
            filename = f"frame_{self.camera_id}_{timestamp}.jpg"
        filepath = os.path.join(self.output_dir, filename)
        cv2.imwrite(filepath, frame)
        self.log(f"✓ 已保存: {filename} ({os.path.getsize(filepath)/1024:.1f}KB)")
        if self.enable_metadata:
            self._save_metadata(filepath, frame)
        return filepath

    def capture_video(self, duration=10, fps=10, output_file=None):
        if not self.cap:
            self.log("❌ 摄像头未打开", "ERROR")
            return None
        if output_file is None:
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            output_file = f"record_{self.camera_id}_{timestamp}.avi"
        output_path = os.path.join(self.output_dir, output_file)

        width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
        height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
        fourcc = cv2.VideoWriter_fourcc(*'MJPG')
        out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))

        self.log(f"开始录像: {output_file}, 时长 {duration}s")
        start_time = time.time()
        frame_count = 0
        try:
            while time.time() - start_time < duration:
                ret, frame = self.cap.read()
                if ret:
                    out.write(frame)
                    frame_count += 1
        finally:
            out.release()
            self.log(f"录像完成: {output_file}, 共 {frame_count} 帧")
        return output_path

    def _save_metadata(self, image_path, frame):
        try:
            json_path = image_path.replace('.jpg', '_meta.json')
            metadata = {
                'timestamp': datetime.now().isoformat(),
                'camera_id': self.camera_id,
                'resolution': f"{frame.shape[1]}x{frame.shape[0]}",
                'file_size_kb': os.path.getsize(image_path)/1024,
                'frame_count': self.frame_count
            }
            with open(json_path, 'w') as f:
                json.dump(metadata, f, indent=2)
        except:
            pass

# ---------------------------
# 简单测试录像
# ---------------------------
if __name__ == "__main__":
    cam = HeadlessCameraCapture(camera_id=CAM_ID)
    if cam.open_camera(width=640, height=480, fps=10):
        cam.capture_video(duration=20, fps=10)
        cam.cap.release()

网络摄像头

访问 http://192.168.3.42:8080/video

python 复制代码
#!/usr/bin/env python3
"""
ZYNQ 摄像头浏览器访问版(纯 Python + OpenCV,无依赖)
- MJPEG 流浏览器访问
- 显示帧数和实时 FPS
- 可选录像
"""

import cv2
import time
import threading
from http.server import BaseHTTPRequestHandler, HTTPServer

CAM_ID = 3
FRAME_WIDTH = 640
FRAME_HEIGHT = 480
FPS = 10
SHOW_FPS = True
RECORD = False
PORT = 8080

class CameraStream:
    def __init__(self, camera_id=0, width=640, height=480, fps=10):
        self.cap = cv2.VideoCapture(f"/dev/video{camera_id}", cv2.CAP_V4L2)
        if not self.cap.isOpened():
            raise RuntimeError(f"无法打开摄像头 /dev/video{camera_id}")
        self.cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'MJPG'))
        self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
        self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
        self.cap.set(cv2.CAP_PROP_FPS, fps)

        self.frame = None
        self.lock = threading.Lock()
        self.stopped = False

        # FPS
        self._last_time = time.time()
        self._frame_count = 0
        self.current_fps = 0

        # 录像
        self.out = None
        if RECORD:
            timestamp = time.strftime("%Y%m%d_%H%M%S")
            self.out = cv2.VideoWriter(f'record_{camera_id}_{timestamp}.avi',
                                       cv2.VideoWriter_fourcc(*'MJPG'),
                                       fps,
                                       (width, height))

        t = threading.Thread(target=self.update, daemon=True)
        t.start()

    def update(self):
        while not self.stopped:
            ret, frame = self.cap.read()
            if not ret:
                continue

            self._frame_count += 1
            now = time.time()
            if now - self._last_time >= 1.0:
                self.current_fps = self._frame_count / (now - self._last_time)
                self._frame_count = 0
                self._last_time = now

            if SHOW_FPS:
                cv2.putText(frame, f'FPS: {self.current_fps:.1f}', (10, 30),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)
                cv2.putText(frame, f'Frame: {self._frame_count}', (10, 60),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)

            if self.out:
                self.out.write(frame)

            with self.lock:
                self.frame = frame

    def read(self):
        with self.lock:
            if self.frame is None:
                return None
            ret, jpeg = cv2.imencode('.jpg', self.frame)
            return jpeg.tobytes()

    def stop(self):
        self.stopped = True
        time.sleep(0.1)
        self.cap.release()
        if self.out:
            self.out.release()

# -------------------------
# HTTP MJPEG 服务
# -------------------------
camera = CameraStream(camera_id=CAM_ID, width=FRAME_WIDTH, height=FRAME_HEIGHT, fps=FPS)

class MJPEGHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path != '/video':
            self.send_error(404)
            return
        self.send_response(200)
        self.send_header('Content-type', 'multipart/x-mixed-replace; boundary=frame')
        self.end_headers()
        try:
            while True:
                frame = camera.read()
                if frame is None:
                    continue
                self.wfile.write(b'--frame\r\n')
                self.send_header('Content-Type', 'image/jpeg')
                self.send_header('Content-Length', str(len(frame)))
                self.end_headers()
                self.wfile.write(frame)
                self.wfile.write(b'\r\n')
                time.sleep(1.0 / FPS)
        except Exception:
            pass

if __name__ == '__main__':
    print(f"访问浏览器查看摄像头:http://0.0.0.0:{PORT}/video")
    server = HTTPServer(('0.0.0.0', PORT), MJPEGHandler)
    try:
        server.serve_forever()
    finally:
        camera.stop()
        server.server_close()
相关推荐
xyz_CDragon2 小时前
OpenClaw Skills 完全指南:ClawHub 安装、安全避坑与自定义开发(2026)
人工智能·python·ai·skill·openclaw·clawhub
断眉的派大星2 小时前
pytorch中view和reshape的区别
人工智能·pytorch·python
nihao5612 小时前
机器学习:阈值与混淆矩阵
人工智能·机器学习·矩阵
鱼骨不是鱼翅2 小时前
机器学习(1)-----基础概念
人工智能·机器学习
xiao5kou4chang6kai42 小时前
蒸散发与光合作用阻抗理论 → ArcGIS自动化 → 区域ET/GPP产品融合
人工智能·蒸散发·植被生产力估算·penman-monteith
cd_949217212 小时前
骁龙与F1的故事:一场连接与速度的深度对话
人工智能
Fleshy数模2 小时前
基于MediaPipe实现人体姿态与脸部关键点检测
python·opencv·计算机视觉
新加坡内哥谈技术2 小时前
大语言模型的上下文工程指南
人工智能
Gofarlic_OMS2 小时前
装备制造企业Fluent许可证成本分点典型案例
java·大数据·开发语言·人工智能·自动化·制造