Opencv-C++ メモ (14): ハフ変換 (直線、円)

1. ハフ変換 - 直線

ライン検出にはハフ ライン変換が使用されます
前提条件 – エッジ検出が完了している

1. 平面空間 (x, y) を極座標空間に変換します。
ここに画像の説明を挿入

2. 極座標をθとRの関係に変換します。
ここに画像の説明を挿入

1.1 ハフ変換線原理の詳細な説明

[0~360] 空間から極座標に変換された任意の直線上のすべての点について r のサイズを取得でき、同じ直線に属する点は極座標空間 ( r , θ ) にあります。 r,\theta)(r,θ) はある点で最も強い信号が現れるはずで、これを平面座標に逆算することで直線上の各点のピクセル座標を求めることができます。直線が得られます。

標準のハフ変換 cv::HoughLines は平面座標からハフ空間に変換し、最終出力は ( r , θ ) (r, \theta)(r,θ) は極座標空間を表します。

void HoughLines(
InputArray image,     输入图像,必须8-bit的灰度图像
OutputArray lines,    输出的极坐标来表示直线
double rho,        极坐标素扫描步长
double theta,       极坐标角度步长,一般取值CV_PI/180
int threshold,       阈值,多少交点的极坐标点才被看成是直线
double srn = 0,       是否应用多尺度的霍夫变换,默认0表示经典霍夫变换
double stn = 0,       是否应用多尺度的霍夫变换,默认0表示经典霍夫变换 
double min_theta = 0,   表示角度扫描范围 0 ~180之间, 默认即可
double max_theta = CV_PI
);

ハフ変換直線確率 cv::HoughLinesP 最終出力は直線の 2 点 ( x 0 、 y 0 、 x 1 、 y 1 ) です。

void HoughLinesP(
InputArray image,      输入图像,必须8-bit的灰度图像
OutputArray lines,     输出的极坐标来表示直线
double rho,         极坐标像素扫描步长
double theta,        极坐标角度步长,一般取值CV_PI/180
int threshold,        阈值,多少交点的极坐标点才被看成是直线
double minLineLength = 0,  最小直线长度
double maxLineGap = 0 );  最大间隔
//头文件 quick_opencv.h:声明类与公共函数
#pragma once
#include <opencv2\opencv.hpp>
using namespace cv;

class QuickDemo {
    
    
public:
	...
	void hough_Demo(Mat& image1);
	void laplance_Demo(Mat& image1);
	void canny_Demo(Mat& image1);
};
//主函数调用该类的公共成员函数
#include <opencv2\opencv.hpp>
#include <quick_opencv.h>
#include <iostream>
using namespace cv;


int main(int argc, char** argv) {
    
    
	Mat src = imread("D:\\Desktop\\jianbian.png");
	if (src.empty()) {
    
    
		printf("Could not load images...\n");
		return -1;
	}
	QuickDemo qk;
	qk.hough_Demo(src1);
	qk.hough_Demo(src1);
	qk.canny_Demo(src1);
	waitKey(0);
	destroyAllWindows();
	return 0;
}
void QuickDemo::hough_Demo(Mat& image) {
    
    
	Mat image_line = image.clone();
	
	// 霍夫直线检测
	Mat gau_dst, gray_dst, grad_dst;
	GaussianBlur(image_line, gau_dst, Size(3, 3), 10);
	cvtColor(gau_dst, gray_dst, COLOR_BGR2GRAY);

	vector<Vec4f> plines;
	Canny(gray_dst, gray_dst, 100, 200);
	imshow("Canny", gray_dst);

	HoughLinesP(gray_dst, plines, 5, CV_PI/180, 10, 0, 10);// 斜线检测调整maxlineGap
	cout << "线条个数:" << plines.size() << endl;
	for (int i = 0; i < plines.size(); i++) {
    
    
		Vec4f hline = plines[i];
		line(image_line, Point(hline[0], hline[1]), Point(hline[2], hline[3]), Scalar(0, 0, 255), 1, 8, 0);
	}
	imshow("HoughLinesP", image_line);


	// 霍夫圆检测
	Mat median_dst, gray_median_dst;
	vector<Vec3f> pcircles;
	medianBlur(image, median_dst, 3);
	cvtColor(median_dst, gray_median_dst, COLOR_BGR2GRAY);
	HoughCircles(gray_median_dst, pcircles, HOUGH_GRADIENT, 1, 10, 100, 30, 5, 100);
	cout << "圆形个数:" << pcircles.size() << endl;

	for (int i = 0; i < pcircles.size(); i++) {
    
    
		Vec3f cc = pcircles[i];
		circle(image, Point(cc[0], cc[1]), cc[2], Scalar(255, 0, 0), 2, 8, 0);
		circle(image, Point(cc[0], cc[1]), 2, Scalar(255, 0, 0), 2, 8, 0); // 标注圆形
	}
	imshow("circle", image);
}

