在前几周的文章中已经介绍过如何在核桃派上用OpenCV读取图像并显示到pyqt5的窗口上,这里在上一篇文章的基础上,给开发板加入颜色检测功能,尝试将图像中所有蓝色的东西都用一个框标记出来。
颜色检测核心api
按照惯例,先要介绍一下opencv中常用的hsv像素格式。颜色还是那个颜色,只是描述颜色用的参数变了。h代表色调,s代表饱和度,v代表明度,比使用rgb格式更方便计算与思考。
opencv中也提供了将rgb bgr等转为hsv图片的api:
hsvImage = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
cv2.inRange,给定一个要检测的hsv颜色范围,返回一张黑白图。将hsv值在该范围内的像素点全部变为白色,不在的则为黑色。
import numpy as np hsv_upper=np.array([125, 250, 250]) hsv_lower=np.array([95, 40, 40]) grayImage = cv2.inRange(hsvImage, hsv_lower, hsv_upper) # 颜色二值化
findContours,传入黑白图像,寻找所有轮廓。返回两个列表,contours里是找到的所有轮廓,hierarchy是那些轮廓之间的相对位置关系
contours, hierarchy = cv2.findContours(grayImage, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
minAreaRect,传入一个轮廓,计算最小外接矩形
# 画最小外接矩形 for cts in contours : rect = cv2.minAreaRect(cts)
drawContours, 绘制轮廓
box = np.int0(cv2.boxPoints(rect)) cv2.drawContours(rgbImage, [box], 0, (255, 0, 0), 2)
基本测试代码
import cv2 from ui_main import Ui_MainWindow import numpy as np import PyQt5 from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * # 修正qt的plugin路径,因为某些程序(cv2)会将其改到其他路径 import os os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = os.path.dirname(PyQt5.__file__) #【可选代码】允许Thonny远程运行 import os os.environ["DISPLAY"] = ":0.0" #【建议代码】允许终端通过ctrl+c中断窗口,方便调试 import signal signal.signal(signal.SIGINT, signal.SIG_DFL) timer = QTimer() timer.start(100) # You may change this if you wish. timer.timeout.connect(lambda: None) # Let the interpreter run each 100 ms # 线程类 class Work(QThread): signal_update_label = pyqtSignal(QPixmap) label:QLabel def sloat_update_label( self, pixmap self.label.setPixmap(pixmap) def run(self): print("label.width()=", self.label.width()) print("label.height()=", self.label.height()) self.signal_update_label.connect(self.sloat_update_label) cap = cv2.VideoCapture(1) while True: ret, frame = cap.read() if ret: # 颜色转换 rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) hsvImage = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # 二值化 hsv_upper=np.array([125, 250, 250]) hsv_lower=np.array([95, 40, 40]) grayImage = cv2.inRange(hsvImage, hsv_lower, hsv_upper) # 颜色二值化 # 查找并绘制最小外接矩形 contours, hierarchy = cv2.findContours(grayImage, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) for cts in contours : rect = cv2.minAreaRect(cts) box = np.int0(cv2.boxPoints(rect)) cv2.drawContours(rgbImage, [box], 0, (255, 0, 0), 2)
由于摄像头拍出来的噪点很多,而物体由于本身材质反光导致拍出来也有一些部分的颜色变了。所以实际应用时需要对图像进行一些滤波模糊化处理。或是直接对生成后的黑白图像进行一定膨胀与收缩。
再把各个参数做成pyqt窗口的选项,查看各项搭配后的效果,快速找到合适的参数选择。
# 图像缩小并转换颜色格式 frame = cv2.resize(frame, (320, 240)) rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) h, w, ch = rgbImage.shape # 图像模糊 if self.blur.flag : rgbImage = cv2.blur(rgbImage,(self.blur.num, self.blur.num)) if self.median.flag : rgbImage = cv2.medianBlur(rgbImage,self.median.num) if self.gaussian.flag : rgbImage = cv2.GaussianBlur(rgbImage, (self.gaussian.num, self.gaussian.num), 0) # 二值化 hsvImage = cv2.cvtColor(rgbImage, cv2.COLOR_RGB2HSV) grayImage = cv2.inRange(hsvImage, np.array([self.hl.num, self.sl.num, self.vl.num]), np.array([self.hu.num, self.su.num, self.vu.num])) # 颜色二值化 # 图像操作 if self.dilate.flag : grayImage = cv2.dilate(grayImage, np.ones((self.dilate.num, self.dilate.num), dtype=np.uint8), 1) # 膨胀 if self.erode.flag : grayImage = cv2.erode(grayImage, np.ones((self.erode.num, self.erode.num), dtype=np.uint8), 1) # 腐蚀 # 获取中心点的颜色,画上十字光标 height, width = rgbImage.shape[:2] center_y, center_x = height // 2, width // 2 color = tuple(map(int, rgbImage[center_y, center_x, :])) cv2.line(rgbImage, (center_x, 0), (center_x, height-1), color, 3) cv2.line(rgbImage, (0, center_y), (width-1, center_y), color, 3) contours, hierarchy = cv2.findContours(grayImage, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
全部0条评论
快来发表一下你的评论吧 !