源图像
目标是 提取 四个 大圈圈 ;
具体项目描述见 参考资料
实现过程
import cv2 as cv import numpy as np img0 = cv.imread('imgs/640.webp') ########### 预处理 img = cv.cvtColor(img0, cv.COLOR_BGR2GRAY) # 灰度 ret, img2 = cv.threshold(img, 100, 255, cv.THRESH_BINARY) # 二值化 # counters, _ = cv.findContours(img2, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) # cv.drawContours(img, counters, -1, (255, 0, 0), 2) ########### 边缘检测 blur = cv.GaussianBlur(img, (5, 5), 0) # 高斯 canny = cv.Canny(blur, 50, 200) # 边缘检测前最好高斯一下 ########### 一系列的 图像形态处理 kernel1 = cv.getStructuringElement(cv.MORPH_RECT, (3, 3)) # 根据实际情况 框 可以大一点 img3 = cv.dilate(canny, kernel1, iterations=10) kernel2 = cv.getStructuringElement(cv.MORPH_RECT, (3, 3)) # 腐蚀 和 膨胀 保持一致,框 和 次数 img4 = cv.erode(img3, kernel2, iterations=10) ########### 轮廓检测 counters, _ = cv.findContours(img4, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) cv.drawContours(img0, counters, -1, (255, 0, 255), 2) # 红色框 ########### 轮廓 边界矩形分析 和 面积分析 areas = [] for ind, c in enumerate(counters): x, y, w, h = cv.boundingRect(c) # 边界矩形 if max((w, h)) / min((w, h)) > 1.5: continue # 明显不是正方形,那四个大圈圈的边界矩形应接近正方形 area = cv.contourArea(c) # 面积 areas.append([ind, area]) areas.sort(key=lambda x: x[1]) # 面积排序 areas = areas[-4:] # 最大的4个 print(areas) # 画出这4个轮廓看看,据此可调整 图像形态学处理 方式 for i in areas: cv.drawContours(img0, counters, i[0], (0, 255, 0), 4) # 绿色框 ########### 创建 mask black = np.ones(img0.shape, dtype=np.uint8) # 创建 黑板图 mask = cv.drawContours(black, [counters[i[0]] for i in areas], -1, (255, 255, 255), -1) # 四个轮廓用白色填充 ########### 图像位运算 img00 = cv.imread('imgs/640.webp') out = cv.bitwise_and(img00, black) cv.imshow('img', out) cv.waitKey(0)
实现过程分析
边缘检测,看到边缘有些噪声,需要一系列 膨胀(黑变白) 腐蚀(白变黑) 消除噪声
膨胀,因为上面的 毛刺 有些长,故 膨胀的框可以大一点
腐蚀,保持和膨胀一致
轮廓检测
根据轮廓属性 边界矩形、面积 筛选 轮廓,绿色是筛后的
创建掩码
位运算
参考资料:
https://mp.weixin.qq.com/s/cnt8_skGdZT5qpApMHUpzQ 基于OpenCV提取特定区域