OpenCV3-Python常用轮廓检测方法
admin 于 2018年05月11日 发表在 计算机视觉

轮廓检测的详细步骤,具体可查看博文《OpenCV3-Python轮廓检测介绍》,本节介绍常用的轮廓检测方法。

1. 基本轮廓检测

现实中会对目标的边界框、最小矩形区域、最小闭圆感兴趣。将cv2.findContours函数与少量OpenCV的功能相结合就能非常容易实现这些功能。

应用举例:

import cv2
import numpy as np

img = cv2.pyrDown(cv2.imread("hammer.jpg", cv2.IMREAD_UNCHANGED))

ret, thresh = cv2.threshold(cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY) , 127, 255, cv2.THRESH_BINARY)
image, contours, hier = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

for c in contours:
  
  #1.矩形边界框检测
  #(1)计算出一个简单的边框
  x,y,w,h = cv2.boundingRect(c)
  
  #(2)将轮廓转换为(x,y)坐标,加上矩形的高度和宽度,绘制矩形
  cv2.rectangle(img, (x,y), (x+w, y+h), (0, 0, 255), 2)

  #2.最小矩形区域检测
  #(1)计算出包围目标的最小区域
  rect = cv2.minAreaRect(c)
  
  #(2)计算最小面积矩形的坐标
  box = cv2.boxPoints(rect)
  
  #(3)坐标归一化为整型
  box = np.int0(box)
  
  #(4)绘制轮廓
  cv2.drawContours(img, [box], 0, (0,255, 0), 3)
  
  #3.最小闭圆检测
  #(1)计算最小闭圆的中心和半径
  (x,y),radius = cv2.minEnclosingCircle(c)
  
  #(2)坐标归一化为整型
  center = (int(x),int(y))
  radius = int(radius)
  
  #(3)绘制圆
  img = cv2.circle(img,center,radius,(255,0,0),2)

cv2.drawContours(img, contours, -1, (255, 0, 0), 2)   #绘制边沿轮廓
cv2.imshow("contours", img)

cv2.waitKey()
cv2.destroyAllWindows()

三种轮廓检测效果:

2. 直线检测(官网)

通过HoughLines()和HoughLinesP()函数来完成。两者主要区别:前者使用标准的Hough变换,后者使用概率Hough变换(因此名称里有一个字母'P')

HoughLinesP()函数之所以称为概率版本的Hough变换是因为它只通过分析点的子集并估计这些点都属于一条直线的概率,这就是标准Hough变换的优化版本。

2.1 使用HoughLines()检测直线

import cv2
import numpy as np

img = cv2.imread('lines.png')

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

edges = cv2.Canny(gray,50,150)

'''
cv2.HoughLines(image, rho, theta, threshold[, lines[, srn[, stn[, min_theta[, max_theta]]]]]) → lines

image – 8-bit, single-channel binary source image. The image may be modified by the function.
rho – Distance resolution of the accumulator in pixels.
theta – Angle resolution of the accumulator in radians.
threshold – Accumulator threshold parameter. Only those lines are returned that get enough votes ( >threshold).

'''
#200 代表应该检测到的行的最小长度
lines = cv2.HoughLines(edges, 1, np.pi/180, 200)

for i in range(len(lines)):
    for rho,theta in lines[i]:
        a = np.cos(theta)
        b = np.sin(theta)
        x0 = a*rho
        y0 = b*rho
        x1 = int(x0 + 1000*(-b))
        y1 = int(y0 + 1000*(a))
        x2 = int(x0 - 1000*(-b))
        y2 = int(y0 - 1000*(a))
    
        cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)
cv2.imshow("edges",edges)
cv2.imshow("lines", img)
cv2.waitKey()
cv2.destroyAllWindows()

2.2 使用HoughLinesP()检测直线

import cv2
import numpy as np


img = cv2.imread('lines.png')

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

edges = cv2.Canny(gray,50,150)

'''
cv2.HoughLinesP(image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]]) → lines

image – 8-bit, single-channel binary source image. The image may be modified by the function.
rho – Distance resolution of the accumulator in pixels.
theta – Angle resolution of the accumulator in radians.
threshold – Accumulator threshold parameter. Only those lines are returned that get enough votes ( >threshold ).
minLineLength – Minimum line length. Line segments shorter than that are rejected.
maxLineGap – Maximum allowed gap between points on the same line to link them.

'''

#最低线段的长度,小于这个值的线段被抛弃
minLineLength = 100

#线段中点与点之间连接起来的最大距离,在此范围内才被认为是单行
maxLineGap =10

#100阈值,累加平面的阈值参数,即:识别某部分为图中的一条直线时它在累加平面必须达到的值,低于此值的直线将被忽略。
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 100, minLineLength, maxLineGap)

for i in range(len(lines)):
    for x1,y1,x2,y2 in lines[i]:
        cv2.line(img, (x1,y1), (x2,y2), (0,255,0), 2)

cv2.imshow("edges",edges)
cv2.imshow("lines", img)
cv2.waitKey()
cv2.destroyAllWindows()

3. 圆检测(官网)

OpenCV中HoughCircles()函数可用来检测圆,它与使用的HoughLines()函数类似。与用来决定删除或保留直线的两个参数minLineLength和maxLineGrap一样,HoughCircles有一个圆心间的最小距离圆的最小及最大半径

import cv2
import numpy as np

planets = cv2.imread('planet_glow.jpg')

gray_img = cv2.cvtColor(planets, cv2.COLOR_BGR2GRAY)

#中值滤波
img = cv2.medianBlur(gray_img, 5)

#灰度转换为彩色
cimg = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

#圆形检测
'''
cv2.HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) → circles

image – 8-bit, single-channel, grayscale input image.
method – Detection method to use. Currently, the only implemented method is CV_HOUGH_GRADIENT , which is basically 21HT , described in [Yuen90].
dp – Inverse ratio of the accumulator resolution to the image resolution. For example, if dp=1 , the accumulator has the same resolution as the input image. If dp=2 , the accumulator has half as big width and height.
minDist – Minimum distance between the centers of the detected circles. If the parameter is too small, multiple neighbor circles may be falsely detected in addition to a true one. If it is too large, some circles may be missed.
param1 – First method-specific parameter. In case of CV_HOUGH_GRADIENT , it is the higher threshold of the two passed to the Canny() edge detector (the lower one is twice smaller).
param2 – Second method-specific parameter. In case of CV_HOUGH_GRADIENT , it is the accumulator threshold for the circle centers at the detection stage. The smaller it is, the more false circles may be detected. Circles, corresponding to the larger accumulator values, will be returned first.
minRadius – Minimum circle radius.
maxRadius – Maximum circle radius.
circles – Output vector of found circles. Each vector is encoded as a 3-element floating-point vector  (x, y, radius) .

'''
cicles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT,1,120,
                          param1=100, param2=30, minRadius=0, maxRadius=0)

circles = np.uint16(np.around(cicles))

for i in circles[0,:]:
    
    #绘制外部圆轮廓
    cv2.circle(planets,(i[0],i[1]),i[2],(0,255,0),2)
    
    #标注圆的中心
    cv2.circle(planets,(i[0],i[1]),2,(0,0,255),3)
    
cv2.imwrite("planets_circles.jpg", planets)

cv2.imshow("original", cimg)
cv2.imshow("HoughCircles", planets)
cv2.waitKey()
cv2.destroyAllWindows()

下一篇: OpenCV3-Python深度估计—基于图像》

注意:本站所有文章除特别说明外,均为原创,转载请务必以超链接方式并注明作者出处。 标签:opencv3,python