赞
踩
在学习B站教学视频的时候记录的笔记
OpenCV+TensorFlow】迪哥带你做项目!深度学习+计算机视觉实战 纯实战教学 技能点加满
模板匹配和卷积原理很像,模板在原图像上从原点开始滑动,计算模板与(图像被模板覆盖的地方)的差别程度。这个差别程度的计算方法在opencv里有6种,然后将每次计算的结果放入一个矩阵里,作为结果输出。假如原图形是AxB大小,而模板是axb大小,则输出结果的矩阵是(A-a+1)x(B-b+1)
- #模板匹配
- img= cv2.imread('H:\Peronal\lena.jpg')
- template = cv2.imread('H:\Peronal\\face.png',0)
- h,w = template.shape[:2]
左侧小图为face.png右侧大图为lena.jpg.假设在lena.jpg图像上分割出几个区域,然后找出这几个区域中跟face最像的那个区域。大致思路如下:从A到I每一个与face进行一次匹配,直至找到最为匹配的那个区域完成查找工作(图中的分割示意等分)。
那么每个区域与face如何判断匹配?最简单是每一个像素进行匹配,例如,首先进行(0,0)这个像素点进行比较,数值相同即为匹配。然后再比较(0,1)如此循环直至face的全部像素点都计算一遍。
最终会返回一个匹配结果:
A B ... E ... I
0% 0%... 100% ... 0%
由于匹配方法的不同,结果也不同。但含义是一致的。
TM_SQDIFF :计算平方不同,计算出来的值越小越相关
TM_CCORR:计算相关性,计算出来的值越大越相关
TM_CCOEFF:计算相关系数,计算出来的值越大越相关
TM_SQDIFF_NORMED:计算归一化平方不同,计算出来的值越接近0越相关
TM_CCORR_NORMED:计算归一化相关性,计算出来的值越接近1越相关
TM_CCOEFF_NORMED:计算归一化相关系数,计算出来的值越接近1越相关
如图:
处理过程:
- template = cv2.cvtColor(template, cv2.COLOR_BGR2RGB)
- res = cv2.matchTemplate(img,template,1)
注意:template = cv2.cvtColor(template, cv2.COLOR_BGR2RGB)必须的,否则会报错。
res.shape
(110,85)
这个数值如何得来,参看之前的描述 假如原图形是AxB大小,而模板是axb大小,则输出结果的矩阵是(A-a+1)x(B-b+1)
滑动检测过程中有太多的结果,为了方便操作opencv提供了一个函数。
cv2.minMaxLoc(res)
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,max_val,min_loc,max_loc = cv2.minMaxLoc(res)
-
- #如果是平方差匹配TM_SQDIFF或者归一化平方差匹配,取最小值
- 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('H:\Peronal\mario.jpg')
- img_gray = cv2.cvtColor(img_rgb,cv2.COLOR_BGR2GRAY)
- template = cv2.imread('H:\Peronal\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)
一张图统计像素点的分布。如图:
把所有像素点,按照其值统计起来,统计某一个值有多少个点。右侧直方图按照
横坐标表示灰度值,纵坐标表示点个数的方式,形成的直方图。
cv2.calcHist(images,channels,mask,histSize,ranges)
images:元图像格式为unit8或uint16.当传入函数时硬用括号[]括起来例如:[img]
channels:同样用中括号括起来它会告诉函数我们统计图像的直方图。如果输入图像是灰度图,它的值就是[0]如果是彩色图像的传入参数可以是[0] [1] [2] 分别对应的BGR。
mask:掩模图像。统整幅图像的直方图就把它设置为None。但如果你想统图像的某一部分的直方图你就制作一个掩模图像并使用它。
histSize:BIN的数目,也应用中括号括起来。
ranges:像素值范围常为[0-256]
以cat.jpg为例代码如下:
- img = cv2.imread('H:\Peronal\cat.jpg',0) #0为灰度图
- hist = cv2.calcHist([img],[0],None,[256],[0,256])
- hist.shape
(256, 1)
- # 显示直方图
- plt.hist(img.ravel(),256)
- plt.show()
以彩色图方式绘制3个颜色直方图。
- img = cv2.imread('H:\Peronal\cat.jpg')
- color = ['b','g','r']
- for i,col in enumerate(color):
- histr = cv2.calcHist([img],[i],None,[256],[0,256])
- plt.plot(histr,color=col)
- plt.xlim([0,256])
从灰度直方图中可以直观看出,像素点比较集中的分布在270左右的位置。
mask操作
是以img的尺寸为例子,创建一个二维数组。np.uint8 : 数据类型
行100到300 列100到400区域内设置成255.代码如图:
- # 创建mask
- mask = np.zeros(img.shape[:2],np.uint8)
- mask[100:300,100:400] = 255
- cv_show(mask,'mask')
读取cat.jpg然后使用掩模mask与cat进行与操作。代码如下:
- img = cv2.imread('H:\Peronal\cat.jpg',0)
- masked_img = cv2.bitwise_and(img,img,mask=mask) # 与操作
- cv_show(masked_img,'masked_img')
- hist_full = cv2.calcHist([img],[0],None,[256],[0,256])
- hist_mask = cv2.calcHist([img],[0],mask,[256],[0,256])
- plt.subplot(221),plt.imshow(img,'gray')
- plt.subplot(222),plt.imshow(mask,'gray')
- plt.subplot(223),plt.imshow(masked_img,'gray')
- plt.subplot(224),plt.plot(hist_full),plt.plot(hist_mask)
- plt.xlim([0,256])
- plt.show()
左上为原始图像,右上为掩模,左下为与操作之后结果。右下为直方图。
直方图均衡化
左上来一张小狗的原始图像,右上为灰度直方图。从图上看出,灰度分布比较集中。那么如果把灰度值打散均匀分布一下,会产生什么样的影响呢?下方左中右就是处理后的效果。
- img = cv2.imread('H:\Peronal\cat.jpg',0)
- plt.hist(img.ravel(),256)
- plt.show()
均衡化代码如下:
- equ = cv2.equalizeHist(img)
- plt.hist(equ.ravel(),256)
- plt.show()
展示图像结果,代码如下:
- res = np.hstack((img,equ))
- cv_show(res,'res')
同样适用lena.jpg测试
使用clahe.jpg测试
右侧图像的石膏像面部细节丢失了很多。为了在均衡化的同时保留石膏像面部细节,设想是否可以在同一张图像上,分区域进行均衡化呢?如图:
自适应直方图均衡化
首先产生分隔代码如下:
clahe = cv2.createCLAHE(clipLimit=2.0,tileGridSize=(8,8))
将分隔应用到图像上,代码如下:
- res_clahe = clahe.apply(img)
- res = np.hstack((img,equ,res_clahe))
- cv_show(res,'res')
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。