600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > OpenCV-Python 颜色识别(红色)并拟合矫正目标区域

OpenCV-Python 颜色识别(红色)并拟合矫正目标区域

时间:2020-05-06 10:21:58

相关推荐

OpenCV-Python 颜色识别(红色)并拟合矫正目标区域

OpenCV版本:4.6.0.66

算法实现思路:

颜色识别(红色)形态学去噪轮廓检测多边形拟合透视矫正

代码实现:

import cv2import numpy as np# 可视化def img_show(name, img):cv2.namedWindow(name, 0)cv2.resizeWindow(name, 1000, 500)cv2.imshow(name, img)cv2.waitKey(0)def color_warped(path):img = cv2.imread(path)hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)# 颜色识别(红色),过滤红色区域lower_red1 = np.array([0, 43, 46]) # 红色阈值下界higher_red1 = np.array([10, 255, 255]) # 红色阈值上界mask_red1 = cv2.inRange(hsv, lower_red1, higher_red1)lower_red2 = np.array([156, 43, 46]) # 红色阈值下界higher_red2 = np.array([180, 255, 255]) # 红色阈值上界mask_red2 = cv2.inRange(hsv, lower_red2, higher_red2)mask_red = cv2.add(mask_red1, mask_red2) # 拼接过滤后的maskimg_show('mask_red', mask_red)# 形态学去噪,cv2.MORPH_OPEN先腐蚀再膨胀,cv2.MORPH_CLOSE先膨胀再腐蚀kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))mask_red = cv2.morphologyEx(mask_red, cv2.MORPH_OPEN, kernel, iterations=1)kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7, 7))mask_red = cv2.morphologyEx(mask_red, cv2.MORPH_CLOSE, kernel, iterations=3)img_show('mask_red', mask_red)# 轮廓检测,找出线条的轮廓draw_cnt = img.copy()cnts = cv2.findContours(mask_red, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]cv2.drawContours(draw_cnt, cnts, -1, (0, 255, 0), 2)img_show('draw_cnt', draw_cnt)# 四边形拟合,找到相应的的顶点draw_approx = img.copy()point1, point2 = list(), list()for cnt in cnts:for epsilon in range(50):approx = cv2.approxPolyDP(cnt, epsilon, True)if len(approx) == 4:breakcv2.polylines(draw_approx, [approx], True, (0, 0, 255), 2) # 绘制边for i in approx:cv2.circle(draw_approx, i[0], 6, (0, 0, 0), -1) # 绘制顶点approx = [i[0] for i in approx.tolist()]approx = sorted(approx, key=lambda k: k[1], reverse=False) # 按y坐标排序,升序point1.extend(approx[:2]) # 存放上顶点坐标point2.extend(approx[2:]) # 存放下顶点坐标point1.sort(key=lambda k: k[0], reverse=False) # 按x坐标排序,升序point2.sort(key=lambda k: k[0], reverse=False)img_show('draw_approx', draw_approx)# 透视矫正目标区域w, h = 900, 300rect = [point1[0], point1[-1], point2[-1], point2[0]] # 顺序为第一个四边形的左上,第四个四边形的右上,第四个四边形的右下,第一个四边形的左下pts1 = np.array(rect, dtype="float32")pts2 = np.array([rect[0], [rect[0][0] + w, rect[0][1]],[rect[0][0] + w, rect[0][1] + h], [rect[0][0], rect[0][1] + h]], dtype="float32")M = cv2.getPerspectiveTransform(pts1, pts2) # 变换矩阵img_warped = cv2.warpPerspective(img, M, (1500, 500)) # 透视变换img_show('img_warped1', img_warped)img_warped = img_warped[rect[0][1]: rect[0][1] + h, rect[0][0]: rect[0][0] + w] # 抠出变换后的区域img_show('img_warped2', img_warped)if __name__ == '__main__':path = 'data/picture/18.jpg'color_warped(path)

原图:

颜色识别(红色)

img = cv2.imread(path)hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

颜色识别使用的通道是HSV通道。使用HSV通道识别颜色会比使用BGR通道更容易区分。H表示Hue(色调、色相,取值:0-180),S表示Saturation(饱和度、色彩纯净度,取值:0-255),V表示Value(亮度,取值:0-255),详情可见:HSV颜色空间。各颜色的取值范围如下:

可见红色的取值范围有两个,大部分情况下这两个范围刚好是互补的,可根据实际情况调整。

# 颜色识别(红色),过滤红色区域lower_red1 = np.array([0, 43, 46]) # 红色阈值下界higher_red1 = np.array([10, 255, 255]) # 红色阈值上界mask_red1 = cv2.inRange(hsv, lower_red1, higher_red1)lower_red2 = np.array([156, 43, 46]) # 红色阈值下界higher_red2 = np.array([180, 255, 255]) # 红色阈值上界mask_red2 = cv2.inRange(hsv, lower_red2, higher_red2)mask_red = cv2.add(mask_red1, mask_red2) # 拼接过滤后的mask

过滤出来的二值图如下:

形态学去噪

