如何用OpenCV+Python+PiCamera识别两个绿色物体并统计像素
没问题,我来一步步帮你实现这个需求。咱们从PiCamera视频流的获取开始,到绿色物体识别、画框,再到像素统计,全程用Python+OpenCV搞定:
1. 确认依赖导入
虽然你说环境已经配置好,还是把需要用到的库列出来,确保导入没问题:
import cv2 import numpy as np from picamera import PiCamera from picamera.array import PiRGBArray import time
2. 初始化PiCamera并获取实时流
用PiRGBArray可以高效获取帧,避免实时流的延迟问题:
# 初始化相机参数 camera = PiCamera() camera.resolution = (640, 480) # 可根据需求调整分辨率,越低帧率越高 camera.framerate = 32 rawCapture = PiRGBArray(camera, size=(640, 480)) # 给相机留一点预热时间 time.sleep(0.1)
3. 绿色物体识别与矩形框绘制
核心是用HSV颜色空间筛选绿色(比RGB更抗光照干扰),然后检测轮廓、筛选目标:
步骤拆解:
- 将每一帧从BGR(OpenCV默认格式)转成HSV格式
- 设定绿色的HSV阈值,生成只保留绿色区域的掩码
- 对掩码做腐蚀+膨胀的形态学操作,去除小噪声
- 检测轮廓,筛选出面积较大的前2个目标(对应你要识别的两个绿色物体)
- 给每个目标绘制矩形框
整合到流循环的代码:
# 绿色的HSV初始阈值(可根据实际环境调整) lower_green = np.array([40, 40, 40]) upper_green = np.array([70, 255, 255]) # 遍历视频流的每一帧 for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True): # 获取当前帧的图像数据 image = frame.array # 1. 颜色筛选:转HSV格式,生成绿色掩码 hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) mask = cv2.inRange(hsv, lower_green, upper_green) # 2. 去除噪声:先腐蚀再膨胀,过滤掉小杂点 kernel = np.ones((5,5), np.uint8) mask = cv2.erode(mask, kernel, iterations=1) mask = cv2.dilate(mask, kernel, iterations=2) # 3. 检测轮廓 contours, _ = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 按轮廓面积从大到小排序,取前2个(确保是两个最大的绿色物体) contours = sorted(contours, key=cv2.contourArea, reverse=True)[:2] # 4. 绘制矩形框 for cnt in contours: # 过滤掉极小的轮廓(避免噪声被误识别) if cv2.contourArea(cnt) > 100: x, y, w, h = cv2.boundingRect(cnt) # 画绿色矩形框,线宽为2 cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
4. 统计彩色像素与黑色像素数量
这里的黑色像素指三通道数值都为0的纯黑色像素,彩色像素是总像素数减去黑色像素数:
# 计算总像素数 total_pixels = image.shape[0] * image.shape[1] # 统计纯黑色像素(三通道都为0) black_pixels = np.sum((image[:, :, 0] == 0) & (image[:, :, 1] == 0) & (image[:, :, 2] == 0)) # 彩色像素=总像素-黑色像素 color_pixels = total_pixels - black_pixels # 把统计结果显示在画面左上角 cv2.putText(image, f"Color Pixels: {color_pixels}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2) cv2.putText(image, f"Black Pixels: {black_pixels}", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
5. 显示画面与退出逻辑
最后把处理后的画面显示出来,按q键可以退出循环:
# 显示处理后的实时画面 cv2.imshow("PiCamera Stream", image) # 清空缓存,准备接收下一帧 rawCapture.truncate(0) # 按q键退出循环 key = cv2.waitKey(1) & 0xFF if key == ord("q"): break # 释放所有资源 cv2.destroyAllWindows() camera.close()
关键优化提示
- 调整绿色阈值:如果识别不准,你可以用这个小工具实时调整HSV参数,拖动滑块直到掩码只显示绿色物体,再把数值替换到代码里:
# HSV阈值调参工具 def adjust_hsv(): def nothing(x): pass cv2.namedWindow("Trackbars") cv2.createTrackbar("L-H", "Trackbars", 40, 179, nothing) cv2.createTrackbar("L-S", "Trackbars", 40, 255, nothing) cv2.createTrackbar("L-V", "Trackbars", 40, 255, nothing) cv2.createTrackbar("U-H", "Trackbars", 70, 179, nothing) cv2.createTrackbar("U-S", "Trackbars", 255, 255, nothing) cv2.createTrackbar("U-V", "Trackbars", 255, 255, nothing) while True: frame = next(camera.capture_continuous(rawCapture, format="bgr", use_video_port=True)).array hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # 获取滑块当前值 l_h = cv2.getTrackbarPos("L-H", "Trackbars") l_s = cv2.getTrackbarPos("L-S", "Trackbars") l_v = cv2.getTrackbarPos("L-V", "Trackbars") u_h = cv2.getTrackbarPos("U-H", "Trackbars") u_s = cv2.getTrackbarPos("U-S", "Trackbars") u_v = cv2.getTrackbarPos("U-V", "Trackbars") lower = np.array([l_h, l_s, l_v]) upper = np.array([u_h, u_s, u_v]) mask = cv2.inRange(hsv, lower, upper) cv2.imshow("Frame", frame) cv2.imshow("Mask", mask) rawCapture.truncate(0) if cv2.waitKey(1) & 0xFF == ord("q"): break cv2.destroyAllWindows()
- 提升帧率:如果画面卡顿,可以降低相机分辨率,或者减少形态学操作的迭代次数。
内容的提问来源于stack exchange,提问作者J Dow
相关产品推荐
相关产品推荐

