opencv图像处理⑦

目录

图像金字塔

高斯金字塔

 拉普拉斯金字塔

 图像轮廓

 绘制轮廓

 轮廓特征

轮廓近似 

 边界矩形

外接圆 

 模板匹配

 匹配多个对象


图像金字塔

  • 高斯金字塔

高斯金字塔:向下采样方法(缩小)

 高斯金字塔:向上采样方法(放大)

 


img=cv2.imread("AM.png")

cv_show(img.'img')

print(img.shape)

(442,340,3)

up=cv2.pyrUp(img)  #pyr:金字塔,Up:上采样

cv_show(up,'up')

print(up.shape) 

(884,680,3) 

 变大了

down=cv2.pyrDown(img) #Down下采样

cv_show(down,'down')

print(down.shape) 

(221,170,3)

 变小了

 up2=cv2.pyrUp(up) #对上采样再次执行上采样

cv_show(up2,'up2')

print(down.shape)

(1768,1360,3) 

 图片过大,无法展示

up=cv2.pyrUp(img)

up_down=cv2.pyrDown(up)

cv_show(np.hstack((img,up_down)),'up_down') 

先执行上采样,再执行下采样,所得到的图形与之前的不相同,因为上采样中需要进行0填充,而下采样中又会丢失一些信息。 

 与原始图像相比,变的模糊了

 拉普拉斯金字塔

 Gi(img,原始图像)减去 先up后down的图像,每一层都是这样做

 

down=cv2.pyrDown(img)

down_up=cv2.pyrUp(down)

l_1=img-down_up

cv_show(l_1,'l_1')

 图像轮廓

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('car.png')

gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #转灰度图

ret,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY) #阈值,小于127取一个值,大于255取一个值

cv_show(thresh,'thresh')

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

 绘制轮廓

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

#注意需要copy,要不原图会变,会自动将修改信息保存在原图上

draw_img=img.copy()

res=cv2.drawContours(draw_img,contours,-1,(0,0,255),2)#-1是绘制所有轮廓,0.0.255是BGR,2是线条宽度

cv_show(res,'res') 

 轮廓特征

 算一些轮廓的特征的时候,需要指定某一个轮廓

 cnt=contours[0]

下面是计算一些轮廓的特征用到的 

#面积

cv2.contourArea(cnt) 

#周长

cv2.arcLength(cnt,True)#可以指定true或false,true表示是闭合的 

轮廓近似 

近似原理: AB为一条曲线,C为曲线上距离AB最远的点,C到AB的距离为d,当d小于一个阈值T时,可以近似成为一条直线。d大于T时,不可以用一条直线来近似,用两条直线AC和CB来近似,以此类推。

img=cv2.imread('contours2.png')

gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

ret,thresh=cv2.threshold(gray,127,255,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.1*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.png')

gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

ret,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)

cnt=contours[0]

d

x,y,w,h=cv2.boundingRect(cnt)

img=cv2.rectangle(img,(x,y),(x+y,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') 

 模板匹配

当前模板在原图中匹配位置,模板匹配和卷积原理很像,模板在原图像上从原点开始滑动,计算模板与(图像被模板覆盖的地方)的差别程度,这个差别程度的计算方法在opencv里有6种,然后将每次计算的结果放入一个矩阵里,作为结果输出。假设原图形是A×B大小,而模板是a×b大小,则输出结果的矩阵时(A-a+1)×(B-b+1)

匹配方式:从左到右,从上到下

公式:OpenCV: Object Detection

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

尽量使用归一化的结果 

 # 模板匹配
img = cv2.imread('lena.jpg', 0)
template = cv2.imread('face.jpg', 0)
h, w = template.shape[:2] 
img.shape
(263, 263)
template.shape
(110, 85)

 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, cv2.TM_SQDIFF)#模板匹配

res.shape 

(154,179) 

#最小值,最大值,最小值坐标位置,最大值坐标位置

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

min_val

39168.0

max_val

74403584.0

min_loc

(107, 89)

max_loc

(159, 62)

for meth in methods:
    img2 = img.copy()

    # 匹配方法的真值
    method = eval(meth)
    print (method)
    res = cv2.matchTemplate(img, template, method)
    min_val, max_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.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('mario_coin.jpg', 0)
h, w = template.shape[:2]

res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)#模板匹配
threshold = 0.8#指定阈值
# 取匹配程度大于%80的坐标
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)

 模板如下

 匹配结果如下

猜你喜欢

转载自blog.csdn.net/weixin_58176527/article/details/125170805