OpenCV的霍夫變換(Hough Transform)圓檢測

Hough變換檢測圓

霍夫變換也可以用於檢測其他幾何形體,事實上,可以用參數方程表示的幾何體都可以嘗試用霍夫變換進行檢測。

比如圓形,它對應的參數方程爲:r2=(x-x0)2+(y-y0)2

該函數包含三個參數,分別是圓心的座標和圓的半徑,這意味着需要三維的累加器。

OpenCV中實現的霍夫圓檢測算法通常是兩個步驟:

1. 二維累加器用於尋找可能爲圓的位置。由於在圓周上的點的梯度應該指向半徑的方向,因此對於每一個點,只有沿着梯度方向的項纔得到增加(需要預先設定最大和最小的半徑);

2. 若找到了圓心,則構建一維的半徑的直方圖,這個直方圖的峯值對應的是檢測到的圓的半徑。

OpenCV中的霍夫變換圓檢測函數 cv::HoughCircles

它整合了Canny檢測和霍夫變換,輸出是cv::Vec3f向量,每個元素包含檢測圓的圓心座標和半徑(cx, cy, radius)。

另外,在進行霍夫變換之前,先對操作圖像進行平滑,以減少可能引起誤檢測的噪聲點。

#include "opencv2/highgui.hpp"
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"

class CircleFinder{
private:
	std::vector<cv::Vec3f> circles;
	double dp;       // 累加器的分辨率(圖像尺寸/2)
	double minDist;  // 兩個圓之間的最小距離
	double th;       // Canny中的高閾值
	double minVote;  // 最小投票數
	int minR;
	int maxR;        // 有效半徑的最小值和最大值
public:
	CircleFinder() {
		dp = 1.0, minDist = 1.0;
		th = 300;
		minVote = 80;
		minR = 1, maxR = 100;
	}
	void setDPandThreshold(double dp, double th) {
		dp = dp;
		th = th;
	}
	void setMinVote(double minv) {
		minVote = minv;
	}
	void setCircleParams(double minD, int minR, int maxR) {
		minDist = minD;
		minR = minR;
		maxR = maxR;
	}

	// Hough變換檢測圓
	void findCircles(cv::Mat& imageBlur) {
		circles.clear();
		cv::HoughCircles(imageBlur, circles, CV_HOUGH_GRADIENT, dp, minDist, th, minVote, minR, maxR);
	}

	void drawDetectedCircles(cv::Mat &image, cv::Scalar color = cv::Scalar(255)) {
		std::vector<cv::Vec3f>::const_iterator itc = circles.begin();
		while (itc != circles.end()) {
			cv::Point pt((*itc)[0], (*itc)[1]);
			cv::circle(image, pt, int((*itc)[2]), cv::Scalar(255), 2); //畫圓
			++itc;
		}
	}
};

int main(int argc, char *argv[])
{
	cv::Mat image = cv::imread("D:/VS_exercise/images/coin3.jpg");
	cv::Mat imageGray;
	cv::cvtColor(image, imageGray, cv::COLOR_RGB2GRAY);

	// 在調用cv::HoughCircles函數前對圖像進行平滑,減少誤差
	cv::Mat imageBlur;
	cv::GaussianBlur(imageGray, imageBlur, cv::Size(5, 5), 1.5);

	// Hough變換檢測
	CircleFinder finder;
	finder.setDPandThreshold(2, 300);
	finder.setMinVote(25);
	finder.setCircleParams(20, 5, 100);
	finder.findCircles(imageBlur);
	finder.drawDetectedCircles(image);

	// 顯示
	cv::namedWindow("Detected Lines with Hough");
	cv::imshow("Detected Lines with Hough", image);
	cv::waitKey(0);
	return 0;
}



發佈了71 篇原創文章 · 獲贊 98 · 訪問量 42萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章