OpenCv学习笔记4(形状与结构分析:轮廓检测,轮廓匹配)

从二值图像提取形状信息有助于对图像进行更高级的处理和识别。下面介绍如何使用findContours()搜索图像中的轮廓,并对其进行处理和计算。

轮廓检测在这里插入图片描述

输出参数:image,contours轮廓的多边形列表, hierarchy轮廓的嵌套信息

fig, axes = pl.subplots(1, 2, figsize=(10, 6))
img = cv2.imread("E:/ruanjianDM/jupyternoerbookDM/picture/xyz.jpg")

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
binary=cv2.Canny(gray,100,100)
#ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
#检测轮廓
image,contours, hierarchy = cv2.findContours(binary,mode=cv2.RETR_TREE,method=cv2.CHAIN_APPROX_SIMPLE)
#画出轮廓
cv2.drawContours(img,contours,-1,(0,255,0),3)
axes[0].imshow(binary,cmap='binary')
axes[1].imshow(img[:,:,::-1])

在这里插入图片描述

轮廓匹配

通过findContours()获取轮廓之后,可以使用approxPolyDP()对其进行简化,然后通过matchShapes()比较两个简化之后的轮廓之间的近似程度。

"要从patterns.png图像中找到与targets.png中最匹配的轮廓"
#首先获取图像的轮廓信息
img_patterns = cv2.imread("E:/ruanjianDM/jupyternoerbookDM/picture/patterns.png", cv2.IMREAD_GRAYSCALE)
_,patterns, _ = cv2.findContours(img_patterns, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

img_targets = cv2.imread("E:/ruanjianDM/jupyternoerbookDM/picture/targets.png", cv2.IMREAD_GRAYSCALE)
_,targets, _ = cv2.findContours(img_targets, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
#并将所有轮廓的坐标最小值都修改为0
patterns = [pattern - np.min(pattern, 0, keepdims=True) for pattern in patterns] 
targets = [target - np.min(target, 0, keepdims=True) for target in targets]
#然后调用approxPolyDP()对轮廓进行近似处理。它的第二个参数为近似的误差允许范围,
#该值越大,近似之后的轮廓的点数越少。第三个参数指示轮廓是否为封闭形状。
patterns_simple = [cv2.approxPolyDP(pattern, 5, True) for pattern in patterns] 
targets_simple = [cv2.approxPolyDP(target, 8, True) for target in targets]


#%figonly=使用`matchShapes()`比较由`approxPolyDP()`近似之后的轮廓
fig, ax = pl.subplots(figsize=(8, 8))
ax.set_aspect("equal")
width = 180
for tidx, (target, target_simple) in enumerate(zip(targets, targets_simple)): 
    scores = []
    texts = []
    for pidx, (pattern, pattern_simple) in enumerate(zip(patterns, patterns_simple)):
        index = np.s_[:, 0, :]
        pattern2 = pattern[index]
        target2 = target[index]
        pattern_simple2 = pattern_simple[index]
        target_simple2 = target_simple[index]
        
        x0 = pidx * width + width
        y0 = tidx * width + width
        
        if tidx == 0:
            pattern_poly = pl.Polygon(pattern2 + [x0, 0], color="black", alpha=0.6)
            ax.add_patch(pattern_poly)
            text = ax.text(x0 + width * 0.3, -50, str(pidx), fontsize=14, ha="center")
        if pidx == 0:
            target_poly = pl.Polygon(target2 + [0, y0], color="green", alpha=0.6)
            ax.add_patch(target_poly)
            text = ax.text(-50, y0 + width * 0.3, str(tidx), fontsize=14, ha="center")

        pattern_simple_poly = pl.Polygon(pattern_simple2 + [x0, 0], facecolor="none", alpha=0.6)
        ax.add_patch(pattern_simple_poly)
        target_simple_poly = pl.Polygon(target_simple2 + [0, y0], facecolor="none", alpha=0.6)
        ax.add_patch(target_simple_poly)
        #比较两个形状的近似程度
        score = cv2.matchShapes(target_simple, pattern_simple, 3, 0)
        text = ax.text(x0 + width * 0.3, y0 + width * 0.2, "{:5.4f}".format(score), 
                ha="center", va="center", fontsize=16)
        scores.append(score)
        texts.append(text)
    best_index = np.argmin(scores)
    texts[best_index].set_color("red")
ax.relim()
ax.set_axis_off()
ax.autoscale();

在这里插入图片描述

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值