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;
}