Opencv学习笔记——直方图与模板匹配


一、直方图

直方图是像素点数值分布的统计图形表示,也就是每个点出现的个数,它让我们能够理解数据的密度估计和概率分布。
在这里插入图片描述

cv2.calcHist(images,channels,mask,histSize,ranges)

images: 原图像图像格式为 uint8 或 float32。当传入函数时需要用中括号 [] 括来例如[img]
channels: 同样用中括号括来它会告函数我们统幅图 像的直方图。如果输入图像是灰度图它的值就是 [0]如果是彩色图像 的传入的参数可以是 [0][1][2] 它们分别对应着 BGR。
mask: 掩模图像。统计整幅图像的直方图就把它为 None。但是如 果你想统计图像某一分的直方图的你就制作一个掩模图像并 使用它。
histSize:BIN 的数目。也应用中括号括来,比如[256]
ranges: 像素值范围常为 [0-256]

1.画直方图

import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
def cv_show(img,name):
    cv2.imshow(name,img)
    cv2.waitKey()
    cv2.destroyAllWindows()
img = cv2.imread('D:/cat2.jpg',0) #0表示灰度图
hist = cv2.calcHist([img],[0],None,[256],[0,256])
plt.hist(img.ravel(),256);
plt.show()

效果:
在这里插入图片描述

2.mask的使用

用mask对图像上某些区域作屏蔽,使其不参加处理或不参加处理参数的计算,或仅对屏蔽区作处理或统计。
使用mask:

import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
def cv_show(img,name):
    cv2.imshow(name,img)
    cv2.waitKey()
    cv2.destroyAllWindows()
img = cv2.imread('D:/cat2.jpg',0) #0表示灰度图
# 创建mast
mask = np.zeros(img.shape[:2], np.uint8)
print (mask.shape)
mask[100:200, 100:300] = 255#mask[起始点横坐标,起始点纵坐标]=255,255为白色,也就是需要保留的地方
masked_img = cv2.bitwise_and(img, img,mask=mask)#与操作
res=res = np.hstack((img,masked_img))#t图像拼接
cv_show(res,'res')

其中cv2.bitwise_and的参数
img:第一张输入图片
img: 第二张输入图片
mask:掩码图像
因为cv2.bitwise_and需要有两个输入图像,所以我们两个都是img
效果:在这里插入图片描述

3.直方图均值化

直方图均衡化是将原图像通过某种变换,得到一幅灰度直方图为均匀分布的新图像的方法。直方图均衡化方法的基本思想是对在图像中像素个数多的灰度级进行展宽,而对像素个数少的灰度级进行缩减。从而达到清晰图像的目的。
在这里插入图片描述
在这里插入图片描述

import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
def cv_show(img,name):
    cv2.imshow(name,img)
    cv2.waitKey()
    cv2.destroyAllWindows()
img = cv2.imread('D:/cat2.jpg',0) #0表示灰度图
equ = cv2.equalizeHist(img)
res = np.hstack((img,equ))
cv_show(res,'res')

效果:
在这里插入图片描述

4.自适应直方图均衡化

自适应直方图均衡化(用来提升图像的对比度的一种计算机图像处理技术。和普通的直方图均衡不同,AHE算法通过计算图像的局部直方图,然后重新分布亮度来改变图像对比度。因此,该算法更适合于改进图像的局部对比度以及获得更多的图像细节。
由于图片明暗分布的问题,对一张图片进行全局的直方图均衡化可能导致明部或者暗部的细节丢失。为了优化均衡化效果,我们对可以对不同区域进行直方图均衡化以获得更加合适的效果。

import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
def cv_show(img,name):
    cv2.imshow(name,img)
    cv2.waitKey()
    cv2.destroyAllWindows()
img = cv2.imread('D:/cat2.jpg',0) #0表示灰度图
equ = cv2.equalizeHist(img)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
res_clahe = clahe.apply(img)
res = np.hstack((img,res_clahe,equ))
cv_show(res,'res')

cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))其中clipLimit颜色对比度的阈值,titleGridSize进行像素均衡化的网格大小,即在多少网格下进行直方图的均衡化操作。
效果:
在这里插入图片描述
图二为自适应直方图均衡化后的图像,可以发现比图三保留了更多的细节。

二、模板匹配

1.匹配单个对象

