数字图像处理(DIP)实验3 图像特征检测
数字图像处理课程相关文章 传送门
https://blog.csdn.net/qq_46164507/article/details/122503851
博文说明
本文所使用代码或多或少参考了以往博文的同类or相似文章的代码,并非纯原创
本文仅用于记录并提供一种代码思路,供大家参考
正文
要求
代码
运行环境:Ubuntu16.04 LTS + OpenCV 3.0.4 + ROS-kinetic-full
代码语言:c++
/*
*edition:1
*remain:代码可行,速度过慢
*time:2021年10月28日09:57:04
*/
#include <stdlib.h>
#include <iostream>
#include <math.h>
#include <cv.h>
#include <highgui.h>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include "ros/ros.h"
#include "std_msgs/String.h"
#include "std_msgs/Float32.h"
#include "std_msgs/Bool.h"
#include "geometry_msgs/Twist.h"
#include "sensor_msgs/Image.h"
#define LINEAR_X 0
#define pi 3.1415926
using namespace cv;
using namespace std;
typedef struct line
{
double angle;
int dist;
}LINE;
typedef struct CIRCLE
{
int x_center;
int y_center;
int r;
}Circle;
void GUassian_Template_Generater(int n,double sigma,double **tem)
{
tem = new double*[n];
for(int i=0;i<n;i++)
{
tem[i] = new double[n];
}
int xi = (n-1)/2;
int yi = xi;
double xi_2 = 0;
double yi_2 = 0;
double sum = 0;
for(int i= 0;i<n;i++)
{
for(int j= 0;j<n;j++)
{
xi_2 = pow(i-xi,2);
yi_2 = pow(j-yi,2);
tem[i][j] = exp((xi_2+yi_2)/pow(sigma,2));
sum += tem[i][j];
cout<<tem[i][j]<<endl;
}
}
for(int i = 0;i<n;i++)
{
for(int j = 0;j<n;j++)
{
tem[i][j] /=sum;
cout<<tem[i][j]<<endl;
}
}
}
void Guassian_filter(Mat input,Mat output,double sigma,int n)
{
double** tem;
tem = new double*[n];
for(int i=0;i<n;i++)
{
tem[i] = new double[n];
}
int xi = (n-1)/2;
int yi = xi;
double xi_2 = 0;
double yi_2 = 0;
double sum = 0;
for(int i= 0;i<n;i++)
{
for(int j= 0;j<n;j++)
{
xi_2 = pow(i-xi,2);
yi_2 = pow(j-yi,2);
tem[i][j] = exp((xi_2+yi_2)/pow(sigma,2));
sum += tem[i][j];
}
}
for(int i = 0;i<n;i++)
{
for(int j = 0;j<n;j++)
{
tem[i][j] /=sum;
}
}
int m = (n-1)/2;
int rows = input.rows;
int cols = input.cols;
for(int i=0;i<rows;i++)
{
for(int j=0;j<cols;j++)
{
double sum = 0;
for(int xj = i-m;xj<=i+m;xj++)
{
for(int yj =j-m;yj<=j+m;yj++)
{
if(xj<0||xj>=rows||yj<0||yj>=cols)
{
continue;
}
sum += input.at<uchar>(xj,yj)*tem[xj-i+m][yj-j+m];
}
}
output.at<uchar>(i,j) = uchar(sum);
}
}
}
void EdgeDetector(Mat input,Mat output)
{
//Guassian_filter(input,output,1,3);
int** sobelx;
int** sobely;
sobelx = new int*[3];
sobely = new int*[3];
for(int i=0;i<3;i++)
{
sobelx[i] = new int[3];
sobely[i] = new int[3];
}
//sobel
Mat output1 = output.clone();
sobelx[0][0] = -1;
sobelx[0][1] = 0;
sobelx[0][2] = 1;
sobelx[1][0] = -2;
sobelx[1][1] = 0;
sobelx[1][2] = 2;
sobelx[2][0] = -1;
sobelx[2][1] = 0;
sobelx[2][2] = 1;
sobely[0][0] = 1;
sobely[0][1] = 2;
sobely[0][2] = 1;
sobely[1][0] = 0;
sobely[1][1] = 0;
sobely[1][2] = 0;
sobely[2][0] = -1;
sobely[2][1] = -2;
sobely[2][2] = -1;
int rows = input.rows;
int cols = input.cols;
double** angle;
angle= new double*[rows-2];
for(int i=0;i<rows-2;i++)
{
angle[i] = new double[cols-2];
}
for(int i=1;i<rows-1;i++)
{
for(int j=1;j<cols-1;j++)
{
double Gx = 0;
double Gy = 0;
for(int xj = i-1;xj<=i+1;xj++)
{
for(int yj =j-1;yj<=j+1;yj++)
{
Gx += output1.at<uchar>(xj,yj)*sobelx[xj-i+1][yj-j+1];
Gy += output1.at<uchar>(xj,yj)*sobely[xj-i+1][yj-j+1];
}
}
angle[i-1][j-1] = atan(Gy/Gx);
output.at<uchar>(i,j) = uchar(sqrt(pow(Gx,2)+pow(Gy,2))/6.0);
}
}
//not maximum suppression
Mat output2 = output.clone();
for(int i=1;i<rows-1;i++)
{
for(int j=1;j<cols-1;j++)
{
if(-pi/8<angle[i-1][j-1]<pi/8)
{
if(output2.at<uchar>(i,j) < output2.at<uchar>(i,j-1))
{
output.at<uchar>(i,j)=0;
continue;
}
else if(output2.at<uchar>(i,j) < output2.at<uchar>(i,j+1))
{
output.at<uchar>(i,j)=0;
continue;
}
}
if(pi/8<angle[i-1][j-1]<3*pi/8)
{
if(output2.at<uchar>(i,j) < output2.at<uchar>(i-1,j+1))
{
output.at<uchar>(i,j)=0;
continue;
}
else if(output2.at<uchar>(i,j) < output2.at<uchar>(i+1,j-1))
{
output.at<uchar>(i,j)=0;
continue;
}
}
if(3*pi/8<angle[i-1][j-1]<pi/2||-pi/2<angle[i-1][j-1]<-3*pi/8)
{
if(output2.at<uchar>(i,j) < output2.at<uchar>(i-1,j))
{
output.at<uchar>(i,j)=0;
continue;
}
else if(output2.at<uchar>(i,j) < output2.at<uchar>(i+1,j))
{
output.at<uchar>(i,j)=0;
continue;
}
}
if(-3*pi/8<angle[i-1][j-1]<-pi/8)
{
if(output2.at<uchar>(i,j) < output2.at<uchar>(i-1,j-1))
{
output.at<uchar>(i,j)=0;
continue;
}
else if(output2.at<uchar>(i,j) < output2.at<uchar>(i+1,j+1))
{
output.at<uchar>(i,j)=0;
continue;
}
}
}
}
//double threshould
Mat output3 = output.clone();
uchar TH = 70;
uchar TL = 40;
int flag = 0;
for(int i=1;i<rows-1;i++)
{
for(int j=1;j<cols-1;j++)
{
flag = 0;
if(output3.at<uchar>(i,j)<=TL)
{
output.at<uchar>(i,j) = 0;
continue;
}
if(output3.at<uchar>(i,j)>=TH)
{
output.at<uchar>(i,j) = 255;
continue;
}
if(TL<output3.at<uchar>(i,j)<TH)
{
for(int x=-1;x<=1;x++)
{
for(int y=-1;y<=1;y++)
{
if(output3.at<uchar>(i+x,j+y)>=TH)
{
output.at<uchar>(i,j) = 255;
flag = 1;
break;
}
}
if(flag ==1)
{
break;
}
}
if(flag == 0)
{
output.at<uchar>(i,j) = 0;
}
}
}
}
}
void Hough_Line(Mat input,Mat output) {
vector<Vec2f> lines;
Mat dst_canny;
output=input.clone();
float rho=10;float theta=pi/180; int threshold=705;
cv::Canny(output, dst_canny, 50, 200, 3);
imshow("2_edge",dst_canny);
cv::HoughLines(dst_canny, lines, rho, theta, threshold, 0, 0);
for( size_t i = 0; i < lines.size(); i++ )
{
//提取出距离和角度
float rho = lines[i][0], theta = lines[i][1];
//定义两个点,两点确定一条直线
//计算得到的两点的坐标为(ρcosθ-1000sinθ,ρsinθ+1000cosθ),(ρcosθ+1000sinθ,ρsinθ-1000cosθ)
Point pt1, pt2;
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
pt1.x = cvRound(x0 + 1000*(-b));
pt1.y = cvRound(y0 + 1000*(a));
pt2.x = cvRound(x0 - 1000*(-b));
pt2.y = cvRound(y0 - 1000*(a));
//在原图上画宽带为2的红线
cv::line( output, pt1, pt2, Scalar(0,255,255),2);
}
// namedWindow( "lines", CV_WINDOW_AUTOSIZE );
imshow( "line_output", output );
}
void Hough_Circle(Mat input,Mat output)
{
EdgeDetector(input,output);
int rows = output.rows;
int cols = output.cols;
int r_min = 100/2.0;
int r_max = 0;
double interval = 1.0;
int theta_min = 0;
int theta_max = 360.0;
if(rows>cols)
{
r_max = int(rows)/2.0;
}
else
{
r_max = int(cols)/2.0;
}
// cout<<r_max<<endl;
vector<int**> Hough_Area(rows);
for(int i=0;i<rows;i++)
{
Hough_Area[i] = new int*[cols];
for(int j=0;j<cols;j++)
{
Hough_Area[i][j] = new int[r_max-r_min];
}
}
for(int i=0;i<rows;i++)
{
for(int j=0;j<cols;j++)
{
for(int r = 0;r<r_max-r_min;r++)
{
Hough_Area[i][j][r] = 0;
}
}
}
for(int i=0;i<rows;i++)
{
for(int j=0;j<cols;j++)
{
if(output.at<uchar>(i,j)==0)
{
continue;
}
for(int r=0;r<r_max-r_min;r++)
{
for(int theta = 0;theta<360;theta++)
{
int x_center = int(j - (r+r_min)*cos(theta*pi/180.0));
int y_center = int(i - (r+r_min)*sin(theta*pi/180.0));
if(x_center<=0||y_center<=0||x_center>=rows||x_center>=cols||y_center>=rows||y_center>=cols)
{
continue;
}
Hough_Area[x_center][y_center][r] +=1;
}
}
}
}
int thres = 85;
Circle circle1[5000];
int circle_num = 0;
for(int row=0;row<rows;row++)
{
for(int col=0;col<cols;col++)
{
for(int r=0;r<r_max-r_min;r++)
{
if(Hough_Area[row][col][r]>thres)
{
if(circle_num>=20)break;
circle1[circle_num].x_center = row;
circle1[circle_num].y_center = col;
circle1[circle_num].r = r+r_min;
circle_num+=1;
// cout<<circle_num<<endl;
}
}
}
}
// cout<<circle_num<<endl;
Mat mat_circle = input.clone();
for(int i=0;i<circle_num;i++)
{
circle(mat_circle,Point(circle1[i].x_center,circle1[i].y_center
),circle1[i].r,Scalar(0,0,255),2);
}
output=mat_circle.clone();
imshow("circle_output",mat_circle);
// imshow("canny",output);
output=mat_circle;
}
int main(int argc,char** argv)
{
ROS_WARN("*****Start");
ros::init(argc,argv,"trafficLaneTrack");
ros::NodeHandle n;
ros::Rate loop_rate(10);
ros::Publisher pub = n.advertise<geometry_msgs::Twist>("/smoother_vel",5);
VideoCapture capture;
capture.open(0);
waitKey(1000);
if(!capture.isOpened())
{
printf("capture isn't opened!");
return 0;
}
Mat frame;
int nFrames = 0;
int frameWidth = capture.get(CV_CAP_PROP_FRAME_WIDTH);
int frameHeight = capture.get(CV_CAP_PROP_FRAME_HEIGHT);
Mat edge_output;
Mat circle_output;
Mat line_output;
//edge
Mat src1 = imread("./src/img_pkg_3/src/1.png");
Mat gray1;
cvtColor(src1,gray1,COLOR_BGR2GRAY);
edge_output = gray1.clone();
EdgeDetector(gray1,edge_output);
imshow("1_gray",gray1);
imshow("edge_output",edge_output);
//line
Mat src2 = imread("./src/img_pkg_3/src/2.png");
Mat gray2;
cvtColor(src2,gray2,COLOR_BGR2GRAY);
line_output = gray2.clone();
Hough_Line(gray2,line_output) ;
imshow("2_gray",gray2);
// imshow("line_output",line_output);
//circle
Mat src3 = imread("./src/img_pkg_3/src/4.png");
Mat gray3;
cvtColor(src3,gray3,COLOR_BGR2GRAY);
circle_output = gray3.clone();
Hough_Circle(gray3,circle_output);
imshow("3_gray",gray3);
// imshow("circle_output",circle_output);
while(ros::ok())
{
capture.read(frame);
if(frame.empty())
{
break;
}
ros::spinOnce();
waitKey(5);
}
return 0;
}