OpenCV学習の基本的な画像操作(12):ハフ変換

ハフ変換

極座標

x = \ rho cos \ Theta \ \、\ \ y = \ rho sin \ Theta \\ \ rho ^ 2 = x ^ 2 + y ^ 2、tan \ Theta = \ frac {y} {x}(x \ neq 0)

ライン検出 

プロセスステップ:

  • 極座標を介して、空間座標のポイントを極座標空間(ハフ空間)に変換します
  • ハフ空間の交点で表される線は、これらの点が配置されている線です。
  • 次に、極座標を使用して、ハフ空間でハフによって選択されたポイントを逆に変換して、長方形座標の直線に戻します。

y = ax + b \\ y =(-\ frac {cos \ Theta} {sin \ Theta})x +(\ frac {r} {sim \ Theta})\\ r_ \ Theta = x_0 \ cdot cos \ Theta + y_0 \ cdot sin \ Theta

円の検出

プロセスステップ

  •  ハフサークルの検出は画像のソルトアンドペッパーノイズに対してより敏感であるため、最初に画像に対してメディアンフィルタリングを実行します
  • キャニーエッジ検出を実行し、最初にエッジである可能性のあるポイントを除外します
  • パラメトリック方程式を使用して、カルテシアン座標系を極座標系に変換します

              \ frac {(xa)^ 2} {R} + \ frac {(yb)^ 2} {R} = 1 \\ \ left \ {\ begin {matrix} x = a + Rcos \ Theta \\ y = b + Rsin \ Theta \ end {matrix} \ right。

  • 各ピクセルが中心(a、b)であると仮定し、(a、b)を決定した後、θとRを変更して複数の円を描画し、これらの円が1点で交差する場合、それは円の中心であり、半径は複数ある場合があります(これらのポイントからこのポイントまでの距離によって決定されます)

APIの紹介

ライン検出

HoughLines(
InputArray src,//输入图像,必须是8-bit的灰度图
OutputArray lines,//输出图像,是极坐标形式的直线
double rho,//生成极坐标时候的像素扫描步长,以像素为单位的距离步长。
double theta,//生成极坐标时候的角度扫描步长,以弧度为单位的角度步长。
int threshold,//阈值,只有获得足够交点的极坐标才会被视为是一条有效的直线
double srn=0,//默认值为0,用于在多尺度霍夫变换中作为参数rho的除数,rho=rho/srn。
double stn=0,//默认值为0,用于在多尺度霍夫变换中作为参数theta的除数,theta=theta/stn。
double min_theta,//表示角度扫描范围0~180之间,默认即可
double max_theta = CV_PI//
)
//需要自己将他反变换回直角坐标系中

HoughLinesP
(
InputArray src,//输入图像,必须是8-bit的灰度图
OutputArray lines,//输出直线,是直角坐标形式的直线
double rho,//生成极坐标时候的像素扫描步长
double theta,//生成极坐标时候的角度扫描步长,通常取CV_PI/180
double minLineLength = 0,//最小直线长
double maxLineGap = 0,//最大间隔,即直线与直线之间的间隔 
)
//直接返回直角坐标系中的直线

円の検出

HoughCircles(
    InputArray src,//输入图像,必须是8-bit的灰度图
    OutputArray lines,//输出结果,发现圆的信息
    Int method,//方法 HOUGH_GRADENT 基于梯度的
    Double dp,//dp = 1 ,DIP,即尺度
    Double mindist,//两个圆弧相隔的最短距离,比这个距离小就认为是同一个圆,大于则认为是同心圆
    Double param1,//canny的弱边缘阈值
    Double param2,//中心点累加器的阈值,即有多数个像素在同一弧度上,才判断为圆,设定此值需要参考半径
    Int minradiux,//最小半径
    Int maxradiux,//最大半径
)

コードと練習

ライン検出


#include <iostream>
#include <math.h>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
	//src = imread("src.jpg");
	Mat src = imread("1.PNG");
	Mat edge_img;
	if (!src.data)
	{
		cout << "cannot open image" << endl;
		return -1;
	}
	Mat gray_src;
	cvtColor(src, gray_src, COLOR_BGR2GRAY);
	Canny(src, edge_img, 150, 250);
	
	
	imshow("edge image", edge_img);

	vector<Vec4f> plines;
	//创建向量存储检测结果
	HoughLinesP(edge_img, plines, 1, CV_PI/180.0, 10, 0, 5);
	//检测直线
	Scalar color = Scalar(0, 0, 255);

	for (size_t i = 0; i < plines.size(); i++)
	{
		Vec4f hline = plines[i];
		line(gray_src, Point(hline[0], hline[1]), Point(hline[2], hline[3]), color, 3, LINE_AA);
	}
	imshow("OUTPUT", gray_src);
	
	waitKey(0);
	
	return 0;
}

#include <iostream>
#include <math.h>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;


int main(int argc, char* argv[])
{
	Mat src = imread("5.jpg");
	//Mat src = imread("1.PNG");
	Mat edge_img;
	if (!src.data)
	{
		cout << "cannot open image" << endl;
		return -1;
	}

	Mat moutput;
	medianBlur(src, moutput,3);
	cvtColor(moutput, moutput, COLOR_BGR2GRAY);


	vector<Vec3f> pcircles;
	//创建向量存储检测结果
	HoughCircles(moutput, pcircles, HOUGH_GRADIENT, 1, 15, 30, 35, 15, 50);
	//检测圆
	Scalar color = Scalar(0, 255, 0);
	for (size_t i = 0; i < pcircles.size(); i++)
	{
		Vec3f cc = pcircles[i];
		circle(src, Point(cc[0], cc[1]), cc[2], color, 2);
		circle(src, Point(cc[0], cc[1]), 2, color, 2);
	}
	imshow("OUTPUT", src);
	
	waitKey(0);
	
	return 0;
}

おすすめ

転載: blog.csdn.net/fan1102958151/article/details/107448800