雷达相机标定(二)-----图像提取角点

6 篇文章 0 订阅


点云提取角点: https://blog.csdn.net/xx970829/article/details/123233029

思路

本文目的为提取红外图像中的角点,据红外热像仪成像特性对角点处进行了简单处理,然后识别其角点和轮廓,最后从多个角点中区分出标定板角点。

源码

//--------------------------------------------------------------------------------------------
//   source /home/xx/catkin_ws/devel/setup.bash && rosrun my_cam_lidar_calib  image 1.png
//
//     提取图像中的标定板
//--------------------------------------------------------------------------------------------

#include <iostream>
#include <string>
//图像类
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;
using namespace std;

void contourExtraction(cv::Mat image, cv::Mat otsuMat, cv::Mat matContours,int row,int col);
void cornerDetection(cv::Mat grayMat,cv::Mat image,vector<Point2f> &corners);
void minMaxValue(cv::Mat matContours,vector<Point2f> &corners,vector<Point2f> &minMaxVec);
bool contourEdgeCorner(cv::Mat matContours,Point2f &thisPoint);

int main(int argc,char** argv)
{
    Mat image = cv::imread(argv[1], IMREAD_UNCHANGED);
    Mat imageCorners =image.clone();
    Mat imagecontour =image.clone();
    int row=image.rows;
    int col=image.cols;
    cout<<"row:"<<row<<"  col:"<<col<< endl;
    // 阈值操作
    Mat grayMat;
    Mat otsuMat;
    cvtColor(image, grayMat, CV_BGR2GRAY);
    threshold(grayMat, otsuMat, 0, 255, CV_THRESH_BINARY + CV_THRESH_OTSU);
    cv::imwrite("threshold.png",otsuMat);
    Mat matContours=Mat::zeros(otsuMat.size(),CV_8UC1);  //边缘点

    //轮廓提取
    contourExtraction(imagecontour, otsuMat ,matContours,row, col);
    cv::imwrite("contourExtraction.png",matContours);
    imshow("contourExtraction",matContours);

    //角点检测
    vector<Point2f> corners;//存储角点位置
    cornerDetection(grayMat,imageCorners, corners);
    cv::imwrite("cornerDetection.png",imageCorners);
    imshow("cornerDetection",imageCorners);

    //角点提取
    vector<Point2f> minMaxVec;//存储角点A、B、C、D
    minMaxValue( matContours, corners, minMaxVec);



    for (int i = 0; i < minMaxVec.size(); i++)
    {
           circle(image, minMaxVec[i], 5, cv::Scalar(0, 255, 0), 2, 8, 0);
    }

    cv::imwrite("corners.png",image);
    imshow("corners",image);

    waitKey();
    return 0;
}

//轮廓提取
void contourExtraction(cv::Mat image,cv::Mat otsuMat, cv::Mat matContours,int row,int col)
{
    vector<vector<Point>> contours; //每一组Point点集就是一个轮廓
    vector<Vec4i> hierarchy;
    // hierarchy向量内每一个元素的4个int型变量——hierarchy[i][0] ~hierarchy[i][3],
    // 分别表示第i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号
    findContours(otsuMat,contours,hierarchy,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE,Point());
    //CV_RETR_EXTERNAL只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略
    //CV_CHAIN_APPROX_NONE 保存物体边界上所有连续的轮廓点到contours向量内

    Mat imageContours=Mat::zeros(otsuMat.size(),CV_8UC1);

    //contours[i]代表的是第i个轮廓,contours[i].size()代表的是第i个轮廓上所有的像素点数
    int maxEdge=100;
    int maxEdgeIndex=-1;
    for(int i=0;i<contours.size();i++)
    {
        if(maxEdge<contours[i].size())
        {
            maxEdge=contours[i].size();
            maxEdgeIndex=i;
        }
    }
    if(maxEdgeIndex<0)
        return ;
    for(int i=0; i<maxEdge; i++)
    {
        //绘制出contours向量内所有的像素点
        Point P=Point(contours[maxEdgeIndex][i].x,contours[maxEdgeIndex][i].y);
        matContours.at<uchar>(P)=255;
    }

    for(int r=0; r<row; r++)
    {
        for(int c=0 ; c<col ; c++)
        {
            if(matContours.at<uchar>(r,c)==255)
            {
                image.at<Vec3b>(r,c)[0]=0;
                image.at<Vec3b>(r,c)[1]=0;
                image.at<Vec3b>(r,c)[2]=255;
            }
        }
    }
    //imshow("Point of Contours",matContours);
}

