实现步骤:
(1)高斯模糊
(2)边缘梯度
(3)综合梯度
(4)依据梯度方向做非极大值抑制
(5)使用上下阈值检测边缘
(6)连接边缘
canny.cpp#include "iostream"
#include "opencv2/opencv.hpp"
#include "imgproc.h"
#include "characterproc.h"
using namespace cv;
using namespace std;
int main()
{
//1,读取图像
String img_path = "/home/whf/PycharmProjects/Tool/data/motion_data/trafficcone_src/10.jpg";
Mat img_src = imread(img_path);
Mat img_gray = Mat(img_src.rows,img_src.cols,CV_8UC1,Scalar(0));
//1.1 灰度变换
img_gray = rgb2gray(img_src,"eyeperception");
//2,高斯模糊
Mat img_gauss = gaussproc(img_gray);
//3,求梯度
Mat xy_grad = Mat(img_src.rows,img_src.cols,CV_8UC1,Scalar(0));
Mat th_gra = Mat(img_src.rows,img_src.cols, CV_8UC1, Scalar(0));
xy_grad = xy_gradient(img_gauss);
//imshow("th_gra",th_gra);
//4,梯度的非极大值抑制
Mat img_nms = Mat(img_src.rows,img_src.cols,CV_8UC1,Scalar(0));
img_nms = grad_nms(xy_grad);
//5,使用上下阈值检测边缘
Mat img_thresh = Mat(img_src.rows,img_src.cols,CV_8UC1,Scalar(0));
img_thresh = double_thresh(img_nms, 60, 100);
imshow("img_thresh",img_thresh);
//6,抑制独立的弱边缘
Mat img_link = Mat(img_src.rows,img_src.cols,CV_8UC1,Scalar(0));
img_link = link_eage(img_thresh);
imshow("img_link",img_link);
waitKey(0);
return 0;
}
imgproc.cpp#include "imgproc.h"
#include "characterproc.h"
#include "gauss.h"
#include "assert.h"
using namespace cv;
Mat rgb2gray(Mat rgb_img, string type)
{
Mat img_src = rgb_img.clone();
int cols = rgb_img.cols;
int rows = rgb_img.rows;
Mat img = Mat(rows, cols, CV_8UC1, Scalar(0));
if(stringisequal(type, "eyeperception"))
{
for(int i = 0; i<rows; i++)
{
for(int j = 0; j<cols; j++)
{
Vec3b pix = img_src.at<Vec3b>(i,j);
img.at<uchar>(i,j) = (pix[0]*0.114 + pix[1]*0.55 + pix[2]*0.34);
}
}
return img;
}
if(stringisequal(type, "avg"))
{
for(int i = 0; i<cols; i++)
{
for(int j = 0; j<rows; j++)
{
Vec3b pix = rgb_img.at<Vec3b>(i,j);
img.at<uchar>(i,j) = (pix[0] + pix[1] + pix[2])/3;
}
}
return img;
}
}
Mat gaussproc(Mat img)
{
int c = img.channels();
assert(c == 1);
Mat img_src = img.clone();
int cols = img_src.cols;
int rows = img_src.rows;
Mat img_gauss(rows, cols, CV_8UC1, Scalar(0));
float **ker = gauss_kernel(3, 0.01);
//padding
Mat img_pad = Mat(rows+2, cols+2, CV_8UC1, Scalar(0));
img_src.copyTo(img_pad(Rect(1,1,cols,rows)));
for(int i=0; i < rows; i++)
{
for(int j=0;j<cols;j++)
{
img_gauss.at<uchar>(i,j) = ker[0][0]*img_pad.at<uchar>(i-1,j-1) + ker[0][1]*img_pad.at<uchar>(i-1,j) + ker[0][2]*img_pad.at<uchar>(i-1,j+1)
+ ker[1][0]*img_pad.at<uchar>(i,j-1) + ker[1][1]*img_pad.at<uchar>(i,j) + ker[1][2]*img_pad.at<uchar>(i,j+1)
+ ker[2][0]*img_pad.at<uchar>(i+1,j+1) + ker[2][1]*img_pad.at<uchar>(i+1,j) + ker[2][2]*img_pad.at<uchar>(i+1,j+1);
}
}
delete_kernel(ker,3);
return img_gauss;
}
Mat x_gradient(Mat img)
{
Mat img_src = img.clone();
int cols = img_src.cols;
int rows = img_src.rows;
Mat x_gra = Mat(rows, cols, CV_8UC1, Scalar(0));
for(int i = 0; i < rows-1; i++)
{
for (int j = 0; j < cols-1; j++)
{
x_gra.at<uchar>(i,j) = abs(img_src.at<uchar>(i,j) -img_src.at<uchar>(i+1,j) + img_src.at<uchar>(i,j+1) -img_src.at<uchar>(i+1,j+1) )/2;
}
}
return x_gra;
}
Mat y_gradient(Mat img)
{
Mat img_src = img.clone();
int cols = img_src.cols;
int rows = img_src.rows;
Mat y_gra = Mat(rows, cols, CV_8UC1, Scalar(0));
for(int i = 0; i < rows-1; i++)
{
for (int j = 0; j < cols-1; j++)
{
y_gra.at<uchar>(i,j) = abs(img_src.at<uchar>(i,j) - img_src.at<uchar>(i,j+1) + img_src.at<uchar>(i+1,j) - img_src.at<uchar>(i+1,j+1));
}
}
return y_gra;
}
Mat xy_gradient(Mat img)
{
Mat img_src = img.clone();
int cols = img_src.cols;
int rows = img_src.rows;
Mat x_gra = x_gradient(img_src);
Mat y_gra = y_gradient(img_src);
Mat xy_gra = Mat(rows, cols, CV_8UC1, Scalar(0));
for(int i = 0; i < rows-1; i++)
{
for (int j = 0; j < cols-1; j++)
{
//if(y_gra.at<uchar>(i,j)==0) y_gra.at<uchar>(i,j)=1;
//th_gra = atan(abs(x_gra.at<uchar>(i,j))/abs(y_gra.at<uchar>(i,j)))*57.3 + 90;
xy_gra.at<uchar>(i,j) = sqrt( (x_gra.at<uchar>(i,j) * x_gra.at<uchar>(i,j)) + (y_gra.at<uchar>(i,j) * y_gra.at<uchar>(i,j)) );
if (xy_gra.at<uchar>(i,j)>255) xy_gra.at<uchar>(i,j)=255;
//if (xy_gra.at<uchar>(i,j)<200) xy_gra.at<uchar>(i,j)=0;
}
}
return xy_gra;
}
Mat grad_nms(Mat img)
{
Mat img_src = img.clone();
int cols = img_src.cols;
int rows = img_src.rows;
Mat gra_nms = Mat(rows, cols, CV_8UC1, Scalar(0));
for (int i = 1; i < rows-1; i++)
{
for(int j = 1; j<cols-1; j++)
{
int val00 = img_src.at<uchar>(i-1,j-1);
int val01 = img_src.at<uchar>(i-1,j);
int val02 = img_src.at<uchar>(i-1,j + 1);
int val10 = img_src.at<uchar>(i,j-1);
int val11 = img_src.at<uchar>(i,j);
int val12 = img_src.at<uchar>(i,j + 1);
int val20 = img_src.at<uchar>(i+1,j-1);
int val21 = img_src.at<uchar>(i+1,j);
int val22 = img_src.at<uchar>(i+1,j + 1);
if(val11<val00 | val11<val01 | val11 < val02 | val11 < val10 | val11<val12 | val11<val21 | val11<val22 | val11 < val20) img_src.at<uchar>(i,j)=0;
}
}
return img_src;
}
Mat double_thresh(Mat img, int minthresh, int maxthresh)
{
Mat img_src = img.clone();
int cols = img_src.cols;
int rows = img_src.rows;
for (int i = 1; i < rows; i++)
{
for(int j = 1; j<cols; j++)
{
if(img_src.at<uchar>(i,j) > maxthresh) img_src.at<uchar>(i,j) = 255;
if(img_src.at<uchar>(i,j) < minthresh) img_src.at<uchar>(i,j) = 0;
}
}
return img_src;
}
Mat link_eage(Mat img)
{
Mat img_src = img.clone();
int cols = img_src.cols;
int rows = img_src.rows;
Mat img_l = Mat(rows, cols, CV_8UC1, Scalar(0));
for(int i = 1; i < rows-1; i++)
{
for(int j = 1; j < cols-1; j++)
{
if((img_src.at<uchar>(i-1,j-1) == 255) | (img_src.at<uchar>(i-1,j) == 255) | (img_src.at<uchar>(i-1, j+1) == 255)
| (img_src.at<uchar>(i, j-1) == 255) | (img_src.at<uchar>(i, j+1) == 255)
| (img_src.at<uchar>(i+1, j-1) == 255) | (img_src.at<uchar>(i+1,j) == 255) | (img_src.at<uchar>(i+1,j+1) == 255))
{
img_l.at<uchar>(i,j) = 255;
}
else
{
img_l.at<uchar>(i,j) = img_src.at<uchar>(i,j);
}
}
}
return img_l;
}
imgproc.h #include "opencv2/opencv.hpp" #include "math.h" using namespace cv; using namespace std; Mat rgb2gray(Mat rgb_img, string type); Mat gaussproc(Mat img); Mat x_gradient(Mat img); Mat y_gradient(Mat img); Mat xy_gradient(Mat img); Mat grad_nms(Mat img); Mat double_thresh(Mat img, int minthresh, int maxthresh); Mat link_eage(Mat img);
gauss.cpp#include <gauss.h>
#include <math.h>
#define pi 3.1415926
using namespace std;
float** gauss_kernel(int k, float sigm)
{
//printf("k: %d, sigm: %f\n",k,sigm);
float **M;
float sum = 0;
M = new float *[k];
for(int i = 0; i < k; i++)
{
M[i] = new float[k];
}
for(int i = -(k-1)/2; i < (k-1)/2+1; i++)
{
for(int j = -(k-1)/2; j < (k-1)/2+1; j++)
{
float f1 = 1./(2*pi*pow(sigm, 2));
float f2 = -(pow(i,2)+pow(j,2));
float f3 = f2/(2*pow(sigm, 2));
M[i+(k-1)/2][j+(k-1)/2] = f1*exp(f3);
sum = sum+M[i+(k-1)/2][j+(k-1)/2];
//printf("%f\t",M[i+(k-1)/2][j+(k-1)/2]);
}
//printf("\n");
}
//归一化
for(int i = 0; i < k; i++)
{
for(int j = 0; j < k; j++)
{
M[i][j] = M[i][j]/sum;
}
}
return M;
}
void delete_kernel(float** M,int k)
{
for(int i = 0; i < k; i++)
{
delete[] M[i];
M[i] = nullptr;
}
delete[] M;
M = nullptr;
}
gauss.h#include "iostream" float** gauss_kernel(int k, float sigm); void delete_kernel(float** M,int k);
characterproc.cpp
#include "characterproc.h"
bool stringisequal(string A, string B)
{
int lenA = A.length();
int lenB = B.length();
if(lenA!=lenB) return false;
for(int i = 0; i<lenA; i++)
{
if(A[i]!=B[i]) return false;
}
return true;
}
#include "iostream" using namespace std; bool stringisequal(string A, string B);
来源:https://www.cnblogs.com/zhibei/p/12201452.html