霍夫圆检测原理
从平面坐标到极坐标转换三个参数 C(x0,y0,r) C ( x 0 , y 0 , r ) 其中 x0,y0 x 0 , y 0 是圆心
假设平面坐标的任意一个圆上的点,转换到极坐标中: C(x0,y0,r) C ( x 0 , y 0 , r ) 处有最大值,霍夫变换正是利用这个原理实现圆的检测。
现实考量:
因为霍夫圆检测对噪声比较敏感,所以首先要对图像做中值滤波。
基于效率考虑,OpenCV中实现的霍夫变换圆检测是基于图像梯度的实现,分为两步:
1. 边缘检测,发现可能的圆心
2. 基于第一步的基础从候选圆心开始计算最佳半径大小
import cv2
import numpy as np
import time
import matplotlib as plt
def dectect_circle_demo(image):
# dst = cv2.bilateralFilter(image, 0, 150, 5)
# 高斯双边模糊
# cv2.imshow("1", dst)
# dst = cv2.pyrMeanShiftFiltering(image, 5, 100)
# 均值迁移,EPT边缘保留滤波
# cv2.imshow("2", dst)
# dst = cv2.GaussianBlur(image, (13, 15), 15)
# 使用高斯模糊
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 20, param1=80, param2=20, minRadius=12, maxRadius=25)
circles = np.uint16(np.around(circles))
for i in circles[0, :]:
# 圆心加到图中
cv2.circle(image, (i[0], i[1]), i[2], (0, 0, 255), 2)
# 圆圈加到图中
cv2.circle(image, (i[0], i[1]), 2, (255, 0, 0), 2)
cv2.namedWindow("detect_circle_demo", cv2.WINDOW_NORMAL)
cv2.imshow("detect_circle_demo", image)
if __name__ == "__main__":
start = time.clock()
file = '0101_1'
name = '.jpeg'
filename = file + name
# img = cv2.imread(filename, 0)
# 参数零代表读取的图片为灰度图
img = cv2.imread(filename)
cv2.namedWindow("input", cv2.WINDOW_NORMAL)
# 设置窗口大小为NORMAL 避免大照片窗口太大
cv2.imshow("input", img)
dectect_circle_demo(img)
end = time.clock()
print('Running time: %s Seconds' % (end - start))
while (1):
k = (cv2.waitKey() & 0xFF)
if k == ord('q') or k == 27:
cv2.destroyAllWindows()
break
elif k == ord('s'):
cv2.imwrite(file + '_out' + name, img)
break
函数 HoughCircles相关参数,
手册中的declaration
def HoughCircles(image, method, dp, minDist, circles=None, param1=None, param2=None, minRadius=None, maxRadius=None): # real signature unknown; restored from __doc__
"""
HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) -> circles
. @brief Finds circles in a grayscale image using the Hough transform.
.
. The function finds circles in a grayscale image using a modification of the Hough transform.
.
. Example: :
. @code
. #include
. #include
. #include
.
. using namespace cv;
. using namespace std;
.
. int main(int argc, char** argv)
. {
. Mat img, gray;
. if( argc != 2 || !(img=imread(argv[1], 1)).data)
. return -1;
. cvtColor(img, gray, COLOR_BGR2GRAY);
. // smooth it, otherwise a lot of false circles may be detected
. GaussianBlur( gray, gray, Size(9, 9), 2, 2 );
. vector circles;
. HoughCircles(gray, circles, HOUGH_GRADIENT,
. 2, gray.rows/4, 200, 100 );
. for( size_t i = 0; i < circles.size(); i++ )
. {
. Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
. int radius = cvRound(circles[i][2]);
. // draw the circle center
. circle( img, center, 3, Scalar(0,255,0), -1, 8, 0 );
. // draw the circle outline
. circle( img, center, radius, Scalar(0,0,255), 3, 8, 0 );
. }
. namedWindow( "circles", 1 );
. imshow( "circles", img );
.
. waitKey(0);
. return 0;
. }
. @endcode
.
. @note Usually the function detects the centers of circles well. However, it may fail to find correct
. radii. You can assist to the function by specifying the radius range ( minRadius and maxRadius ) if
. you know it. Or, you may set maxRadius to a negative number to return centers only without radius
. search, and find the correct radius using an additional procedure.
.
. @param image 8-bit, single-channel, grayscale input image.
. @param circles Output vector of found circles. Each vector is encoded as a 3-element
. floating-point vector \f$(x, y, radius)\f$ .
. @param method Detection method, see #HoughModes. Currently, the only implemented method is #HOUGH_GRADIENT
. @param 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.
. @param 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.
. @param param1 First method-specific parameter. In case of #HOUGH_GRADIENT , it is the higher
. threshold of the two passed to the Canny edge detector (the lower one is twice smaller).
. @param param2 Second method-specific parameter. In case of #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.
. @param minRadius Minimum circle radius.
. @param maxRadius Maximum circle radius. If <= 0, uses the maximum image dimension. If < 0, returns
. centers without finding the radius.
.
. @sa fitEllipse, minEnclosingCircle
"""
method:输入图像(灰度图)
method:指定检测方法,目前OpenCV中只有霍夫梯度法
dp:累加器图像的反比分辨 =1 即可默认
minDist = src_gray.row/8: 检测到圆心之间的最小距离,经验值。这个大了,那么多个圆就被认为是一个圆
param_1 : canny边缘函数的高阈值
param_2 : 圆心检测阈值,根据图像中的圆的大小设置,当这张图片中的圆越小,那么此值就应该设置越小。当设置的越小,那么检测出的圆越多,在检测较大的圆时,则会产生很多噪声。所以要根据检测圆的大小变化
min_radius = 0 : 能检测到的最小圆半径,默认为0.
max_radius = 0 : 能检测到的最大圆半径,默认为0.