ここに画像の説明を挿入

2.ハフサークル検出

アルゴリズムの詳細については、次を参照してください: ハフ円検出公式が良い例を示しています。
直線の場合、直線は極半径と極角 ( r , θ ) (r, θ)(r, θ) で表すことができますが、円の場合は 3 つのパラメーターが必要です。円の中心 ( a , b ) (a , b) (a,b)、半径 r。
デカルト座標系における円の方程式は次のとおりです。
ここに画像の説明を挿入
これは、各セット (a、b、r) が点 (x0、y0) を通過する円を表すことを意味します。

特定の点 (x0、y0) について、その点を通過するすべての円を 3 次元デカルト座標系で描くことができます。最終的には 3 次元の曲線が完成します。
ハフ線変換円検出はノイズの影響を受けやすいため、最初に画像をメディアン フィルター処理する必要があり、より多くの検出計算が必要になります。OpenCV ハフ円変換は、標準のハフ円変換の操作を最適化します。「ハフ勾配法」を採用しています。

効率性を考慮して、Opencv に実装されたハフ変換円検出は画像勾配に基づいており、次の 2 つのステップに分かれています。

  1. エッジを検出し、考えられる円の中心を検出します
  2. 最初のステップに基づいて、候補円の中心からの最適な半径を計算します。

ハフ勾配法の原理

推定中心

1. 元のイメージに対して Canny エッジ検出を実行して、エッジ検出のバイナリ イメージを取得します。

元の画像に対してソーベル演算子を実行して、すべてのピクセルの近傍勾配値を計算します。

中心空間 N(a,b) を初期化し、全て N(a,b)=0 とします。

Canny エッジ バイナリ イメージ内のすべての非ゼロ ピクセル ポイントをトラバースし、グラデーション方向 (接線の垂直方向) に沿って線を描き、N(a,b)+ =1 となります。

void HoughCircles(
InputArray image,      输入图像 ,必须是8位的单通道灰度图像
OutputArray circles,    输出结果,发现的圆信息
int method,         HOUGH_GRADIENT
double dp,         dp = 1 累加器图像的反比分辨率
double minDist=src_gray.rows/8, 检测到圆心之间的最小距离,否则认为是同心圆-
double param1 = 100,    canny edge detection low threshold
double param2 = 100,   中心点累加器阈值 – 候选圆心
int minRadius = 0,      能检测到的最小圆半径, 默认为0
int maxRadius = 0      能检测到的最大圆半径, 默认为0
);
参数: 
第一个参数,InputArray类型的image,输入图像,即源图像,需为8位的灰度单通道图像。
第二个参数,InputArray类型的circles,经过调用HoughCircles函数后此参数存储了检测到的圆的输出矢量,每个矢量由包含了3个元素的浮点矢量(x, y, radius)表示。
第三个参数,int类型的method,即使用的检测方法,目前OpenCV中就霍夫梯度法一种可以使用,它的标识符为CV_HOUGH_GRADIENT,在此参数处填这个标识符即可。
第四个参数,double类型的dp,用来检测圆心的累加器图像的分辨率于输入图像之比的倒数,且此参数允许创建一个比输入图像分辨率低的累加器。上述文字不好理解的话,来看例子吧。例如,如果dp= 1时,累加器和输入图像具有相同的分辨率。如果dp=2,累加器便有输入图像一半那么大的宽度和高度。
第五个参数,double类型的minDist,为霍夫变换检测到的圆的圆心之间的最小距离,即让我们的算法能明显区分的两个不同圆之间的最小距离。这个参数如果太小的话,多个相邻的圆可能被错误地检测成了一个重合的圆。反之,这个参数设置太大的话,某些圆就不能被检测出来了。
第六个参数,double类型的param1,有默认值100。它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示传递给canny边缘检测算子的高阈值,而低阈值为高阈值的一半。
第七个参数,double类型的param2,也有默认值100。它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示在检测阶段圆心的累加器阈值。它越小的话,就可以检测到更多根本不存在的圆,而它越大的话,能通过检测的圆就更加接近完美的圆形了。
第八个参数,int类型的minRadius,有默认值0,表示圆半径的最小值。
第九个参数,int类型的maxRadius,也有默认值0,表示圆半径的最大值。

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/jiyanghao19/article/details/131897249