如何用Python的OpenCV为图像中的红色区域绘制边界?
如何在OpenCV中为检测到的红色区域绘制边界?
我正在使用Python的OpenCV进行颜色检测,希望为图像中的红色区域绘制边界。以下是我的Python代码:
import cv2 import numpy as np cap = cv2.VideoCapture(0) while(1): _, frame = cap.read() frame=np.fliplr(frame) hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) lower_red = np.array([0,170,175]) upper_red = np.array([20,255,255]) mask = cv2.inRange(hsv, lower_red, upper_red) res = cv2.bitwise_and(frame,frame, mask= mask) kernel = np.ones((15,15),np.float32)/225 smoothed = cv2.filter2D(res,-1,kernel) cv2.imshow('Original',frame) cv2.imshow('Averaging',smoothed) _, puck = cv2.threshold(smoothed, 30, 255, cv2.THRESH_BINARY) cv2.imshow('Puck',puck) k = cv2.waitKey(5) & 0xFF if k == 27: break cv2.destroyAllWindows() cap.release()
目前我已成功识别出红色,但不清楚如何检测红色区域的位置并绘制边界,特此求助。
解决方案
要给检测到的红色区域绘制边界,核心是通过轮廓检测定位红色区域的轮廓,再基于轮廓绘制边界框或直接绘制轮廓。下面是具体步骤和修改后的代码:
关键步骤说明:
- 先将二值化后的
puck图像转为单通道灰度图,因为cv2.findContours需要单通道输入才能正确工作 - 提取轮廓后,过滤掉面积过小的轮廓,避免噪声被误识别为目标区域
- 遍历有效轮廓,用矩形框或直接绘制轮廓的方式标记红色区域
修改后的完整代码:
import cv2 import numpy as np cap = cv2.VideoCapture(0) while(1): _, frame = cap.read() frame = np.fliplr(frame) hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # 保留你原来的红色HSV检测范围 lower_red = np.array([0,170,175]) upper_red = np.array([20,255,255]) mask = cv2.inRange(hsv, lower_red, upper_red) res = cv2.bitwise_and(frame, frame, mask=mask) kernel = np.ones((15,15),np.float32)/225 smoothed = cv2.filter2D(res,-1,kernel) _, puck = cv2.threshold(smoothed, 30, 255, cv2.THRESH_BINARY) # 将3通道二值图转为单通道灰度图,满足轮廓检测的输入要求 gray_puck = cv2.cvtColor(puck, cv2.COLOR_BGR2GRAY) # 查找轮廓:只检测最外层轮廓,压缩轮廓点减少计算量 contours, _ = cv2.findContours(gray_puck, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 遍历所有轮廓,绘制边界框 for cnt in contours: # 过滤小面积轮廓,阈值可根据你的场景调整 if cv2.contourArea(cnt) > 500: # 获取轮廓的外接矩形坐标 x, y, w, h = cv2.boundingRect(cnt) # 在原图像上绘制绿色边界框(BGR格式,线宽2) cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2) # 若想直接绘制轮廓,可替换为下面这行: # cv2.drawContours(frame, [cnt], -1, (0,255,0), 2) # 显示带有边界框的原图像 cv2.imshow('Original with Bounding Box', frame) cv2.imshow('Averaging', smoothed) cv2.imshow('Puck', puck) k = cv2.waitKey(5) & 0xFF if k == 27: break cv2.destroyAllWindows() cap.release()
代码细节解释:
- 单通道转换:
puck是3通道的二值图像,必须转为灰度图才能让轮廓检测函数正常解析 - 轮廓参数选择:
cv2.RETR_EXTERNAL只提取最外层轮廓,避免嵌套轮廓干扰;cv2.CHAIN_APPROX_SIMPLE会压缩轮廓上的冗余点,提升运行效率 - 面积过滤:通过
cv2.contourArea计算轮廓面积,忽略小于500的区域,你可以根据实际拍摄场景调整这个阈值(比如目标更大就调大,更小就调小) - 边界绘制:
cv2.boundingRect快速获取轮廓的外接矩形,cv2.rectangle在原图像上绘制醒目的绿色框,方便观察检测结果
运行这段代码后,你就能在原画面中看到红色区域被绿色边界框标记出来了,多红色区域也能同时检测并绘制各自的边界。
内容的提问来源于stack exchange,提问作者Kaushal97
相关产品推荐
相关产品推荐

