OpenCV4【14】实例 提取特定区域

源图像

目标是 提取 四个 大圈圈 ;

具体项目描述见 参考资料

实现过程

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提取特定区域

原文地址:https://www.cnblogs.com/yanshw/p/15500078.html