博主简介

博主是一名大二学生,主攻人工智能研究。感谢让我们在CSDN相遇,博主致力于在这里分享关于人工智能,c++,Python,爬虫等方面知识的分享。如果有需要的小伙伴可以关注博主,博主会继续更新的,如果有错误之处,大家可以指正。

专栏简介: 本专栏主要研究python在人工智能方面的应用,涉及算法,案例实践。包括一些常用的数据处理算法,也会介绍很多的Python第三方库。如果需要,点击这里 专栏订阅。

给大家分享一个我很喜欢的一句话:“每天多努力一点,不为别的,只为日后,能够多一些选择,选择舒心的日子,选择自己喜欢的人!


目录

角点检测

Harris算子

goodFeaturesToTrack算子

几何形状检测

Hough算法

直线检测

圆检测

尺度不变特征变换



角点检测

在进行图像匹配的时,通常需要对两幅图像中的特征点进行匹配。为了保证匹配的准确性,选择的特征点必须具有其独特性,而图像的角点则经常被看成是一种不错的选择。由观察可知,角点往往是两天边缘的交点,它是两条边缘方向变换的一种表示,因此,其两个方向的梯度变化通常都比较大并且容易检测。人们通过在一个小小的窗口区域内观察像素点的灰度值大小来识别角点,如果向任何方向移动窗口都会引起较大的灰度变化,则该位置往往就是我们要找的角点。


Harris算子

对于角点检测,有很多的算法,其中Harris算法是最常用的角点检测算法之一,算法依据的正是上图的直观判断。

要衡量在某个方向上的梯度变化大小,可定义图像在某个方向上灰度的变化E(u,v)。

E(u,v)=

向量(u,v)表示某个方向,以及在该方向上的位移。I(x,y)表示像素灰度值强度,范围为0~255,I(x+u,y+v)表示位移强度。由上述公式可知,我们要研究在哪个方向上图像灰度值变化最大,只需令E(u,v)的值最大即可,因为E(u,v)表示的是某个方向上图像灰度的变化。而求解问题,则可通过泰勒展开式:

记上式最后结果为

其中M为2*2的Harris矩阵,

根据Harris矩阵来计算矩阵特征值,并通过一个评分函数R来判断一个窗口中是否含有角点:

.

这些特征值决定了一个区域是否为角点,边缘或平面。

①.当λ1和λ2都很小时,|R|的值也很小,则该区域为平坦区域。

②.当λ1>>λ2,或者λ1<<λ2,则该区域为边缘。

③.当λ都很大时,且λ1≈λ2时,也很大,则该区域为角点。

因此,Harris角点检测可以“R>阈值”作为条件判断一个图像区域是否为为角点。J·西(J·Shi)和C·托马西(C·Tomasi)于1994年在其论文“Good Features to Track”中提出了一种对Harris角点检测算子的改进算法,也就是Shi—Tomasi角点检测算子。我们也可以通过goodFeaturesToTrack算法进行角点检测,它同样定义了评分函数R,也是用R值的大小来判断区域是否为特征点:

根据图像我们可以发现,角点的检测有些不太准确,只能检测较为明显的角点,并且存在很多的错误角点标记。于是,opencv便推出了更为精确的算法函数。


goodFeaturesToTrack算子

函数原型:

cv2.goodFeaturesToTack(image,maxCorners,qualityLevel,minDistance,[,corners[,mask[,blocksize[,useHarrisDetector[,k]]]])

参数说明如下:

(1).image:待检测目标图像

(2).maxCorners:最大数目的角点数

(3).qualityLevel:该参数指出最低可接受的角点质量,是一个百分数,实例中给0.01。

(4).minDistance:焦点之间最小的欧拉距离,避免得到相邻特征点。

(5).mask:可选参数,给出ROI。

利用goodFeaturesToTrack算法进行图像检测示例代码:

#goodFeaturesToTrack算法import numpy as npimport cv2#读入图像filename='D:\Image\\four.jpg'img=cv2.imread(filename)img2=img#将其转换为float型img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)img_gray=np.float32(img_gray)#得到角点坐标向量goodFeatures_corners=cv2.goodFeaturesToTrack(img_gray,25,0.01,10)goodFeatures_corners=np.int0(goodFeatures_corners)for i in goodFeatures_corners:    x,y=i.flatten()    #用绿点标记角点    cv2.circle(img2,(x,y),3,[0,255,],-1)cv2.imshow('goodFreaturesToTack角点检测',img2)cv2.waitKey()

其中绿点表示角点,从两个算法检测结果来看,对于图像角点的标记,goodFeaturesToTrack算法更为精确,准确性高,但是也有误差。


几何形状检测

在数字图像中,往往存在一些特殊形状的几何图形,例如人眼瞳孔的圆形,建筑物立面的直线等。在图像处理与识别中,物体的形状属于高级信息,而基本几何形状是图像目标的主要特征之一,在数字图像中对其进行准确的检测有重要意义。

Hough算法

Hough变换是一种常用的几何图形检测算法,其基本原理是将特定图形上的点变换到一组参数空间上,然后根据参数空间点的累加结果找到一个极大值对应的解,而这个解正对应着要寻找的几何形状的参数(例如直线的斜率k与常数b,圆的圆心o与半径r等)。

)量化,赋初值为一个二维矩阵M,M(ρ,θ)就成了一个累加器。

②.对图像边界上的每一个点进行变换,变换后属于那一组(ρ,θ),就把该组(ρ,θ)对应的累加器数加1,这里需要变换的点就是上面说的经过边缘提取以后的图像。

③.处理完成所有点后,分析得到的M(ρ,θ),设置一个阈值T,当M(ρ,θ)>T,就认为存在一条有意义的直线。

