我是靠谱客的博主 体贴哑铃,最近开发中收集的这篇文章主要介绍使用OpenCV进行基本图像处理背景,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

背景

在进行一个和视频分析相关的项目研究的时候,我们需要前置使用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进行基本图像处理背景所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部