关于opencv的学习(三)

这次学习的是轮廓检测和模版匹配,由于一些问题,导致花费了大量的时间。(有可能是图像选择的问题)

轮廓检测:

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

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

首先第一步是引入图像:(为更高准确率,使用二值图像) 

img=cv2.imread('people.jpg')
print(img.shape)
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
print(thresh.shape)
binary,contours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)

然后接下来是绘制边框:

#传入绘制图像,轮廓,轮廓索引,颜色模式,线条厚度
#注意copy,要不原图会变
draw_ = img.copy()
res=cv2.drawContours(img,contours,-1,(0,0,255),2)      #2代表线条宽度,-1代表全部
cv_show('b',res)

res =cv2.drawContours(draw_,contours,0,(0,0,255),2)
cv_show('c',res)
#轮廓特征
cnt = contours[0]
#面积
s=cv2.contourArea(cnt)
#周长,Ture表示闭合
c=cv2.arcLength(cnt,True)

#轮廓近似:
epsilon = 0.1*cv2.arcLength(cnt,True)       #自己设置也可以,通常安装周长的百分比
approx = cv2.approxPolyDP(cnt,epsilon,True)

drwaContours(图像,轮廓索引,-1(表示全部的轮廓,其他数字代表对应的的轮廓),颜色,线条的厚度)

这是轮廓的完整的代码:

img=cv2.imread('people.jpg')
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
binary,contours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)

cnt = contours[0]
s=cv2.contourArea(cnt)
c=cv2.arcLength(cnt,True)

draw_ = img.copy()
res=cv2.drawContours(img,[cnt],-1,(0,0,255),2)


#图像轮廓近似
epsilon = 0.1*c
approx = cv2.approxPolyDP(cnt,epsilon,True)
draw_ = img.copy()
res=cv2.drawContours(draw_,[approx],-1,(0,0,255),2)

边界矩形:

在轮廓检测的基础上对轮廓进行框取:

#边界矩形
img=cv2.imread('people.jpg')
gray=cv2.cvtColor(img,cv2.COLOR_BGR2RGBA)
ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
cnt = contours[0]

x,y,w,h=cv2.boundingRect(cnt)         #B  G  R
img=cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)   #2代表线条宽度
cv_show('e',img)

 轮廓面积与边界矩形比值:(目前还不太清楚它有啥用)

rect_ =w * h
area = cv2.contourArea(cnt)
extent = float(area)/rect_        #轮廓面积与边界矩形比值
print(extent)

轮廓的学习中cv2.findContours(img.mode,method)此处一直报错,有的版本是两个值,有的是三个值,自己瞎鼓弄了好久才解决这个问题。

接着是模板匹配,单个匹配在结果的显示上一直有问题(可以用多个匹配来代替单个匹配)

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

一共6函数,下面的3个函数更可靠。

methods =['cv2.TM_SQDIFF','cv2.TM_CCORR','cv2.TM_CCOEFF','cv2.TM_SQDIFF_NORMED','cv2.TM_CCORR_NORMED','cv2.TM_CCOEFF_NORMED']
img = cv2.imread('people.jpg',0)
print(img.shape)
img1 = cv2.imread('people1.jpg',0)
cv_show('a',img1)
print(img1.shape)

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


    res=cv2.matchTemplate(img,img1,method)      #小值
    cv_show('a',res)
    print(res.shape)        #结果=A-a+1,B-b+1
    min_val ,max_val , min_joc,max_joc= cv2.minMaxLoc(res)
    #最小值,最大值,最小值坐标位置,最大值坐标位置




    #cv2.TM_SQDIFF  cv2.TM_SQDIFF_NORMED 取最小值
    if method in [cv2.TM_SQDIFF,cv2.TM_SQDIFF_NORMED]:
        top = min_joc
    else:
        top = max_joc
    tmp = cv2.imread('people1.jpg')
    h, w = tmp.shape[:2]
    bottom = (top[0]+w,top[1]+h)
    print('bottom')
    print(bottom)

    #画矩形
    cv2.rectangle(img1,top,bottom,255,2)
    plt.subplots(221)              #第一个参数代表子图的行数;第二个参数代表该行图像的列数; 第三个参数代表每行的第几个图像。
    plt.imshow(res,cmap='gray')
    plt.xticks([]),plt.yticks([])#隐藏坐标轴
    plt.subplots(222)
    plt.imshow(img2,cmap='gray')
    plt.xticks([]),plt.yticks([])
    plt.suptitle(meth)
    plt.show()

这是将6个函数放在一起,可以观察一下他们的差别。(我这里的结果不知道为什么一直有问题,于是我将多个匹配来代替单个匹配)

img = cv2.imread('people.jpg')
gary=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
tmp = cv2.imread('people1.jpg')
h,w=tmp.shape[:2]

res =cv2.matchTemplate(img,tmp,cv2.TM_CCOEFF_NORMED)
threshold =0.8
loc =np.where(res>=threshold)
for pt in zip(*loc[::-1]):    #*表示可选参数
    bottom =(pt[0]+w,pt[1]+h)
    cv2.rectangle(img,pt,bottom,(0,0,255),2)
cv2.imshow('sss',img)
cv2.waitKey(0)

接下来我继续去寻找出现问题的原因,(也可能只用多个结果匹配) 按照自己的节奏去完成暑假给自己定的目标。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值