定义:把图像按照分辨率大小组合成金字塔的形状,主要用于图像的多层级特征提取。
img=cv2.imread("AM.png")
cv2.imshow("img",img)
cv2.waitKey()
cv2.destroyAllWindows()
print(img.shape)
第一种:向下采样方法(金字塔从下往上走)——缩小
步骤:1、将原图像与高斯核模板进行卷积操作(先相乘再加在一起)。
2、将所有的偶数行核列去除掉。
up=cv2.pyrUp(img)
cv2.imshow("up",up)
cv2.waitKey()
cv2.destroyAllWindows()
print(up.shape)
第二种:向上采样方法(金字塔从上往下走)——放大
步骤:1、将图像在每个方向扩大为原来的两倍,新增的行和列以0填充。
2、使用先前同样的高斯核模板(乘以4)与放大后的图像卷积,获得近似值。
down=cv2.pyrDown(img)
cv2.imshow("down",down)
cv2.waitKey()
cv2.destroyAllWindows()
print(down.shape)
ps:如果对原图像先上采样再下采样,得到的结果比原图像会差一点,因为进行上采样是采用0进行填充放大的,再进行下采样会损失一些信息。
down=cv2.pyrDown(img)
down_up=cv2.pyrUp(down)
l_1=img-down_up
cv2.imshow("l_1",l_1)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.findContours(img,mode,method)
mode(轮廓检索模式): 1、RETR_EXTERNAL——只检索最外边的轮廓
2、RETR_LIST——检索所有的轮廓,并将其保存到一条链表上
3、RETR_CCOMP——检索所有的轮廓,并将其组织为两层,顶层是各部分的外部边界,第二层
是空洞的边界
4、RETR_TREE——检索所有的的轮廓,并重构嵌套轮廓的整个层次(最常用的模式)
method(轮廓逼近方法):1、CHAIN_APPROX_NONE——以FREEMAN链码的方式输出轮廓,所有
其他方法输出多边形(顶点的序列)
2、CHAIN_APPROX_SIMPLE——压缩水平的、垂直的和斜的的部分,函数
只保留它们的终点部分
ps:轮廓检测最好是二值化图像
img=cv2.imread("contour.png")
#转化为灰度图像
gray=cv2.cvtColor(img,cv2.BGR2GRAY)
#采用阈值处理转化为二值化图像
ret,thresh=cv2.Threshold(img,127,255,cv2.THRESH_BINARY)
cv2.imshow("thresh",thresh)
cv2.waitKey()
cv2.destroyAllWindows()
#轮廓检测(binary:二值化图像,contours:轮廓点信息,hierarchy:轮廓层级
binary,contours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
#绘制轮廓
draw_img=img.copy
#-1是指绘制全部轮廓,其他数字按照从左下开始检测部分轮廓,2是指绘制的线条宽度
res=cv2.drawContours(draw_img,contours,-1,(0,0,255),2)
cv2.imshow("res",res)
cv2.waitKey()
cv2.destroyAllWindows()
cnt=contours[0]#第0个轮廓
cv2.contourArea(cnt)#计算轮廓面积
cv2.arcLength(cnt,True)#计算轮廓周长,True表示闭合
以直代曲:设定一个阈值,如果两点间的曲线弯曲程度大于阈值则用直线代替,否则在中间再找一点,寻找两条直线代替。(类似于二分法)
epsilon=0.1*cv2.arcLength(cnt,True)
approx=cv2.approxPolyDP(cnt,epsilon,True)#近似函数,利用0.1倍周长作为阈值
draw_img=img.copy()
res=cv2.drawContours(draw_img,[approx],-1,(0,0,255),2)
cv2.imshow("res",res)
cv2.waitKey()
cv2.destroyAllWindows()
#边界矩形
x,y,w,h=cv2.boundingRect(cnt)
img=cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow("img",img)
cv2.waitKey()
cv2.destroyAllWindows()
#轮廓面积与边界矩形比
area=cv2.contourArea(cnt)
x,y,w,h=cv2.boundingRect(cnt)
rect_area=w*h
extent=float(area)/rect_area
pri("轮廓面积与边界矩形比:",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)
cv2.imshow("img",img)
cv2.waitKey()
cv2.destroyAllWindows()
定义:模板匹配类似于卷积,模板在原图像上从原点开始滑动,计算模板与图形被模板覆盖区域的差别程度,将每次计算的结果都保存到一个矩阵里,作为结果输出
假设:模板:a*b 原图像:A*B 输出结果矩阵:(A-a+1)*(B-b+1)
差别程度计算方法:TM_SQDIFF:计算平方不同,值越小,越相关
TM_CCORR:计算相关性,值越大,越相关
TM_CCOEFF:计算相关系数,值越大,越相关
TM_SQDIFF_NORMED:计算归一化平方不同,越接近于0越相关
TM_CCORR_NORMED:计算归一化相关性,越接近于1越相关
TM_CCOEFF_NORMED:计算归一化相关系数,越接近于1越相关
import cv2
import matplotlib.pyplot as plt
img=cv2.imread("lena.jpg",0)
template=cv2.imread("face.jpg",0)
h,w=template.shape[:2]
img.shape
template.shape
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)#不能是字符串
print(method)
res=cv2.matchTemplate(img2,template,method)
res.shape
min_val,max_val,min_roc,max_roc=cv2.minMaxLoc(res)#最小值,最大值,最小值坐标位置,最大值坐标位置
if method in [cv2.TM_SQDIFF,cv2.TM_SQDIFF_NORMED]:
top_left=min_roc
else :
top_left=max_roc
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.xtick([])#隐藏坐标轴
plt.ytick([])
plt.subtitle(meth)
plt.show()
threshold=0.8#设定一个阈值
loc=np.where(res>=threshold)
for pt in zip(*loc[::-1]):
bottom_right=(pt+w,pt+h)
cv2.rectangle(img2,pt,bottom_rigth,(0,0,255),2)
cv2.imshow("img2",img2)
cv2.waitKey()
cv2.destroyAllWindows()