基于python的opencv项目实战P7

本文深入探讨了使用OpenCV进行图像处理的两个关键概念:图像金字塔和轮廓检测。介绍了高斯金字塔的向下采样、向上采样以及拉普拉斯金字塔的构建。同时详细讲解了如何使用`cv2.findContours`进行轮廓检测,包括不同的轮廓检索模式和轮廓逼近方法。此外,还涵盖了轮廓的绘制、轮廓特征提取,如边界矩形和外接圆。最后提到了模板匹配的不同方法及其应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

07 图像金字塔与轮廓检测

import cv2
import matplotlib.pyplot as plt
import numpy as np
get_ipython().run_line_magic('matplotlib','inline')


def cv_show(img,name):
    cv2.imshow(name,img)
    cv2.waitKey()
    cv2.destroyAllWindows()

高斯金字塔:
向下采样,缩小,提取特征
将Gi与高斯内和卷积,将所有偶数行列去除。
向上采样,扩大

img = cv2.imread('AM.png')cv_show(img,'img')print (img.shape)


#上采样1次
up = cv2.pyrUp(img)
cv_show(up,'up')
print (up.shape)


#下采样
down = cv2.pyrDown(img)
cv_show(down,'down')
print (down.shape)


#上采样2次
up2 = cv2.pyrUp(up)
cv_show(up2,'up2')
print (up2.shape)


#先上采样再下采样
up = cv2.pyrUp(img)
up_down = cv2.pyrDown(up)
cv_show(up_down,'up_down')


#对比原图、先上采样再下采样的组合图
cv_show(np.hstack((img,up_down)),'up_down')


up = cv2.pyrUp(img)
up_down = cv2.pyrDown(up)
cv_show(img-up_down,'img-up_down')

拉普拉斯金字塔

Li=Gi-PyrUp(PyrDown(Gi))

轮廓检测

cv2.findContours(img,mode,method)

mode:轮廓检索模式
•RETR_EXTERNAL:只检索最外侧的轮廓
•RETR_LIST:检索所有轮廓并保存到一条链表
•RETR_CCOMP:检索所有轮廓并将他们组织为两层:顶层是各部分的外界边界,第他们组织为两层:顶层是各部分的外界边界,第二层是空洞的边界
•RETR_TREE:检索所有轮廓,并重构嵌套轮廓的整个层次

method:轮廓逼近方法
•CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方式输出多边形(顶点的序列)。
•CHAIN_APPROX_SIMPLE:压缩水平垂直和斜的部分,函数只保留他们的终点部分。

#图像预处理img = cv2.imread('contours.jpg')gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)cv_show(thresh,'thresh')


contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)

绘制轮廓

cv_show(img,'img')


#传入绘制图像,轮廓,轮廓索引,颜色模式,线条厚度,注意copy


#-1所有轮廓  (0,0,255)BGR 2线条宽度
draw_img = img.copy()
res = cv2.drawContours(draw_img,contours,-1,(0,0,255),4)
cv_show(res,'res')

轮廓特征

cnt = contours[0]


#面积
cv2.contourArea(cnt)


#周长,True表示闭合的
cv2.arcLength(cnt,True)

轮廓近似

img = cv2.imread('contours2.png')gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)cnt = contours[0]draw_img = img.copy()res = cv2.drawContours(draw_img,[cnt],-1,(0,0,255),2)cv_show(res,'res')



epsilon = 0.01*cv2.arcLength(cnt,True)#0.1粗糙
approx = cv2.approxPolyDP(cnt,epsilon,True)


draw_img = img.copy()
res = cv2.drawContours(draw_img,[approx],-1,(0,0,255),2)
cv_show(res,'res')

边界矩形

img = cv2.imread('contours.jpg')gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)cnt = contours[2]x,y,w,h = cv2.boundingRect(cnt)img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)cv_show(img,'img')


area = cv2.contourArea(cnt)
x,y,w,h = cv2.boundingRect(cnt)
rect_area = w*h
extent = float(area)/ rect_area
print('轮廓面积与边界矩形',extent)

外接圆

(x,y),radius = cv2.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
img = cv2.circle(img,center,radius,(0,255,0),2)
cv_show(img,'img')

模板匹配

•TM_SQDIFF:计算平方不同,计算出来值越小,越相关
•TM_CCORR:计算相关性,计算出来值越大,越相关
•TM_CCOEFF:计算相关系数,计算出来值越大,越相关
•TM_SQDIFF_NORMED:计算归一化平方不同,越接近0,越相关
•TM_CCORR_NORMED:计算归一化相关性,越接近1,越相关
•TM_CCOEFF_NORMED:计算归一化相关系数,越接近1,越相关

img = cv2.imread('lena.png',0)template = cv2.imread('face.png',0)h,w = template.shape[:2]


img.shape


template.shape


methods = ['cv2.TM_CCOEFF','cv2.TM_CCOEFF_NORMED','cv2.TM_CCORR',
           'cv2.TM_CCORR_NORMED','cv2.TM_SQDIFF','cv2.TM_SQDIFF_NORMED']


res = cv2.matchTemplate(img,template,1)#1可以变为cv2.TM_CCOEFF
res.shape


min_val,max_val,min_loc,max_loc = cv2.minMaxLoc(res)


min_val


max_val


min_loc#最小值位置左上点


max_loc


for meth in methods:
    img2 = img.copy()
    
    #匹配方法的真值
    method = eval(meth)
    print(method)
    res = cv2.matchTemplate(img,template,method)
    min_val,min_val,min_loc,max_loc = cv2.minMaxLoc(res)
    
    #如果平方差匹配TM_SQDIFF或归一化平方差匹配TM_SQDIFF_NORMED,取最小值
    if method in [cv2.TM_SQDIFF,cv2.TM_SQDIFF_NORMED]:
        top_left = min_loc
    else:
        top_left = max_loc
    bottom_right = (top_left[0] + w,top_left[1] + h)
    
    #画矩形
    cv2.rectangle(img2,top_left,bottom_right,255,2)
    
    plt.subplot(121),plt.imshow(res,cmap='gray')
    plt.xticks([]),plt.yticks([])#隐藏坐标轴
    plt.subplot(122),plt.imshow(img2,cmap='gray')
    plt.xticks([]),plt.yticks([])#隐藏坐标轴
    plt.suptitle(meth)
    plt.show()

匹配多个

img_rgb = cv2.imread('mario.png')
img_gray = cv2.cvtColor(img_rgb,cv2.COLOR_BGR2GRAY)
template = cv2.imread('mario_coin.png',0)
h,w = template.shape[:2]


res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.8
#取匹配程度大于百分之八十的坐标
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):#*表示可选参数
    bottom_right = (pt[0] + w,pt[1] + h)
    cv2.rectangle(img_rgb,pt,bottom_right,(0,0,255),2)


cv2.imshow('img_rgb',img_rgb)
cv2.waitKey(0)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值