目录
- 模版匹配
- 不同方法对比
- 一个模板匹配多个
- 直方图及直方图均衡化
- Mask操作
- 直方图均衡化
- 自适应直方图均衡化
模版匹配
公式
import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
%matplotlib inline
def cv_show(img,name):
cv2.imshow(name,img)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.waitKey(1)
# 模板匹配
img1 = cv2.imread('./汪学长的随堂资料/6/模板匹配/lena.jpg', 0)
template = cv2.imread('./汪学长的随堂资料/6/模板匹配/face.jpg', 0)
# 导入图片
img = cv2.imread('./汪学长的随堂资料/6/模板匹配/lena.jpg') # 读取原始图片,返回的img是一个包含图像所有像素值的NumPy数组,其中每个像素值都是一个BGR (Blue-Green-Red) 值的列表
imgTemp = cv2.imread('./汪学长的随堂资料/6/模板匹配/face.jpg') # 读取模板图片
# 执行模板匹配。cv2.matchTemplate函数的三个参数分别为:原始图片、模板图片、匹配算法
result = cv2.matchTemplate(img,imgTemp,cv2.TM_SQDIFF_NORMED)
print('result的形状: ', result.shape)
# 统计出数组的中最大值、最小值以及对应的索引
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(result) # minLoc: 这是矩形左上角的坐标,由cv2.minMaxLoc函数返回。
# 绘制矩形框
print('minLoc: ', minLoc)
cv2.rectangle(img,minLoc,(minLoc[ 0 ]+imgTemp.shape[ 1 ],minLoc[ 1 ]+imgTemp.shape[ 0 ]),(255,0,0),2)
cv_show(img, 'img')
注:shape[0]是高h,shape[1]是宽w,根据左上角的点和右下角的点来确定矩形
result的形状: (154, 179)
minLoc: (107, 89)
不同方法对比
# 模板匹配
img = cv2.imread('./汪学长的随堂资料/6/模板匹配/lena.jpg', 0)
template = cv2.imread('./汪学长的随堂资料/6/模板匹配/face.jpg', 0)
h, w = template.shape[:2]
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']
for meth in methods:
img2 = img.copy()
# 匹配方法的真值
method = eval(meth) # 'cv2.TM_CCOEFF' -> 0
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()
注:res结果中,白色或者黑色就是最大最小值也就是匹配的框
一个模板匹配多个
img_rgb = cv2.imread('./汪学长的随堂资料/6/模板匹配/mario.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('./汪学长的随堂资料/6/模板匹配/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)
cv_show(img_rgb, 'img_rgb')
直方图及直方图均衡化
import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
%matplotlib inline
def cv_show(img,name):
cv2.imshow(name,img)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.waitKey(1)
img = cv2.imread('./汪学长的随堂资料/6/模板匹配/cat.jpg',0) # 读取名为 'cat.jpg' 的图片,0 表示以灰度图模式打开图片
# 计算图片的直方图,输出是一个256x1的数组(hist),表示图片中每种像素值的数量。
# hist的大小是(256, 1),表示256个bins,每个bin对应一种灰度级别的像素数量。
hist = cv2.calcHist([img],[0],None,[256],[0,256])
hist.shape
下面这两行代码使用matplotlib库将计算得到的直方图进行绘制,256表示直方图分成256份。
# 使用matplotlib库的hist函数直接计算并绘制直方图。img.ravel()将图像的二维数组展平成一维数组,256表示直方图分成256份。
plt.hist(img.ravel(),256);
plt.show()
下面这部分代码读取了一张彩色图片,并对每个通道分别计算了直方图,然后用不同的颜色将这三个通道的直方图画出来。
img = cv2.imread('./汪学长的随堂资料/6/模板匹配/cat.jpg') # 再次读取图片,这次是彩色模式。
color = ('b','g','r') # 定义三种颜色,分别对应BGR三个通道。
for i,col in enumerate(color): # 对三个通道进行遍历,计算每个通道的直方图并绘制
histr = cv2.calcHist([img],[i],None,[256],[0,256])
plt.plot(histr,color = col)
plt.xlim([0,256])
Mask操作
# 创建mask
# 创建一个和原图同样大小的全零矩阵,作为掩模(mask),np.uint8是数据类型,表示8位无符号整数,范围0-255。
mask = np.zeros(img.shape[:2], np.uint8)
print(mask.shape)
mask[100:300, 100:400] = 255 # 将掩模的一部分设置为255,这部分将被用于计算直方图
cv_show(mask,'mask')
img = cv2.imread('./汪学长的随堂资料/6/模板匹配/cat.jpg', 0)
cv_show(img,'img')
# 这里进行了一个位运算,使用掩模与原图进行“与”操作,得到的结果就是原图中被掩模部分的内容,其他部分为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])
# 使用subplot在一个图中显示多个子图,包括原图,掩模,掩模后的图像以及两个直方图
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()
直方图均衡化
# 使用OpenCV的imread函数以灰度模式读取一张名为'clahe.jpg'的图片
img = cv2.imread('./汪学长的随堂资料/6/模板匹配/clahe.jpg',0)
# 通过调用matplotlib的hist方法对原始图像进行直方图统计,256表示将像素值分成256段进行统计
plt.hist(img.ravel(),256);
plt.show()
# 使用OpenCV的equalizeHist函数对原始图像进行全局直方图均衡化操作。
# 全局直方图均衡化是一种提高图像对比度的方法,它可以改善图像的亮度分布和增强图像的对比度
equ = cv2.equalizeHist(img)
plt.hist(equ.ravel(),256) # 对进行了全局直方图均衡化的图像进行直方图统计。
plt.show()
res = np.hstack((img,equ)) # 使用numpy的hstack函数,将原始图像和进行了全局直方图均衡化的图像进行水平拼接
cv_show(res,'res')
自适应直方图均衡化
# 这行代码是使用OpenCV的createCLAHE函数创建一个CLAHE对象。
# CLAHE(Contrast Limited Adaptive Histogram Equalization)即限制对比度的自适应直方图均衡化,它是全局直方图均衡化的改进版本。
# 与全局直方图均衡化不同,CLAHE是在图像的小块区域上进行直方图均衡化。
# clipLimit参数表示对比度的最大值,tileGridSize参数表示每个小块的大小。
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
res_clahe = clahe.apply(img) # 使用CLAHE对象的apply方法对原始图像进行CLAHE操作
res = np.hstack((img,equ,res_clahe)) # 将原始图像、全局直方图均衡化的图像、以及CLAHE处理后的图像进行水平拼接
cv_show(res,'res')