Canny是边缘检测算法
步骤:
高斯模糊 - GaussianBlur
灰度转换 - cvtColor
计算梯度 – Sobel/Scharr
非最大信号抑制
高低阈值输出二值图像
cv::Canny
Canny( InputArray src, //
8-bit的输入图像 OutputArray edges,// 输出边缘图像, 一般都是二值图像,背景是黑色 double threshold1,// 低阈值,常取高阈值的1/2或者1/3 double threshold2,// 高阈值 int aptertureSize,// Soble算子的size,通常3x3,取值3 bool L2gradient // 选择 true表示是L2来归一化,否则用L1归一化 )
#include<iostream>
#include<opencv2/opencv.hpp>
#include<cmath>
using namespace std;
using namespace cv;
Mat src,dst,gray_src,temp;
int main(){
src=imread("D:/opencv/2/a.jpg");
if(!src.data){
printf("could not load image...\n");
return -1;
}
imshow("input",src);
cvtColor(src,gray_src,COLOR_BGR2GRAY);
blur(gray_src,gray_src,Size(3,3),Point(-1,-1),BORDER_DEFAULT);
Canny(gray_src,dst,124,248,3,false);
Mat kernel= getStructuringElement(MORPH_RECT,Size(5,5),Point(-1,-1));
morphologyEx(dst,dst,MORPH_DILATE,kernel);
imshow("output",~dst);
waitKey(0);
return 0;
}
霍夫变换-直线
Hough Line Transform用来做直线检测
前提条件 – 边缘检测已经完成
平面空间到极坐标空间转换
标准的霍夫变换 cv::HoughLines从平面坐标转换到霍夫空间,表示极坐标空间
霍夫变换直线概率 cv::HoughLinesP最终输出是直线的两个点
cv::HoughLines
( InputArray src, // 输入图像,必须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
( InputArray src, // 输入图像,必须8-bit的灰度图像 OutputArray lines, // 输出的极坐标来表示直线 double rho, // 生成极坐标时候的像素扫描步长 double theta, //生成极坐标时候的角度步长,一般取值CV_PI/180 int threshold, // 阈值,只有获得足够交点的极坐标点才被看成是直线 double minLineLength=0;// 最小直线长度 double maxLineGap=0;// 最大间隔 )
#include<iostream>
#include<opencv2/opencv.hpp>
#include<cmath>
#include<vector>
using namespace std;
using namespace cv;
Mat src,dst,gray_src,temp;
int LineGapValue=0;
const int LineGapMax=100;
Scalar color=Scalar(0,0,255);
Vec4f hline;
vector<Vec4f> plines;
void HoughLine(int,void*);
int main(){
src=imread("D:/opencv/2/a.jpg");
if(!src.data){
printf("could not load image...\n");
return -1;
}
imshow("input",src);
//提取边缘
Canny(src,gray_src,100,200,3,false);
cvtColor(gray_src,dst,COLOR_GRAY2BGR);
imshow("Canny",gray_src);
namedWindow("output");
createTrackbar("LineGap","output",&LineGapValue,LineGapMax,HoughLine);
HoughLine(0,0);
waitKey(0);
return 0;
}
void HoughLine(int,void*){
cvtColor(gray_src,dst,COLOR_GRAY2BGR);
HoughLinesP(gray_src,plines,1,CV_PI/180,10,0,LineGapValue);//最后一个参数代表 像素距离多少以内表示在一条直线内
for(size_t i=0;i<plines.size();i++){
hline = plines[i];
line(dst,Point(hline[0],hline[1]),Point(hline[2],hline[3]),color,3,LINE_AA);
}
imshow("output",dst);
}
霍夫圆变换
cv::HoughCircles
因为霍夫圆检测对噪声比较敏感,所以首先要对图像做中值滤波。 基于效率考虑,Opencv中实现的霍夫变换圆检测是基于图像梯度的实现,分为两步:
1. 检测边缘,发现可能的圆心
2. 基于第一步的基础上从候选圆心开始计算最佳半径大小
HoughCircles( InputArray image, // 输入图像 ,必须是8位的单通道灰度图像 OutputArray circles, // 输出结果,发现的圆信息 Int method, // 方法 - HOUGH_GRADIENT Double dp, // dp = 1; Double mindist, // 10 最短距离-可以分辨是两个圆的,否则认为是同心圆- src_gray.rows/8 Double param1, // canny edge detection low threshold Double param2, // 中心点累加器阈值 – 候选圆心 Int minradius, // 最小半径 Int maxradius//最大半径 )
#include<iostream>
#include<opencv2/opencv.hpp>
#include<cmath>
#include<vector>
using namespace std;
using namespace cv;
Mat src,dst,gray_src,temp;
int main(){
src=imread("D:/opencv/2/a.jpg");
if(!src.data){
printf("could not load image...\n");
return -1;
}
imshow("input",src);
GaussianBlur(src,temp,Size(3,3),0,0);
//medianBlur(src,temp,3);
cvtColor(temp,gray_src,COLOR_BGR2GRAY);
vector<Vec3f>PCircle;
//霍夫检测
imshow("gray",gray_src);
//方法默认
HoughCircles(gray_src,PCircle,HOUGH_GRADIENT,1,10,100,30,5,25);
src.copyTo(dst);
for(size_t i=0;i<PCircle.size();i++){
Vec3f circle=PCircle[i];
cv::circle(dst,Point(circle[0],circle[1]),circle[2],Scalar(0,0,255),3,LINE_AA);
//看圆心
cv::circle(dst,Point(circle[0],circle[1]),2,Scalar(255,0,0),3,LINE_AA);
}
imshow("output",dst);
waitKey(0);
return 0;
}
目录