# 形态学去噪,cv2.MORPH_OPEN先腐蚀再膨胀,cv2.MORPH_CLOSE先膨胀再腐蚀kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))mask_red = cv2.morphologyEx(mask_red, cv2.MORPH_OPEN, kernel, iterations=1)kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7, 7))mask_red = cv2.morphologyEx(mask_red, cv2.MORPH_CLOSE, kernel, iterations=3)

颜色识别有时候会有部分噪声被一起识别,这时候可以用形态学进行去噪。在使用cv2.morphologyEx进行形态学去噪之前,需要由cv2.getStructuringElement先定义卷积核形状大小

cv2.getStructuringElement(shape, ksize)常用参数如下:

shape:核的形状,cv2.MORPH_RECT矩形),cv2.MORPH_CROSS十字形),cv2.MORPH_ELLIPSE椭圆形)ksize:核的大小,格式为(width, height)

cv2.morphologyEx(src, op, kernel, iterations)常用参数如下:

src:输入图像op:形态学操作的类型,cv2.MORPH_ERODE腐蚀),cv2.MORPH_DILATE膨胀),cv2.MORPH_OPEN开运算),cv2.MORPH_CLOSE闭运算),cv2.MORPH_GRADIENT梯度运算),cv2.MORPH_TOPHAT礼帽运算),cv2.MORPH_BLACKHAT黑帽运算),详情可见:形态学操作kernel:进行形态学操作的卷积核iterations:形态学操作迭代的次数,默认值为1

效果如下:

轮廓检测

# 轮廓检测,找出线条的轮廓draw_cnt = img.copy()cnts = cv2.findContours(mask_red, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]cv2.drawContours(draw_cnt, cnts, -1, (0, 255, 0), 2)

使用cv2.findContours(image, mode, method)检测轮廓,常用参数如下:

image:二值图mode:轮廓的检索模式method:轮廓的近似方法

使用cv2.drawContours绘制轮廓,效果如下:

近似多边形

# 四边形拟合,找到相应的的顶点draw_approx = img.copy()point1, point2 = list(), list()for cnt in cnts:for epsilon in range(50):approx = cv2.approxPolyDP(cnt, epsilon, True)if len(approx) == 4:breakcv2.polylines(draw_approx, [approx], True, (0, 0, 255), 2) # 绘制边for i in approx:cv2.circle(draw_approx, i[0], 6, (0, 0, 0), -1) # 绘制顶点

使用cv2.approxPolyDP(curve, epsilon, closed)近似多边形,常用参数如下:

curve:输入二维点集的数组epsilon:近似结果的精度。这是原曲线和其近似曲线之间的最大距离。epsilon越小,近似结果的折线形状越“接近”曲线。详情可见:近似多边形closed:TrueFalseTrue表示近似曲线是闭合的(第一个顶点与最后一个顶点相互连接),False表示近似曲线是不闭合

cv2.approxPolyDP返回近似多边形的顶点坐标,这里用范围内的值遍历epsilon精度,当返回的顶点坐标数量4时,即为四边形

对每个轮廓进行四边形拟合,使用cv2.polylinescv2.circle分别绘制顶点,效果如下:

四边形拟合完成后,对每个四边形的顶点进行排序

透视矫正

# 透视矫正目标区域w, h = 900, 300rect = [point1[0], point1[-1], point2[-1], point2[0]] # 顺序为第一个四边形的左上,第四个四边形的右上,第四个四边形的右下,第一个四边形的左下pts1 = np.array(rect, dtype="float32")pts2 = np.array([rect[0], [rect[0][0] + w, rect[0][1]],[rect[0][0] + w, rect[0][1] + h], [rect[0][0], rect[0][1] + h]], dtype="float32")M = cv2.getPerspectiveTransform(pts1, pts2) # 变换矩阵img_warped = cv2.warpPerspective(img, M, (1500, 500)) # 透视变换

使用cv2.warpPerspective进行透视变换之前,需要先由cv2.getPerspectiveTransform获取变换矩阵

cv2.getPerspectiveTransform(src, dst)常用参数如下:

src:变换前图像四边形顶点坐标数组),其中任意三点不共线dst:变换后图像四边形顶点坐标数组),其中任意三点不共线

这里输入变换前四边形的顶点坐标,分别为第一个四边形的左上坐标第四个四边形的右上坐标第四个四边形的右下坐标第一个四边形的左下坐标;输入变换后四边形的顶点坐标,是以第一个四边形的左上坐标延长宽和高。

cv2.getPerspectiveTransform(src, M, dsize)常用参数如下:

src:输入图像M:变换矩阵dsize:输出图像大小

变换效果如下:

img_warped = img_warped[rect[0][1]: rect[0][1] + h, rect[0][0]: rect[0][0] + w] # 抠出变换后的区域

将变换后的区域抠出来,效果如下:

参考链接

三分钟带你快速学习RGB、HSV和HSL颜色空间 - 知乎

第8章 形态学操作 -- 8.3 核函数 cv2.getStructuringElement()_Enzo 想砸电脑的博客-CSDN博客

Python +OpenCV CH9:形态学操作(morphologyEx扩展)_liguoxin1990的博客-CSDN博客

Python OpenCV approxPolyDP()函数

多边形逼近cv2.approxPolyDP和Douglas-Peucker算法_00000cj的博客-CSDN博客_多边形逼近算法

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。