[图像识别]8.OpenCV的模板匹配和霍夫检测
Posted ζั͡ ั͡雾 ั͡狼 ั͡✾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[图像识别]8.OpenCV的模板匹配和霍夫检测相关的知识,希望对你有一定的参考价值。
回顾,上节课你学了什么?
Sobel_x_or_y=cv.Sobel(img,ddepth,dx,dy,dst,ksize,scale,delta,borderType)
常用 Sobel_x_or_y=cv.Sobel(img,cv.CV_ 16S,dx,dy,ksize)
格式转换Scale_abs=cv.convertScaleAbs(x)
result=cv.addWeighted(img1,p1,img2,p2,k)
laplacian=cv.Laplacian(img,ddepth,dx,dy,dst,ksize,scale,delta,borderType)
canny=cv.Canny(img,threshold1,threshold2)
目录
模板匹配
1.原理
建立一个模板图像,不断移动模板图像来检测匹配程度,找到最高的匹配区域
2.步骤
【1】将原图像(W x H)与模板图像(w x h)计算匹配程度,将结果保存在矩阵R(W-w+1 x H-h+1)里面
【2】找到R矩阵中像素最大(即匹配度最大)的点位置,则这个点为顶点长宽为模板大小的区域就是匹配区域。
3.API代码
R=cv.matchTemplate(img,template,method)
img:原图像
template:模板图像
method:匹配算法
1.平方差匹配(cv.TM_SQDIFF):利用模板与图像之间的平方差进行匹配,最好的匹配是0,匹配越差,匹配的值越大。
2.相关匹配(cv.TM _CCORR):利用模板与图像间的乘法进行匹配,数值越大表示匹配程度较高,越小表示匹配效果差。
3.利用相关系数匹配(cv.TM_CCOEFF):利用模板与图像间的相关系数匹配,1表示完美的匹配,-1表示最差的匹配。匹配完成后得到矩阵使用函数
minVal,maxVal,minLoc,maxLoc=cv.minMaxLoc(R)
minVal:最小值
maxVal:最大值
minLoc:最小值位置
maxLoc:最大值位置
找到最大值所在位置;如果是CV_ TM_ SQDIFF,则找到最小值
举例:
#7.1
import cv2 as cv import numpy as np import matplotlib.pyplot as plt #解决中文显示问题,固定格式,直接复制下面俩行代码就行 plt.rcParams['font.sans-serif']=['SimHei'] plt.rcParams['axes.unicode_minus']=False #1.读取图像 pic1 = cv.imread("8.jpeg") template = cv.imread("8tem.jpeg") #2.获得匹配矩阵R R=cv.matchTemplate(pic1,template,cv.TM_SQDIFF) #3.获得矩阵R的最好匹配位置,即最小值位置 minVal,maxVal,minLoc,maxLoc=cv.minMaxLoc(R) #4.进行绘制矩形框作图 h,w,l=template.shape; pic2=pic1.copy() top_left=minLoc bottom_right=(top_left[0]+w,top_left[1]+h) cv.rectangle(pic2,top_left,bottom_right,(255,0,0),5) #绘制图像 fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(10,10)) axes[0,0].set_title("原图") axes[0,0].imshow(pic1) axes[0,1].set_title("模板") axes[0,1].imshow(template) axes[1,0].set_title("cv.TM_SQDIFF平方差匹配矩阵") axes[1,0].imshow(R,plt.cm.gray) axes[1,1].set_title("绘制矩阵") axes[1,1].imshow(pic2,plt.cm.gray) plt.show() cv.waitKey(0)
结果:
模板匹配不适用于尺度变换等各种条件改变的情况,只能很好匹配完全一样的模板图。视角变换,尺度大小变换,光照改变的图像需要用关键点匹配算法SIFT和SURF等
霍夫变换
常用来提取图像中的直线,圆形等几何图形。
一、霍夫线检测
1.原理:
一条直线的函数为y=kx+q,俩个点(x1,y1)(x2,y2)能确定一个(k1,q1)
坐边是笛卡尔坐标系的一条直线,对应右边霍夫坐标系的一个点,反过来同样照应
如果是俩个点,对应霍夫空间
三点共线情况
不止有一条直线
我们在霍夫空间选择最多的直线汇聚的点,再投影到笛卡尔坐标系
同理,还可以通过极坐标系来求,极坐标系和霍夫空间(ρ,theta)只是变量公式不同而已
只要已知霍夫空间交点,就能知道直线位置方程
OpenCV中霍夫变换坐标系:ρ=xcosθ+ysinθ
2.步骤
【1】霍夫空间,创建一个2维数组叫做累加器,行列分别表示极坐标的俩个参数。该数组大小表示了结果的准确性,如果希望角度设置精度为1度,那么为180列;ρ最大为图片对角线距离
【2】每遍历直线上的一个点,就能得到极坐标霍夫空间ρ和theta的俩个确定值,在累加器相应的ρ和seita格子上加1
【3】设定阈值threshold,遍历累加器,找到大于threshold的ρ和seita,说明这个ρ和theta值在霍夫空间上相交的直线的最多,就可以将图像中的直线显示出来
3.API代码
lines=cv.HoughLines(img,rho,theta,threshold)
lines:[[[rho1,theta1],[rho2,theta2],[rho3,theta3]....]]霍夫空间的交点集合
img:为2值图像,只有0和1
rho,theta:ρ和theta的精度,theta单位为弧度
threshold:阈值,累加器的值高于阈值时认为直线
举例:
#7.2
import cv2 as cv import numpy as np import matplotlib.pyplot as plt #解决中文显示问题,固定格式,直接复制下面俩行代码就行 plt.rcParams['font.sans-serif']=['SimHei'] plt.rcParams['axes.unicode_minus']=False #1.读取单通道图像 pic1 =cv.imread("line.jpg") pic2=pic1.copy() #2.霍夫变换直线 gray=cv.cvtColor(pic1,cv.COLOR_BGR2GRAY) edge=cv.Canny(gray,150,200)#Canny边缘检测 lines=cv.HoughLines(edge,1,np.pi/180,100) #3.绘制检测得到的直线 for line in lines: rho,theta=line[0] a=np.cos(theta) b=np.sin(theta) x0=rho*a y0=rho*b #延长线 x1=int(x0+1000*(-b)) y1=int(y0+1000*a) x2=int(x0-1000*(-b)) y2=int(y0-1000*a) cv.line(pic2,(x1,y1),(x2,y2),(255,0,255),2) #绘制图像 fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(10,10)) axes[0,0].set_title("原图") axes[0,0].imshow(pic1[:,:,::-1]) axes[0,1].set_title("Canny边缘检测进行二值化") axes[0,1].imshow(edge,plt.cm.gray) axes[1,1].set_title("霍夫直线到原图") axes[1,1].imshow(pic2[:,:,::-1]) plt.show() cv.waitKey(0)
结果
二、霍夫圆检测
霍夫圆检测需要三个变量圆心坐标a,b和半径r
(x-a)^2+(y-b)^2=r^2
在三维空间上进行霍夫变换,霍夫检测其他越复杂形状需要的维数更多
霍夫圆检测先确定圆心,再确定半径
圆心检测的原理:圆心是圆周法线的交汇处,设置一个阈值,在某点的相交的直线的条数大于这个阈值就认为该交汇点为圆心。
圆半径确定原理:圆心到圆周上的距离(半径)是相同的,确定一个阈值,只要相同距离的数量大于该阈值,就认为该距离是该圆心的半径。
circles=cv.HoughCircles(img,method,dp,minDist,param1=100,param2=100
,minRadius=0,maxRadius=0)
circlrs:[[[x1,y1,r1],[x2,y2,r2]....]]圆的三个参数集合
img:灰度图像
method:算法,cv.HOUGH_GRADIENT霍夫梯度算法
dp:霍夫空间分辨率1代表与原图一样,2代表是原图一半
minDist:圆心之间最小距离,如果小于该值代表同一个圆心,圆心容差
param1:边缘检测使用的Canny算子高阈值,低阈值是这个值的一半
param2:检测圆心和确定半径阈值
minRadius,maxRadius:检测圆半径的最大值和最小值
举例
#7.3
import cv2 as cv import numpy as np import matplotlib.pyplot as plt #解决中文显示问题,固定格式,直接复制下面俩行代码就行 plt.rcParams['font.sans-serif']=['SimHei'] plt.rcParams['axes.unicode_minus']=False #1.读取单通道图像 pic1 =cv.imread("circle.jpg") gray=cv.cvtColor(pic1,cv.COLOR_BGR2GRAY) #2.中值去噪 pic2=cv.medianBlur(gray,3) #3.霍夫圆检测 circles=cv.HoughCircles(pic2,cv.HOUGH_GRADIENT,1,minDist=200,param1=100,param2=30,minRadius=0,maxRadius=0) circles=np.uint16(np.around(circles))#圆心和半径都为整数 #4.绘制圆 pic3 = pic1.copy() for i in circles[0,:]:#遍历每一行 #绘制圆 cv.circle(pic3,(i[0],i[1]),i[2],(255,0,0),2) #绘制图像 fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(10,10)) axes[0,0].set_title("原图") axes[0,0].imshow(pic1[:,:,::-1]) axes[0,1].set_title("灰度图") axes[0,1].imshow(gray,plt.cm.gray) axes[1,0].set_title("中值去噪") axes[1,0].imshow(pic2,plt.cm.gray) axes[1,1].set_title("霍夫圆到原图") axes[1,1].imshow(pic3[:,:,::-1]) plt.show() cv.waitKey(0)
结果:
总结,这节课你学到了什么?
R=cv.matchTemplate(img,template,method)
minVal,maxVal,minLoc,maxLoc=cv.minMaxLoc(R)
lines=cv.HoughLines(img,rho,theta,threshold)
circles=cv.HoughCircles(img,method,dp,minDist,param1=100,param2=100
,minRadius=0,maxRadius=0)
以上是关于[图像识别]8.OpenCV的模板匹配和霍夫检测的主要内容,如果未能解决你的问题,请参考以下文章