天天看點

【OpenCV】霍夫變換圓檢測

在直角坐标系下,圓的方程表示為

【OpenCV】霍夫變換圓檢測

其中,r是圓的半徑,(a, b)是圓心坐标。

那麼換一種表達方式

【OpenCV】霍夫變換圓檢測

因為在直角坐标系下,圓上的所有點都滿足圓的方程,是以直角坐标系下的一個圓對應到abr坐标系下就是一個點。直角坐标系下經過一個點的所有圓在abr坐标系下就是一條三維曲線。那麼,直角坐标系下圓上的所有點在abr坐标系下就是這麼多條三維曲線交于一點。

但是在實際計算中,三維空間意味着更加複雜的運算。OpenCV對基礎的霍夫圓檢測做了優化,使用兩輪篩選。第一輪篩選使用一個二維累加器,找出可能是圓的位置。因為圓周上像素點的梯度方向與半徑的方向一緻,是以對每個像素來說,累加器隻對沿梯度方向的入口增加計數。一旦檢測到可能的圓心,就在第二輪篩選中建立半徑值範圍的一維直方圖,這個直方圖的尖峰值就是被檢測圓的半徑。

在實踐中,由于梯度容易受噪聲的影響,是以在進行霍夫圓檢測之前要先對圖像進行平滑,以減少圖像中可能導緻誤判的噪聲。

OpenCV中的函數圓形

void cv::HoughCircles(InputArray image,
    OutputArray circles,
    int method,
    double dp,
    double minDist,
    double param1 = 100,
    double param2 = 100,
    int minRadius = 0,
    int maxRadius = 0 
)	
           

函數參數比較多,可能要反複調參才能得到比較好的檢測效果。

cv::Mat srcImg = cv::imread("circle.jpg");
	if (srcImg.empty())
	{
		cout << "error";
		return -1;
	}
	cv::namedWindow("SRC", CV_WINDOW_AUTOSIZE);
	cv::imshow("SRC", srcImg);

	cv::Mat srcGray;
	cv::cvtColor(srcImg, srcGray, cv::COLOR_RGB2GRAY);
	cv::namedWindow("GRAY", CV_WINDOW_AUTOSIZE);
	cv::imshow("GRAY", srcGray);

	cv::Mat blurImg;
	cv::GaussianBlur(srcGray, blurImg, cv::Size(5, 5), 1.5);
	cv::namedWindow("BLUR", CV_WINDOW_AUTOSIZE);
	cv::imshow("BLUR", blurImg);

	std::vector<cv::Vec3f> circles;
	cv::HoughCircles(blurImg, circles, cv::HOUGH_GRADIENT, 2, 50, 200, 100, 25, 100);

	cv::Mat drawImg;
	srcImg.copyTo(drawImg);
	std::vector<cv::Vec3f>::const_iterator it = circles.begin();
	while (it != circles.end())
	{
		cv::circle(drawImg, cv::Point((*it)[0], (*it)[1]), (*it)[2], cv::Scalar(0, 0, 255), 2);
		++it;
	}
	cv::namedWindow("CIRCLE", CV_WINDOW_AUTOSIZE);
	cv::imshow("CIRCLE", drawImg);

	cv::waitKey(0);
           
【OpenCV】霍夫變換圓檢測
【OpenCV】霍夫變換圓檢測
【OpenCV】霍夫變換圓檢測
【OpenCV】霍夫變換圓檢測