④.有了M(ρ,θ)和点p(x,y),我们就可以计算出对应的直线。

直线检测

OpenCV内置的置于Hough算法的直线检测函数有标准Hough变换函数HoughLines()和统计Hough变换函数HoughLinesP(),二者的参数和用法基本一致。我们的示例代码以HoughLinesP()函数为例。

函数原型:

HoughLinesP(image,rho,theta,threshold[,lines[,minLineLength[,maxLineGap]]])

参数说明如下:

(1)image:8比特单通道灰度原图

(2)rho:极坐标参数距离分辨率,即ρ的精度。

(3)theta:极坐标参数角度分辨率,即θ的精度

(4)threshold:设定的阈值,大于此阈值的线段才可以被检测通过并返回到结果中。值越大,意味着检测出的线段越长,检测出的线段个数越少。

(5)lines:函数返回的矢量,包含所有键的到的直线的参数。

(6)minLineLength:线段的最小长度

(7)maxLineGap:点到直线被允许的最大距离。

基于Hough变换算法的图像直线检测示例代码:

#形状检测import cv2import numpy as npimport matplotlib.pyplot as pltimg=cv2.imread('D:\Image\\four.jpg')gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转化为灰度图像#对图像进行Canny边缘检测edges=cv2.Canny(gray,50,200) #基于Canny算子的图像边缘检测plt.subplot(121)plt.imshow(edges,'gray')plt.xticks([])plt.yticks([])#基于统计Hough变换的直线检测lines=cv2.HoughLinesP(edges,1,np.pi/180,30,minLineLength=60,maxLineGap=10)lines1=lines[:,0,:]#返回包含检测到的所有直线的二维矩阵for x1,y1,x2,y2 in lines1[:]:    cv2.line(img,(x1,y1),(x2,y2),(255,255,0),1) #在图像中用黄色的线标记检测出的直线plt.subplot(122)plt.imshow(img,)plt.xticks([])plt.yticks([])plt.show()

结果展示:

根据图像显示,黄色标记的为直线,图像检测结果较为准确,但是依然存在部分重叠,这就需要程序员根据自己的需要调参数。

圆检测

对于圆的检测,我们知道圆的数学方程为:

标记内圆则需要更改参数(minRadius,maxRadius),这里更改参数后的标记如图:

尺度不变特征变换

尺度不变特征转化(Scale-Invariant Feature Transform,SIFT)是用于图像处理的一种算法,是一种局部特征描述算子,具有尺度不变性,可在图像中检测出关键点。

该算法于1999年由戴维·劳(David Lowe)在计算机视觉国际会议(International Conference on Computer Vision,ICCV)中首次提出,2004年,他再次整理完善后将相关论文发表于国际计算机视觉杂志(International Journal of Computer Vision,IJCV)。SIFT算法是用于提取图像局部特征的经典算法,其实质是在不同的尺度空间查找关键点(特征点),并计算出关键点的方向。SIFT所查找的关键点是一些十分突出,不会因光照,仿射变换(Affine Transformation)和噪声等因素而变化的点,如角点,边缘点,暗区的亮点及亮区的暗点等。

OpenCV内置了SIFT算法的诸多函数,包括示例化SIFT类的cv2.xfeatures2d.SIFT_create().

在图像中查找关键点的sift.detect(gray,None),计算找到关键点的描述符的sift.compute(grag,kp)以及在图中画出关键点的cv2.drawKeypoints(gray,kp,img)。

示例代码如下:

#尺度不变特征变换import cv2import numpy as npfrom matplotlib import pyplot as pltdef getSift():    '''    定义函数用于查看SIFT特征    '''    img_path1='D:\Image\girl.jpg'    img=cv2.imread(img_path1)    #将其转换为灰度图像    img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)    #创建SIFT的类    sift=cv2.SIFT_create() #版本改进,原来的函数为xdefaures2d.SIFT_create()    #在图像中找到关键点    kp=sift.detect(img_gray,None)    #keypoint数据分析    print(kp[0].pt)    #计算每个关键点的SIFT特征    des=sift.compute(img_gray,kp)    print(type(kp),type(des))    #des[0]为关键点的list,des[1]为特征向量的矩阵    print(type(des[0]),type(des[1]))    print(des[0],des[1])    print(des[1].shape)    #在灰度图像中找出这些点    img=cv2.drawKeypoints(img_gray,kp,np.array([]),(255,0,0),cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)    plt.imshow(img)    plt.show()getSift()

结果展示:

找到了关键点,那我们也就可以对两张图片进行匹配,shiyongSIFT算法进行图像匹配示例代码:

import cv2from matplotlib import pyplot as pltimg1=cv2.imread('D:\Image\\temp1.jpg',0) #载入第一幅图像img2=cv2.imread("D:\Image\\temp2.jpg",0) #第二幅#初始化SIFT检测器sift=cv2.SIFT_create()#通过SIFT检测找到关键点kp和描述子deskp1,des1=sift.detectAndCompute(img1,None)kp2,des2=sift.detectAndCompute(img2,None)#蛮力匹配算法,有两个参数,距离度量(L2(default),L1),是否交叉匹配(默认为False)bf=cv2.BFMatcher()#返回k个最佳匹配matches=bf.knnMatch(des1,des2,k=2)good=[]for m,n in matches:    if m.distance<0.75*n.distance:        good.append([m])img3=cv2.drawMatchesKnn(img1,kp1,img2,kp2,good[:10],None,flags=2)plt.imshow(img3)plt.show()

结果展示:

如果各位小伙伴认为本篇文章有用的,可以点赞收藏哦!预祝大家新年快乐!