(一)harris角点检测(cv2.cornerHarris)
角点检测这里使用的是cv2.cornerHarris(),主要参数有下面四个:
img: 数据类型为 float32 的入图像
blockSize: 角点检测中指定区域的大小
ksize: Sobel求导中使用的窗口大小
k: 取值参数为 [0,04,0.06]
其中最后一个K,我个人感觉不是只能取那三个值,我最高取到了0.1,还是检测到了角点,只是效果不太好,小伙伴们可以多试试改一下上面的几个参数
import cv2
import numpy as np
img=cv2.imread("1.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
dst = cv2.cornerHarris(gray, 2, 3, 0.04)
dst = cv2.dilate(dst,None)#可有可无,可以增加角点的大小
img[dst>0.1*dst.max()]=[0,255,0]#角点为原谅色
cv2.imshow('dst ',img)
cv2.waitKey(0)
其中上面的img[dst>0.1*dst.max()]=[0,255,0]这里是设定一个阈值 当大于这个阈值分数的都可以判定为角点(然后角点为原谅色),其中前面的系数0.1小伙伴们可以多改改,一般是系数越小,角点越多(且系数一般设置为0.01)
(二)运动物体的检测
这里使用混合高斯模型,在进行前景检测前,先对背景进行训练,对图像中每个背景采用一个混合高斯模型进行模拟,每个背景的混合高斯的个数可以自适应。然后在测试阶段,对新来的像素进行GMM匹配,如果该像素值能够匹配其中一个高斯,则认为是背景,否则认为是前景。由于整个过程GMM模型在不断更新学习中,所以对动态背景有一定的鲁棒性。
下面我们识别视频中的人
原理就不讲了,上代码:
import numpy as np
import cv2
#经典的测试视频
cap = cv2.VideoCapture('test.avi')
#形态学操作需要使用
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
#创建混合高斯模型用于背景建模
fgbg = cv2.createBackgroundSubtractorMOG2()
while(True):
ret, frame = cap.read()
mask = fgbg.apply(frame)
#形态学开运算去噪点
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
#寻找视频中的轮廓
contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
#计算各轮廓的周长
peri = cv2.arcLength(c,True)
if peri > 175:#这里对轮廓进行过滤(因为视频中的警戒线也在飘动),正因为这个过滤,导致左上角的一个人没有框选出来
#找到一个直矩形(不会旋转)
x,y,w,h = cv2.boundingRect(c)
#画出这个矩形
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)#原谅色
cv2.putText(frame,"people",(x-10,y-10),
cv2.FONT_HERSHEY_COMPLEX, 0.7,
(0, 255, 0),3)#原谅色
cv2.imshow('frame',frame)
cv2.imshow('mask', mask)
k = cv2.waitKey(100) & 0xff
if k == 27:
break
cap.release()
cv2.destroyAllWindows()
这里其实还有一种方法叫(帧差法)背景减法,但我个人感觉不怎么好用,所以就不介绍了
(三)点与轮廓的关系(cv2.pointPolygonTest)
使用该函数可以确定一个点与轮廓的距离和位置关系
该函数有三个参数,第一个是目标轮廓,第二个是目标点的,第三个参数是measureDist。如果设置为True,就会计算最短距离。如果是False,只会判断这个点与轮廓之间的位置关系(返回值为+1,-1,0)
这里我们选择3个点分别计算它们与图中椭圆的位置关系和距离,三个点分别为(365,34)(365,68)(365,129)
import cv2
import numpy as np
img = cv2.imread('1.png')
imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转为灰度图
imgBlur = cv2.GaussianBlur(imgGray,(7,7),1)#高斯降噪
imgCanny = cv2.Canny(imgBlur,50,50)#canny边缘检测
contours,hierarchy = cv2.findContours(imgCanny,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)#提取图像外轮廓,并返回至contours
img_output=cv2.drawContours(img.copy(), contours, 3, (0, 255, 0), 3)#这里使用原谅色
#这里有一个细节,那就是我们并没有直接在原图上画出轮廓,因为在原图上,会直接破会原图信息,这里3为椭圆的轮廓
test1=cv2.pointPolygonTest(contours[3],(365,34),True)
test2=cv2.pointPolygonTest(contours[3],(365,63),True)
test3=cv2.pointPolygonTest(contours[3],(365,129),True)
test4=cv2.pointPolygonTest(contours[3],(365,34),False)
test5=cv2.pointPolygonTest(contours[3],(365,63),False)
test6=cv2.pointPolygonTest(contours[3],(365,129),False)
print("test1=",test1)
print("test2=",test2)
print("test3=",test3)
print("test1的位置为",test4)
print("test2的位置为",test5)
print("test3的位置为",test6)
cv2.imshow("img_output", img_output)
cv2.waitKey(0)
终端的打印的信息为:
test1= -29.0
test2= -0.0
test3= 54.0
test1的位置为 -1.0(轮廓的外围)
test2的位置为 0.0(在轮廓的上面)
test3的位置为 1.0(轮廓的内部)
(四)结语
学习opencv有很多的方法,我的建议是你可以加一些群,可以充分利用B站,CSDN,和百度。
在我的博客中,我不会讲解opencv的算法实现(当然我也不太会),我只会讲解一些函数的调用,不理解就多改一些参数,多尝试尝试,慢慢你就理解来。相信你总有一天可以说opencv不过“Ctrl+C,Crtl+V”
如果有什么错误的地方,还请大家批评指正,最后,希望小伙伴们都能有所收获。