前言:
现时各位老铁们对“opencv 采集卡”大致比较珍视,大家都需要知道一些“opencv 采集卡”的相关知识。那么小编也在网上网罗了一些有关“opencv 采集卡””的相关文章,希望小伙伴们能喜欢,兄弟们一起来了解一下吧!轮廓筛选
在《OpenCV轮廓绘制详解》中我们已经学习了如何绘制轮廓。接下来,如果想要计算检测到的轮廓的大小,可以使用基于图像矩的方法或使用 OpenCV 函数 cv2.contourArea() 来计算检测到的轮廓的大小,本节中,我们将首先根据每个检测到的轮廓大小对其进行排序,在实践中,某些小的轮廓可能是噪声导致的,可能需要对轮廓进行筛选。
我们首先在画布上绘制不同半径的圆,用于后续检测:
# 画布image = np.ones((300,700,3), dtype='uint8')# 绘制不同半径的圆cv2.circle(image, (20, 20), 8, (64, 128, 0), -1)cv2.circle(image, (60, 80), 25, (128, 255, 64), -1)cv2.circle(image, (100, 180), 50, (64, 255, 64), -1)cv2.circle(image, (200, 250), 45, (255, 128, 64), -1)cv2.circle(image, (300, 250), 30, (35, 128, 35), -1)cv2.circle(image, (380, 100), 15, (125, 255, 125), -1)cv2.circle(image, (600, 210), 55, (125, 125, 255), -1)cv2.circle(image, (450, 150), 60, (0, 255, 125), -1)cv2.circle(image, (330, 180), 20, (255, 125, 0), -1)cv2.circle(image, (500, 60), 35, (125, 255, 0), -1)cv2.circle(image, (200, 80), 65, (125, 64, 125), -1)cv2.circle(image, (620, 80), 48, (255, 200, 128), -1)cv2.circle(image, (400, 260), 28, (255, 255, 0), -1)
接下来,检测图中的轮廓:
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 阈值处理ret, thresh = cv2.threshold(gray_image, 50, 255, cv2.THRESH_BINARY)# 检测轮廓contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)# 打印检测到的轮廓数print("detected contours: '{}' ".format(len(contours)))
根据每个检测到的轮廓大小进行排序:
def sort_contours_size(cnts): """根据大小对轮廓进行排序""" cnts_sizes = [cv2.contourArea(contour) for contour in cnts] (cnts_sizes, cnts) = zip(*sorted(zip(cnts_sizes, cnts))) return cnts_sizes, cnts (contour_sizes, contours) = sort_contours_size(contours)
最后进行可视化:
for i, (size, contour) in enumerate(zip(contour_sizes, contours)): # 计算轮廓的矩 M = cv2.moments(contour) # 质心 cX = int(M['m10'] / M['m00']) cY = int(M['m01'] / M['m00']) # get_position_to_draw() 函数与上例相同 (x, y) = get_position_to_draw(str(i + 1), (cX, cY), cv2.FONT_HERSHEY_SIMPLEX, 2, 5) # 将排序结果置于形状的质心 cv2.putText(image, str(i + 1), (x, y), cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 255, 255), 5)# show_img_with_matplotlib() 函数与上例相同show_img_with_matplotlib(image, 'image', 1)show_img_with_matplotlib(image, "result", 2)plt.show()
程序运行结果如下所示:
轮廓识别
我们之前已经介绍过了 cv2.approxPolyDP(),它可以使用 Douglas Peucker 算法用较少的点来使一个轮廓逼近检测的轮廓。此函数中的一个关键参数是 epsilon,其用于设置近似精度。我们使用 cv2.approxPolyDP(),以便根据被抽取的轮廓中的检测到顶点的数量识别轮廓(例如,三角形,方形,矩形,五角形或六角形)。为了减少点数,给定某个轮廓,我们首先计算轮廓的边( perimeter )。基于边,建立 epsilon 参数, epsilon 参数计算如下:
epsilon = 0.03 * perimeter
如果该常数变大(例如,从 0.03 变为 0.1 ),则 epsilon 参数也会更大,近似精度将减小,这导致具有较少点的轮廓,并且导致顶点的缺失,对轮廓的识别也将不正确,因为它基于检测到的顶点的数量;另一方面,如果该常数较小(例如,从0.03 变为 0.001),则 epsilon 参数也将变小,因此,近似精度将增加,将产生具有更多点的近似轮廓,对轮廓的识别同样会出现错误,因为获得了虚假顶点。
# 构建测试图像image = np.ones((300,700,3), dtype='uint8')cv2.circle(image, (100, 80), 65, (64, 128, 0), -1)pts = np.array([[300, 10], [400, 150], [200, 150]], np.int32)pts = pts.reshape((-1, 1, 2))cv2.fillPoly(image, [pts], (64, 255, 64))cv2.rectangle(image, (450, 20),(650, 150),(125, 125, 255),-1)cv2.rectangle(image, (50, 180),(150, 280),(255, 125, 0),-1)pts = np.array([[365, 220], [320, 282], [247, 258], [247, 182], [320, 158]], np.int32)pts = pts.reshape((-1, 1, 2))cv2.fillPoly(image, [pts], (125, 64, 125))pts = np.array([[645, 220], [613, 276], [548, 276], [515, 220], [547, 164],[612, 164]], np.int32)pts = pts.reshape((-1, 1, 2))cv2.fillPoly(image, [pts], (255, 255, 0))gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)ret, thresh = cv2.threshold(gray_image, 50, 255, cv2.THRESH_BINARY)# 轮廓检测contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)image_contours = image.copy()image_recognition_shapes = image.copy()# 绘制所有检测的轮廓draw_contour_outline(image_contours, contours, (255, 255, 255), 4)def get_position_to_draw(text, point, font_face, font_scale, thickness): """获取图形坐标中心点""" text_size = cv2.getTextSize(text, font_face, font_scale, thickness)[0] text_x = point[0] - text_size[0] / 2 text_y = point[1] + text_size[1] / 2 return round(text_x), round(text_y)def detect_shape(contour): """形状识别""" # 计算轮廓的周长 perimeter = cv2.arcLength(contour, True) contour_approx = cv2.approxPolyDP(contour, 0.03 * perimeter, True) if len(contour_approx) == 3: detected_shape = 'triangle' elif len(contour_approx) == 4: x, y, width, height = cv2.boundingRect(contour_approx) aspect_ratio = float(width) / height if 0.90 < aspect_ratio < 1.10: detected_shape = "square" else: detected_shape = "rectangle" elif len(contour_approx) == 5: detected_shape = "pentagon" elif len(contour_approx) == 6: detected_shape = "hexagon" else: detected_shape = "circle" return detected_shape, contour_approxfor contour in contours: # 计算轮廓的矩 M = cv2.moments(contour) # 计算轮廓的质心 cX = int(M['m10'] / M['m00']) cY = int(M['m01'] / M['m00']) # 识别轮廓形状 shape, vertices = detect_shape(contour) # 绘制轮廓 draw_contour_points(image_contours, [vertices], (255, 255, 255)) # 将形状的名称置于形状的质心 (x, y) = get_position_to_draw(shape, (cX, cY), cv2.FONT_HERSHEY_SIMPLEX, 1.6, 3) cv2.putText(image_recognition_shapes, shape, (x+35, y), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 3)# 可视化show_img_with_matplotlib(image, "image", 1)show_img_with_matplotlib(cv2.cvtColor(thresh, cv2.COLOR_GRAY2BGR), "threshold = 100", 2)show_img_with_matplotlib(image_contours, "contours outline (after approximation)", 3)show_img_with_matplotlib(image_recognition_shapes, "contours recognition", 4)plt.show()相关链接:
OpenCV轮廓检测详解 - 掘金:
OpenCV图像矩详解 - 掘金:
OpenCV Hu不变矩详解 - 掘金:
OpenCV轮廓绘制详解 - 掘金:
作者:盼小辉丶
链接:
来源:稀土掘金
标签: #opencv 采集卡