版权声明:归所有菜鸟所有 https://blog.csdn.net/weixin_41752475/article/details/89295741
霍夫直线检测
参数说明:
cv::HoughLinesP(
InputArray src, // 输入图像(8位灰度图像)
OutputArray lines, // 输出直线两点坐标(vector<Vec4i>)
double rho, // 生成极坐标时候的像素扫描步长
double theta, //生成极坐标时候的角度步长(一般取CV_PI/180)
int threshold, // 累加器阈值,获得足够交点的极坐标点才被看成是直线
double minLineLength=0;// 直线最小长度
double maxLineGap=0;// 直线最大间隔
)
示例:
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat src, dst;
src = imread("3.jpg");
if (src.empty())
{
printf("can not load image \n");
return -1;
}
cvNamedWindow("input", CV_WINDOW_AUTOSIZE);
imshow("input", src);
dst = Mat::zeros(src.size(), src.type());
cvtColor(src, dst, CV_RGB2GRAY);
Canny(dst, dst, 0, 200);
vector<Vec4i> plines;
HoughLinesP(dst, plines, 1, CV_PI / 180, 80, 10, 10);
for (size_t i = 0; i < plines.size(); i++)
{
Vec4i points = plines[i];
line(src, Point(points[0], points[1]), Point(points[2], points[3]), Scalar(0, 255, 255), 3, CV_AA);
}
cvNamedWindow("output", CV_WINDOW_AUTOSIZE);
imshow("output", src);
waitKey();
return 0;
}
霍夫圆检测
霍夫圆检测对噪声比较敏感,一般要先对图像做中值滤波。
参数说明:
cv::HoughCircles(
InputArray image, // 输入图像 ,必须是8位的单通道灰度图像
OutputArray circles, // 输出结果,即圆信息(圆心+半径)
Int method, // 采用方法:HOUGH_GRADIENT
Double dp, // dp = 1;
Double mindist, // 10 最短距离-可以分辨是两个圆的,否则认为是同心圆:src_gray.rows/8
Double param1, // 用于Canny的边缘阀值上限,下限被置为上限的一半
Double param2, // 中心点累加器阈值
Int minradius, // 最小半径
Int maxradius//最大半径
)
示例:
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat src, dst;
src = imread("line.jpg");
if(src.empty())
{
printf("can not load image \n");
return -1;
}
cvNamedWindow("input", CV_WINDOW_AUTOSIZE);
imshow("input", src);
cvtColor(src,src,CV_RGB2GRAY);
dst = src.clone();
cvtColor(dst,dst,CV_GRAY2RGB);
//中值滤波
medianBlur(src,src,3);
vector<Vec3f> circles;
HoughCircles(src,circles,CV_HOUGH_GRADIENT,1,100,45,30,45,220);
for(size_t i = 0; i < circles.size(); i++)
{
Vec3f c = circles[i];
circle(dst, Point(c[0], c[1]), c[2], Scalar(0,255,255), 3, CV_AA);
}
cvNamedWindow("output", CV_WINDOW_AUTOSIZE);
imshow("output", dst);
waitKey();
return 0;
}
Matlab霍夫椭圆检测
I = imread('C:\Users\sartreck\Desktop\text.jpg');
[m,n,L] = size(I); %m图像的高度,n图像的宽度,L通道数
if L>1
I = rgb2gray(I);
end
BW1 = edge(I,'sobel'); %自动选择阈值用Sobel算子进行边缘检测(二值化)
figure(1)
subplot(211)
imshow(BW1); title('边缘检测');
se = strel('square',2);
BW=imdilate(BW1,se);%图像A1被结构元素B膨胀
hough_circle=zeros(m,n,3);
[Limage, num] = bwlabel(BW,8); %num 连通区域个数
for N=1:num
%[rows,cols] = find(BW); % 找出二值图中的所有非零元素,并将这些元素的线性索引值返回到[rows,cols] 即找出边缘
[rows,cols] = find(Limage==N); % 找出二值图中的所有非零元素,并将这些元素的线性索引值返回到[rows,cols] 即找出边缘
pointL=length(rows); %非零元素个数,椭圆的周长
max_distan=zeros(m,n);
distant=zeros(1,pointL);
for i=1:m
for j=1:n
for k=1:pointL
distant(k)=sqrt((i-rows(k))^2+(j-cols(k))^2); %计算所有点到椭圆边界的点的距离
end
max_distan(i,j)=max(distant); %(i,j)点到椭圆边界的最大距离
end
end
min_distan=min(min(max_distan)); %图像中所有的点到椭圆边界最大距离的最小值,这个最小值对应的坐标位置就是椭圆的中心。
[center_yy,center_xx] = find(min_distan==max_distan); %检索出椭圆中心的位置,
center_y=(min(center_yy)+max(center_yy))/2; %由于计算误差,椭圆中心可能是一簇点,所以选择中心点
center_x=(min(center_xx)+max(center_xx))/2; %center_x,center_y为椭圆的中心
a=min_distan; %a为椭圆的长轴
%% 下面进行Hough变换 %%%%%%
hough_space = zeros(round(a+1),180); %Hough空间
for k=1:pointL
for w=1:180 %theta
G=w*pi/180; %角度转换为弧度
XX=((cols(k)-center_x)*cos(G)+(rows(k)-center_y)*sin(G))^2/(a^2);
YY=(-(cols(k)-center_x)*sin(G)+(rows(k)-center_y)*cos(G))^2;
B=round(sqrt(abs(YY/(1-XX)))+1);
if(B>0&&B<=a) % 计算时,B的值可能很大,这里进行异常处理
hough_space(B,w)=hough_space(B,w)+1;
end
end
end
%% 搜索超过阈值的聚集点
max_para = max(max(max(hough_space))); % 找出累积最大值
[bb,ww] = find(hough_space>=max_para); %找出累积最大值在hough_space位置坐标(坐标值就是b和theta)
if(max_para<=pointL*0.33*0.25) % 如果累积最大值不足一定的阈值则判断不存在椭圆
disp('No ellipse');
return ;
end
b=max(bb); % b为椭圆的短轴
W=min(ww); % %theta
theta=W*pi/180;
%% 标记椭圆
for k=1:pointL
XXX=((cols(k)-center_x)*cos(theta)+(rows(k)-center_y)*sin(theta))^2/(a^2);
YYY=(-(cols(k)-center_x)*sin(theta)+(rows(k)-center_y)*cos(theta))^2/(b^2);
if((XXX+YYY)<=1) %实心椭圆
%if((XXX+YYY)<=1.1&&(XXX+YYY)>=0.99) % 椭圆轮廓
hough_circle(rows(k),cols(k),1) = 255;
end
end
end
subplot(212)
imshow(hough_circle);title('Hough变换');
opencv椭圆检测
.hellipse.h
#pragma once
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/features2d/features2d.hpp" //需要添加该头文件
#include <iostream>
#include <vector>
using namespace cv;
using namespace std;
class Ellipse
{
public:
void Computer_axy(vector<Point> contour, Size imgsize);
int hough_ellipse(vector<Point> contour);
Mat draw_Eliipse(Mat);
private:
double a; //半长轴
double b; //短轴
double theta; //椭圆的旋转角度
Point point_center; //椭圆中心的坐标
};
inline void Ellipse::Computer_axy(vector<Point> contour, Size imgsize)
{
float Ly, Lx, LL;
double maxVal;
Mat distance(1, contour.size(), CV_32FC1); //每一点到轮廓的所有距离
Mat max_distance(imgsize, CV_32FC1, Scalar(0)); //每一点到轮廓的最大距离
for (int i = 0; i < max_distance.rows; i++)
{
for (int j = 0; j < max_distance.cols; j++)
{
for (int n = 0; n < contour.size(); n++)
{
Ly = (i - contour.at(n).y)*(i - contour.at(n).y);
Lx = (j - contour.at(n).x)*(j - contour.at(n).x);
LL = sqrt(Ly + Lx);
distance.at<float>(n) = LL;
}
minMaxLoc(distance, NULL, &maxVal, NULL, NULL);
max_distance.at<float>(i, j) = maxVal;
}
}
double minVal = 0; //最大值一定要赋初值,否则运行时会报错
Point minLoc;
minMaxLoc(max_distance, &minVal, NULL, &minLoc, NULL);
a = minVal;
point_center = minLoc;
}
inline int Ellipse::hough_ellipse(vector<Point> contour)
{
double G, XX, YY;
int B;
Mat hough_space(floor(a + 1), 180, CV_8UC1, Scalar(0)); //高度:a,宽度180
for (int k = 0; k < contour.size(); k++)
{
for (int w = 0; w < 180; w++)
{
G = w * CV_PI / 180; //角度转换为弧度
XX = pow(((contour.at(k).y - point_center.y)*cos(G) + (contour.at(k).x - point_center.x)*sin(G)), 2) / (a*a);
YY = pow((-(contour.at(k).y - point_center.y)*sin(G) + (contour.at(k).x - point_center.x)*cos(G)), 2);
B = floor(sqrt(abs(YY / (1 - XX))) + 1);
if (B > 0 && B <= a)
{
hough_space.at<uchar>(B, w) += 1;
}
}
}
double Circumference;
double maxVal = 0; //最大值一定要赋初值,否则运行时会报错
Point maxLoc;
minMaxLoc(hough_space, NULL, &maxVal, NULL, &maxLoc);
b = maxLoc.y;
theta = maxLoc.x;
Circumference = 2 * CV_PI*b + 4 * (a - b);
return maxVal;
}
inline Mat Ellipse::draw_Eliipse(Mat src)
{
cout << "长轴:" << a << endl;
cout << "短轴:" << b << endl;
cout << "椭圆中心:" << point_center << endl;
cout << "theta:" << theta << endl;
ellipse(src, point_center, Size(b, a), theta, 0, 360, Scalar(0, 255, 0), 3);
return src;
}
.cpp
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/features2d/features2d.hpp" //需要添加该头文件
#include <iostream>
#include <vector>
#include "Math.h"
#include "ellipse.h"
using namespace cv;
using namespace std;
int main()
{
Mat src = imread("text.jpg");
if (!src.data)
{
cout << "Read image error" << endl;
return -1;
}
Mat dst;
cvtColor(src, dst, CV_RGB2GRAY);
//GaussianBlur(dst, dst, Size(3, 3), 0, 0); //高斯模糊(Gaussian Blur)
Canny(dst, dst, 100, 200, 3); //Canny边缘检测
namedWindow("Canny", CV_WINDOW_AUTOSIZE);
imshow("Canny", dst);
//提取轮廓************************************************
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(dst, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
//Hough变换************************************************
int accumulate; // Hough空间最大累积量
Ellipse myellipse;
Mat result(src.size(), CV_8UC3, Scalar(0));
for (int i = 0; i < contours.size(); i++)
{
myellipse.Computer_axy(contours[i], dst.size());
accumulate = myellipse.hough_ellipse(contours[i]);
if (accumulate >= contours[i].size()*0.25) // 判断是否超过给定阈值,判断是否为椭圆
result = myellipse.draw_Eliipse(src);
else
{
cout << "This profile is not an ellipse" << endl;
break;
}
}
namedWindow("Hough_result", CV_WINDOW_AUTOSIZE);
imshow("Hough_result", result);
waitKey();
return 0;
}