目录
前提准备:调用相应的库,包括cv2,matplotlib,numpy
1.轮廓绘制
读入的原图为:ppt自己手动画的,很难百度出满意的图。后面涉及到轮廓的一些信息读取,建议在这一步采用一些恶比较简单的图形。
img=cv2.imread('F:D.PNG')
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
↑读入图片-灰度处理-二值化处理
contours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
↑ 读取到的两个参数的意思分别是:轮廓点的信息-list结构;层级信息
draw_img=img.copy()
↑原图复制一份,待会画轮廓将在复制出来的图片上画。如果不复制,直接会将轮廓画在原图上,这样的话如果后面还需要用到原图,而原图却被改变(附加了自己画的轮廓)
res=cv2.drawContours(draw_img,contours,-1,(0,0,255),1)
↑ cv2.drawContours()里面四个参数分别是:在哪副图轮廓;轮廓信息;所有的轮廓显示哪一个(-1代表图片中所有元素的轮廓);轮廓的颜色;轮廓的粗细
用cv2.imshow()函数显示运行效果:
当cv2.drawContours()第三个参数为0,1,2,3时的效果图:
2.轮廓特征
cnt=contours[3]
area=cv2.contourArea(cnt)
length=cv2.arcLength(cnt,True)#true代表封闭
print(area)
print(length)
↑congtour[3]表示:取的是cv2.drawContours()函数第三个参数取3的图形的轮廓的信息,这里具体是哪个图形的轮廓不能主观臆断,需要代码运行一下看到底是哪一个。这幅图参数为3时对应的是圆的轮廓。
cnt=contours[]这一步是必须的,每次都要申明自己在哪个轮廓上操作。
cv2.contourArea(cnt)是轮廓的面积,cv2.arcLength(cnt,True)是轮廓的周长,运行结果如下:
3.轮廓近似
读入的图片为:
↑为了显示取近似时参数的作用,尽量选取这种凹凸有致的图形,上图是用PPT绘制。
3.1近似
img=cv2.imread('F:ddd.png')
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
↑以上为准备工作,过程和轮廓绘制完全一致,即读入图片、灰度处理、二值化处理、 cv2.findContours()函数提取轮廓信息
draw_img=img.copy()
cnt=contours[-1]
↑ 原图复制,此后的工作都是在draw_img这幅图上而不是img这幅图;cnt为-1即图像的全部元素的轮廓,这幅图就一个元素。
#参照值:决定是否将一段曲线近为直线
epsilon=0.1*cv2.arcLength(cnt,True)
#近似轮廓
approx=cv2.approxPolyDP(cnt,epsilon,True)
#将近似出来的轮廓画在复制出来的图片上
res=cv2.drawContours(draw_img,[approx],-1,(0,0,255),1)
当式中的自变量分别取0.001,0.01,0.1,0.15时,近似出来的轮廓效果如下:
3.2外接矩形
依然是3.1节轮廓近似的图片
cnt=contours[-1]
#确定矩形边界
x,y,w,h=cv2.boundingRect(cnt)
draw_img=img.copy()
#在复制的图中画出矩形边界,左上角开始画
res=cv2.rectangle(draw_img,(x,y),(x+w,y+h),(0,0,255),2)
运行结果:
3.3外接圆
#确定圆心及半径
(x,y),radius=cv2.minEnclosingCircle(cnt)
center=(int(x),int(y))
radius=int(radius)
draw_img=img.copy()
#复制的图层上画外接圆
img=cv2.circle(draw_img,center,radius,(0,255,0),2)
效果如下:
Orz,图片有点小,画的圆出界了。
4.模板匹配
4.1单个对象匹配
读入库,读入原图并灰度处理,读入匹配模板-灰度图格式。模板大小无所谓,只要是在原图上截下来的就成。原图和模板为:
h,w=face.shape
print(h,w)
↑确定模板的高和宽,为后面确定好对象之后画矩形框框起来
res=cv2.matchTemplate(img,face,cv2.TM_SQDIFF_NORMED)
min_val,max_val,min_loc,max_loc=cv2.minMaxLoc(res)
↑ cv2.matchTemplate()是一个匹配函数,匹配的是输入的img.jpg图片和face.jpg模板,匹配的方式是cv2.TM_SQDIFF_NORMED,即方差并归一化。
↑每次匹配时都是一个一个像素点移动,因此有超级多匹配信息,用cv2.minMaxLoc(res)函数将匹配结果中value值最小和最大的那个信息提取出来。具体可以提取出来最大最小匹配结果值和此时的位置。对于平方差处理方式来说,匹配结果越小,说明两者差异越小。
top_left=min_loc
Tm=cv2.rectangle(img, (top_left[0],top_left[1]), (top_left[0] + w,top_left[1] + h), (0, 0, 255), 1)
↑此时应该取得点应该是min_loc,这个点在匹配的位置的左上角,再根据模板的大小在原图上画出矩形,以此作为匹配结果。
几种常见的匹配方式处理结果如下图所示:
4.2多个对象匹配
img=cv2.imread('F:T.jpg')
img1=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
template=cv2.imread('F:T1.jpg',0)
h,w=template.shape
↑读入库(代码中未呈现),读入图片并灰度处理,读入模板并灰度处理,读出模板的高和宽
读入的原图和模板为:
res=cv2.matchTemplate(img1,template,cv2.TM_CCOEFF_NORMED)
↑匹配函数
threshold=0.8
img2=img.copy()
loc=np.where(res>=threshold)
for pt in zip(*loc[::-1]):
cv2.rectangle(img2,pt,(pt[0]+w,pt[1]+h),(0,0,255),1)
↑cv2.TM_CCOEFF_NORMED匹配方式,匹配值越大越接近。当大于阈值时,就认为匹配的对象是合格的,和模板是一致的,将之用和模板一样大的矩形框框起来。
匹配结果如下: