数字图像处理(DIP)实验3 图像特征检测

数字图像处理(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;
}

结果

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值