概述
背景
在进行一个和视频分析相关的项目研究的时候,我们需要前置使用OpenCV对图像进行预处理。在密集使用OpenCV的API的过程中,我们有了这样一种感觉:大部分人写的API都是ctrl+c 和 ctrl+v,而OpenCV的好多API,每一个API背后都是一篇论文。感动之余,Gemfield写了这篇文章,把调研过程中使用过的OpenCV的API都在这篇文章中予以解释。Gemfield也欢迎OpenCV的用户提供和反馈自己使用过的并且觉得有意义的OpenCV API。
本文示例代码基于OpenCV 3.1和python 2.7.14。
frame变量
在下文中任何一个算法的示例代码中,都会用到frame这个变量。frame代表一个图片或者一帧图像。它在C++中是个Mat结构,在Python中是numpy存储的多维数组。当frame是一个图片的时候,它来自读取的一个图片:
import cv2
import numpy as np
frame = cv2.imread('gemfield.jpg')
当frame是一帧图像的时候,它来自一段视频中的一帧:
import cv2
import numpy as np
video_cap = cv2.VideoCapture('gemfield.mp4')
while True:
rc, frame = video_cap.read()
if not rc:
break
常规操作
1,cv2.namedWindow()是新增一个播放窗口。
2,cv2.destroyWindow()是销毁一个播放窗口。
3,cv2.setMouseCallback('gemfield window 1', callback_function),为gemfield window 1播放窗口创建个回调,一般用于鼠标事件。callback_function的第一个参数是event。
cv2.namedWindow('gemfield window 1')
cv2.destroyWindow('gemfield window 1')
cv2.setMouseCallback('gemfield window 1', callback_func1)
颜色操作
1,cv2.cvtColor()
改变frame的颜色。flag有cv2.COLOR_BGR2GRAY 、cv2.COLOR_BGR2HSV等几十个吧。
Image Thresholding
1,cv2.threshold()
将一副图像的像素点按照黑白颜色二分类,非黑即白。
图像平滑
要用卷积核的啊。
1,cv2.filter2D()
2,cv2.blur()
3,cv2.GaussianBlur()
高斯模糊,gemfield最常用的。使用Gaussian kernel做卷积。
4, cv2.medianBlur()
5,cv2.bilateralFilter()
图像梯度和边缘检测
1,cv2.Sobel()
2,cv2.Scharr()
3,cv2.Laplacian()
最好用的、最好上手的API当属下Canny 边缘检测,它融合了梯度检测和NMS:
4,cv2.Canny()
Image Pyramids 图像金字塔
图像融合方面用处很大。
1,cv2.pyrUp()
2,cv2.pyrDown()
图像变换之Fourier Transform
1,cv2.dft()
2,cv2.idft()
Template Matching
1,cv2.matchTemplate()
模板匹配,这个就很有用了。虽然和神经网络比起来是惨不忍睹,但是对于一些模式恒定不变的目标检测,这个还是很有用的。就是使用简单的滑动窗口的方式去寻找猎物。模板匹配的模式有6种:
- cv2.TM_CCOEFF;
- cv2.TM_CCOEFF_NORMED
- cv2.TM_CCORR
- cv2.TM_CCORR_NORMED
- cv2.TM_SQDIFF
- cv2.TM_SQDIFF_NORMED
2,cv2.minMaxLoc()
Hough 线变换和圆变换
一版都会先做edge detection。
1,cv2.HoughLines()
用于检测图像中的直线。不知道为啥,效果很差。
2,cv2.HoughCircles()
用于检测图像中的直线。不知道为啥,效果还是很差。
Image Segmentation 图像分割
1,cv2.watershed()
使用Watershed算法。用处不大,和很多其它API一样,神经网络出来后,这些东西就进博物馆了。
Foreground Extraction 前景提取
1,cv2.grabCut()
Feature Detection and Description 特征检测和描述
1,cv2.cornerHarris()
2,cv2.cornerSubPix()
Harris角检测,这个非常有用。
3,cv2.goodFeaturesToTrack()
Shi-Tomasi 角检测算法。这个应用很广。
4,cv2.SIFT()
5,cv2.SURF()
这2个API在OpenCV 3.1中已经被挪走了。
Background Subtraction 背景移除
主要是为了拿到(移动的)前景,OpenCV实现了3个背景移除的算法:BackgroundSubtractorMOG、BackgroundSubtractorMOG2、BackgroundSubtractorGMG。
1,cv2.BackgroundSubtractorMOG2()
使用了Gaussian Mixture-based Background/Foreground Segmentation 算法,基于2004年的“Improved adaptive Gausian mixture model for background subtraction”和2006年的 “Efficient AdaptiveDensity Estimation per Image Pixel for the Task of Background Subtraction” 这2篇论文。
import numpy as np
import cv2
cap = cv2.VideoCapture('gemfield.mp4')
fgbg = cv2.createBackgroundSubtractorMOG2(history=20, detectShadows=False)
while 1:
ret, frame = cap.read()
fgmask = fgbg.apply(frame)
cv2.imshow('frame',fgmask)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
cv2.destroyAllWindows()
cap.release()
createBackgroundSubtractorMOG2这个API有3个参数,detectShadows表明是否检测影子,history指明当前帧受之前多少帧的影响, varThreshold设定阈值,越高的值表明越多的像素被归为背景。
Morphological Transformations 形态变换
要用卷积核的。
1,cv2.erode()
腐蚀,亮色腐蚀(和卷积核有关)。
2,cv2.dilate()
膨胀,默认的卷积核是亮色膨胀。
3,cv2.morphologyEx()
根据flag的不同,可以是open或者close。
Histograms
1,cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])
frame = cv2.imread('gemfield.jpg',0)
hist = cv2.calcHist([frame],[0],None,[256],[0,256])
参数介绍:
1,images : 输入的图像,用方括号框起来:“[img]”。
2,channels : it is also given in square brackets. It is the index of channel for which we calculate histogram. For example, if input is grayscale image, its value is [0]. For color image, you can pass [0],[1] or [2] to calculate histogram of blue,green or red channel respectively。
3. mask : mask image. To find histogram of full image, it is given as “None”. But if you want to find histogram of particular region of image, you have to create a mask image for that and give it as mask。
4. histSize : this represents our BIN count. Need to be given in square brackets. For full scale, we pass [256]。BIN就是pixal value的范围的个数,比方说10到20就是一个BIN。
5. ranges : this is our RANGE. Normally, it is [0,256]。
Perspective Transformation 透视变换
这个非常有用。
1,cv2.getPerspectiveTransform()
得到透射变换矩阵。
2,cv2.warpPerspective()
直接透射变换图像。
3,cv2.perspectiveTransform()
使用透射变换矩阵把之前坐标系的点转换到新的坐标系中。
Contours 轮廓
1,cv2.findContours()
2,cv2.drawContours()
import numpy as np
import cv2
frame = cv2.imread('gemfield.jpg')
imgray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,0)
image, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
#画出所有的contours
frame = cv2.drawContours(frame, contours, -1, (0,255,0), 3)
#画出第4个contour
frame = cv2.drawContours(frame, contours, 3, (0,255,0), 3)
#也可以这么弄
cnt = contours[4]
frame = cv2.drawContours(frame, [cnt], 0, (0,255,0), 3)
如上面的代码展示的那样,cv2.findContours()函数有3个参数,第一个是frame,第二个参数指定寻找contour的模式(主要是因为轮廓会嵌套,所以衍生出各种模式),第三个参数是contour 的近似方法。返回值是三个,image、contours、hierarchy。返回值中的contours 是个python list,是image中的所有contours,该list中的每一个元素是一个numpy array,代表一个单独的轮廓的边界上的点的坐标。hierarchy表明轮廓的嵌套层级。
话说findContours()函数的第三个参数是contour的近似方法,这到底是什么意思呢?它代表的意思就是如何去用点表示一个轮廓。比如:
- cv2.CHAIN_APPROX_NONE,存储轮廓线上的所有的点;
- cv2.CHAIN_APPROX_SIMPLE,在上面的基础上去掉冗余的点;
3,cv2.moments()
轮廓矩。用一个字典M存储轮廓矩的相关信息。然后根据这些信息计算得到自己想要的,比方说中心位置的x、y坐标。
4,cv2.contourArea()
计算轮廓面积。
5,cv2.arcLength()
计算轮廓周长。
6,Contour Approximation
实现了Douglas-Peucker算法,根据轮廓来拟合自己想要找的形状。
7, cv2.convexHull()
这个有点像 contour approximation,但其实不是。这个函数检查轮廓曲线是否有不是凸的部分,如果有,把它弄平或者凸。也可以单独使用函数 cv2.isContourConvex()来仅仅做判断(不返回修正后的曲线)。
8, cv2.boundingRect()
在轮廓上拟合矩形。为了拟合出面积最小的矩形,还可以使用cv2.minAreaRect()和cv2.boxPoints()来拟合出旋转的矩形。
9, cv2.minEnclosingCircle()
在轮廓上拟合出圆。
10,cv2.fitEllipse()
在轮廓上拟合出椭圆。
11, cv2.fitLine()
在轮廓上拟合出直线。
12,cv2.matchShapes()
比较2个轮廓的异同。
HOG 方向梯度直方图
1,cv2.HOGDescriptor()
hog = cv2.HOGDescriptor()
hog.setSVMDetector( cv2.HOGDescriptor_getDefaultPeopleDetector() )
while True:
ret, frame = camera.read()
found, w = hog.detectMultiScale(frame, winStride=(8,8), padding=(32,32), scale=1.05)
for x, y, w, h in found:
# the HOG detector returns slightly larger rectangles than the real objects.
# so we slightly shrink the rectangles to get a nicer output.
pad_w, pad_h = int(0.15*w), int(0.05*h)
cv2.rectangle(frame, (x+pad_w, y+pad_h), (x+w-pad_w, y+h-pad_h), (0, 255, 0), 1)
cv2.imshow('img', frame)
一般结合SVM分类器来检测行人,这方面比较成功。
Image Inpainting
1,cv2.inpaint()
需要mask。
人脸检测
要弄懂什么是级联啊。
1,cv2.CascadeClassifier()
视频领域中的目标追踪
1,cv2.meanShift()
使用聚类算法进行目标追踪。返回一个矩形的track window。
2, cv2.calcOpticalFlowPyrLK()
OpenCV实现的Lucas-Kanade 光流算法,对于镜头多变的video来说,不好弄。
一些有用的github项目
1,镜头分割(切换)检测
Breakthrough/PySceneDetect
最后
以上就是体贴哑铃为你收集整理的使用OpenCV进行基本图像处理背景的全部内容,希望文章能够帮你解决使用OpenCV进行基本图像处理背景所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复