void cornerDetection(cv::Mat grayMat,cv::Mat image,vector<Point2f> &corners)
{
    //角点识别
    //https://jingyan.baidu.com/article/2c8c281d9d8e7f0008252a88.html
    //设置角点检测参数
    int max_corners = 20;  //最大角点数量
    double quality_level = 0.01;//最小可接受的向量值
    double min_distance = 10; //两个角点之间的最小距离
    int block_size = 3;
    bool use_harris = false;
    double k = 0.04;
    goodFeaturesToTrack(grayMat,
                         corners,
                         max_corners,
                         quality_level,
                         min_distance,
                         Mat(),
                         block_size,
                         use_harris,
                         k);

    //将检测到的角点绘制到原图上
    for (int i = 0; i < corners.size(); i++)
    {
         circle(image, corners[i], 1, Scalar(0, 0, 255), 2, 8, 0);
    }
    //namedWindow("goodTrack corner",CV_WINDOW_NORMAL);
    //imshow("goodTrack corner", image);

    //指定亚像素计算迭代标注
    TermCriteria criteria = TermCriteria(
                                   TermCriteria::MAX_ITER + TermCriteria::EPS,
                                   40,
                                   0.01);

    //亚像素检测
    cornerSubPix(grayMat, corners, Size(5, 5), Size(-1, -1), criteria);
    //将检测到的亚像素角点绘制到原图上
    for (int i = 0; i < corners.size(); i++)
    {
           circle(image, corners[i], 5, cv::Scalar(50, 200, 0), 2, 8, 0);
    }
    //imshow("角点", image);
}

//查找四个极值点
void minMaxValue(cv::Mat matContours,vector<Point2f> &corners,vector<Point2f> &minMaxVec)
{
    vector<Point2f> allVec;

    for(int i=0 ; i<corners.size(); i++)
    {
        if(contourEdgeCorner(matContours,corners[i]))
        {
            allVec.push_back( corners[i] );
        }
    }
    if(allVec.size()<4)
        return;
    Point2f A=allVec[0]; //y-min
    Point2f B=allVec[0]; //x-max
    Point2f C=allVec[0]; //y-max
    Point2f D=allVec[0]; //x-min
    for(int i=1; i<allVec.size(); i++)
    {
        if(A.y>allVec[i].y)
            A=allVec[i];
        if(B.x<allVec[i].x)
            B=allVec[i];
        if(C.y<allVec[i].y)
            C=allVec[i];
        if(D.x>allVec[i].x)
            D=allVec[i];
    }
    minMaxVec.push_back(A);
    minMaxVec.push_back(B);
    minMaxVec.push_back(C);
    minMaxVec.push_back(D);
}

//判断是否为边缘角点
bool contourEdgeCorner(cv::Mat matContours,Point2f &thisPoint)
{
    for(int r=thisPoint.y-10; r<thisPoint.y+10; r++)
    {
        for(int c=thisPoint.x-10; c<thisPoint.x+10; c++)
        {
            if(matContours.at<uchar>(r,c)==255)
                return true;
        }
    }
    return false;
}

效果

在这里插入图片描述

数据

下载:https://download.csdn.net/download/xx970829/85161423

【转载请标明出处:https://blog.csdn.net/xx970829/article/details/123233609】

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值