模板匹配和卷积原理很像,模板在原图像上从原点开始滑动,计算模板与(图像被模板覆盖的地方)的差别程度,这个差别程度的计算方法在opencv里有6种,然后将每次计算的结果放入一个矩阵里,作为结果输出。假如原图形是AxB大小,而模板是axb大小,则输出结果的矩阵是(A-a+1)x(B-b+1)。模板匹配有六种方法,分别是:
TM_SQDIFF:计算平方不同,计算出来的值越小,越相关,公式为:
[R(x,y)= \sum _{x’,y’} (T(x’,y’)-I(x+x’,y+y’))^2]

TM_CCORR:计算相关性,计算出来的值越大,越相关,公式为:[R(x,y)= \sum _{x’,y’} (T(x’,y’) \cdot I(x+x’,y+y’))]

TM_CCOEFF:计算相关系数,计算出来的值越大,越相关,公式为:
[R(x,y)= \sum _{x’,y’} (T’(x’,y’) \cdot I’(x+x’,y+y’))]
where
[\begin{array}{l} T’(x’,y’)=T(x’,y’) - 1/(w \cdot h) \cdot \sum _{x’‘,y’‘} T(x’‘,y’‘) \ I’(x+x’,y+y’)=I(x+x’,y+y’) - 1/(w \cdot h) \cdot \sum _{x’‘,y’‘} I(x+x’‘,y+y’') \end{array}]

TM_SQDIFF_NORMED:计算归一化平方不同,计算出来的值越接近0,越相关,公式为:[R(x,y)= \frac{\sum_{x’,y’} (T(x’,y’)-I(x+x’,y+y’))2}{\sqrt{\sum_{x’,y’}T(x’,y’)2 \cdot \sum_{x’,y’} I(x+x’,y+y’)^2}}]

TM_CCORR_NORMED:计算归一化相关性,计算出来的值越接近1,越相关,公式为:[R(x,y)= \frac{\sum_{x’,y’} (T(x’,y’) \cdot I(x+x’,y+y’))}{\sqrt{\sum_{x’,y’}T(x’,y’)^2 \cdot \sum_{x’,y’} I(x+x’,y+y’)^2}}]

TM_CCOEFF_NORMED:计算归一化相关系数,计算出来的值越接近1,越相关,公式为:[R(x,y)= \frac{ \sum_{x’,y’} (T’(x’,y’) \cdot I’(x+x’,y+y’)) }{ \sqrt{\sum_{x’,y’}T’(x’,y’)^2 \cdot \sum_{x’,y’} I’(x+x’,y+y’)^2} }]

代码:

import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
def cv_show(img,name):
    cv2.imshow(name,img)
    cv2.waitKey()
    cv2.destroyAllWindows()
img = cv2.imread('D:/renxiang.jpg') #0表示灰度图
img2=img[20:150,150:300]#截取人脸
img3 = img.copy()
h, w = img2.shape[:2]#人脸的长和高
res = cv2.matchTemplate(img, img2, cv2.TM_SQDIFF_NORMED)
# 如果是平方差匹配TM_SQDIFF或归一化平方差匹配TM_SQDIFF_NORMED,取最小值
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)#min_val最小值,max_val最大值,min_loc最小值坐标,max_loc最大值坐标
#起始点
top_left = min_loc
#终止点
bottom_right = (top_left[0] + w, top_left[1] + h)
#画框
cv2.rectangle(img3, top_left, bottom_right, (0,0,255), 2)
cv_show(img3,'img')

效果:
在这里插入图片描述

2.匹配多个对象

模板匹配匹配多个对象,相当与设置一个阈值,大于这个阈值我们就认为它是匹配的.
代码:

import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB

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

img = cv2.imread('D:/eryu.jpg') #0表示灰度图
img2 = img[60:200,50:180]#截取图像
img3 = img.copy()
h, w = img2.shape[:2]#截取图像的长宽
#计算归一化相关系数,计算出来的值越接近1,越相关
res = cv2.matchTemplate(img, img2, cv2.TM_CCOEFF_NORMED)
#设置阈值为0.8
threshold = 0.8
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):  # *号表示可选参数
    bottom_right = (pt[0] + w, pt[1] + h)
    cv2.rectangle(img3, pt, bottom_right, (0, 0, 255), 1)
cv_show(img3,'img')

效果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Thousand_drive/article/details/124649604