不止于连接:用Jetson Nano和CSI摄像头玩转计算机视觉入门项目
从零到一用Jetson Nano和CSI摄像头打造智能视觉项目当你第一次拿到Jetson Nano开发板和CSI摄像头时可能会被它小巧的体积所迷惑——这真的能跑计算机视觉算法吗答案是肯定的。这套组合不仅能够流畅运行OpenCV还能处理一些轻量级的深度学习模型。本文将带你超越简单的硬件连接直接进入项目实战环节。1. 环境准备与基础验证在开始任何有趣的项目之前确保你的硬件和软件环境已经正确配置。Jetson Nano预装了JetPack系统包含了CUDA、cuDNN等加速库这为计算机视觉任务提供了强大的支持。首先验证摄像头是否正常工作import cv2 def test_camera(): cap cv2.VideoCapture(nvarguscamerasrc ! video/x-raw(memory:NVMM), width1280, height720, formatNV12, framerate30/1 ! nvvidconv ! video/x-raw, formatBGRx ! videoconvert ! video/x-raw, formatBGR ! appsink, cv2.CAP_GSTREAMER) if not cap.isOpened(): print(无法打开摄像头) return while True: ret, frame cap.read() if not ret: break cv2.imshow(Camera Test, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows() test_camera()这段代码会打开一个窗口显示摄像头实时画面按q键退出。如果能看到画面说明硬件连接正确。注意Jetson Nano的CSI摄像头需要使用GStreamer管道来捕获视频流这与普通USB摄像头的调用方式不同。2. 实时人脸检测系统有了基础验证后我们来构建第一个实用功能——实时人脸检测。OpenCV提供了预训练的人脸检测模型可以直接使用。2.1 加载预训练模型首先下载OpenCV的人脸检测模型文件wget https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_default.xml2.2 实现人脸检测import cv2 def face_detection(): # 加载人脸检测模型 face_cascade cv2.CascadeClassifier(haarcascade_frontalface_default.xml) # 初始化摄像头 cap cv2.VideoCapture(nvarguscamerasrc ! video/x-raw(memory:NVMM), width1280, height720, formatNV12, framerate30/1 ! nvvidconv ! video/x-raw, formatBGRx ! videoconvert ! video/x-raw, formatBGR ! appsink, cv2.CAP_GSTREAMER) while cap.isOpened(): ret, frame cap.read() if not ret: break # 转换为灰度图像 gray cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 检测人脸 faces face_cascade.detectMultiScale(gray, 1.3, 5) # 绘制矩形框标记人脸 for (x,y,w,h) in faces: cv2.rectangle(frame,(x,y),(xw,yh),(255,0,0),2) cv2.imshow(Face Detection, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows() face_detection()这个简单的程序可以实时检测画面中的人脸并用蓝色矩形框标记出来。在实际项目中你可以进一步统计画面中人脸数量计算人脸在画面中的位置添加简单的跟踪功能3. 运动物体检测与追踪除了人脸检测运动物体检测也是计算机视觉的常见应用。我们可以使用背景减除算法来实现这一功能。3.1 背景减除算法原理背景减除是通过比较当前帧与背景模型的差异来检测运动物体。OpenCV提供了几种背景减除算法算法名称特点适用场景MOG2高斯混合模型自适应背景动态背景KNN基于K最近邻的背景减除光照变化场景GMG几何多网格背景减除初始化时间较长但结果精确3.2 实现运动检测import cv2 import numpy as np def motion_detection(): # 创建背景减除器 fgbg cv2.createBackgroundSubtractorMOG2(history500, varThreshold16, detectShadowsTrue) cap cv2.VideoCapture(nvarguscamerasrc ! video/x-raw(memory:NVMM), width1280, height720, formatNV12, framerate30/1 ! nvvidconv ! video/x-raw, formatBGRx ! videoconvert ! video/x-raw, formatBGR ! appsink, cv2.CAP_GSTREAMER) while cap.isOpened(): ret, frame cap.read() if not ret: break # 应用背景减除 fgmask fgbg.apply(frame) # 去除噪声 kernel np.ones((5,5), np.uint8) fgmask cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel) # 寻找轮廓 contours, _ cv2.findContours(fgmask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 绘制运动物体 for contour in contours: if cv2.contourArea(contour) 500: # 忽略小面积区域 continue (x, y, w, h) cv2.boundingRect(contour) cv2.rectangle(frame, (x, y), (xw, yh), (0, 255, 0), 2) cv2.imshow(Original, frame) cv2.imshow(Motion Detection, fgmask) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows() motion_detection()这段代码会显示两个窗口原始画面和运动检测结果。运动物体会被绿色矩形框标记出来。4. 智能拍照与图像处理现在我们来实现一个更实用的功能当检测到人脸时自动拍照并保存同时对照片进行一些基本的图像处理。4.1 实现智能拍照import cv2 import os from datetime import datetime def smart_capture(): face_cascade cv2.CascadeClassifier(haarcascade_frontalface_default.xml) cap cv2.VideoCapture(nvarguscamerasrc ! video/x-raw(memory:NVMM), width1280, height720, formatNV12, framerate30/1 ! nvvidconv ! video/x-raw, formatBGRx ! videoconvert ! video/x-raw, formatBGR ! appsink, cv2.CAP_GSTREAMER) # 创建保存目录 save_dir captured_images os.makedirs(save_dir, exist_okTrue) last_capture_time 0 while cap.isOpened(): ret, frame cap.read() if not ret: break gray cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces face_cascade.detectMultiScale(gray, 1.3, 5) current_time datetime.now().timestamp() # 如果检测到人脸且距离上次拍照超过5秒 if len(faces) 0 and current_time - last_capture_time 5: filename f{save_dir}/{datetime.now().strftime(%Y%m%d_%H%M%S)}.jpg # 对图像进行处理 processed image_processing(frame) cv2.imwrite(filename, processed) print(f照片已保存: {filename}) last_capture_time current_time # 显示实时画面 for (x,y,w,h) in faces: cv2.rectangle(frame,(x,y),(xw,yh),(255,0,0),2) cv2.imshow(Smart Capture, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows() def image_processing(img): 对图像进行处理 # 转换为灰度图 gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 边缘检测 edges cv2.Canny(gray, 100, 200) # 将边缘检测结果叠加到原图 edges_colored cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR) result cv2.addWeighted(img, 0.7, edges_colored, 0.3, 0) return result smart_capture()这个程序会在检测到人脸时自动拍照间隔至少5秒并对照片进行边缘增强处理后再保存。5. 进阶项目简单的人数统计系统结合前面学到的知识我们可以构建一个简单的人数统计系统。这个系统可以统计画面中出现的人数并在人进入或离开时发出通知。5.1 系统设计思路使用背景减除检测运动物体对检测到的运动区域进行形态学处理使用轮廓分析确定人数跟踪人员进出状态5.2 实现代码import cv2 import numpy as np class PeopleCounter: def __init__(self): self.fgbg cv2.createBackgroundSubtractorMOG2(history500, varThreshold16, detectShadowsTrue) self.kernel np.ones((5,5), np.uint8) self.people_count 0 self.min_contour_area 1000 # 最小轮廓面积用于过滤噪声 def process_frame(self, frame): # 背景减除 fgmask self.fgbg.apply(frame) # 形态学处理 fgmask cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, self.kernel) fgmask cv2.dilate(fgmask, self.kernel, iterations2) # 寻找轮廓 contours, _ cv2.findContours(fgmask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 统计有效轮廓数量 current_count 0 for contour in contours: if cv2.contourArea(contour) self.min_contour_area: continue current_count 1 (x, y, w, h) cv2.boundingRect(contour) cv2.rectangle(frame, (x, y), (xw, yh), (0, 255, 0), 2) # 检测人数变化 if current_count self.people_count: print(f有人进入当前人数: {current_count}) elif current_count self.people_count: print(f有人离开当前人数: {current_count}) self.people_count current_count # 显示人数 cv2.putText(frame, fPeople: {self.people_count}, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2) return frame def people_counting(): counter PeopleCounter() cap cv2.VideoCapture(nvarguscamerasrc ! video/x-raw(memory:NVMM), width1280, height720, formatNV12, framerate30/1 ! nvvidconv ! video/x-raw, formatBGRx ! videoconvert ! video/x-raw, formatBGR ! appsink, cv2.CAP_GSTREAMER) while cap.isOpened(): ret, frame cap.read() if not ret: break processed_frame counter.process_frame(frame) cv2.imshow(People Counting, processed_frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows() people_counting()这个简单的计数系统会在终端输出人员进出情况并在画面上显示当前人数。在实际应用中你可以添加更精确的人员检测算法实现区域计数如只统计特定区域的人数将数据上传到服务器进行进一步分析