欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OpenCV的霍夫变换(Hough Transform)圆检测

程序员文章站 2022-07-14 11:18:44
...

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;
}
OpenCV的霍夫变换(Hough Transform)圆检测

OpenCV的霍夫变换(Hough Transform)圆检测