车位线识别之四关于鱼眼相机的一些API

1、引言
自动泊车的博客小编已经写了好几篇了,但是部分都没有代码,今天我从鱼眼相机图像到鸟瞰变换之间的变换写一篇博客,以记录这段过程

首先我们看下车位的鱼眼图像
车位线识别之四关于鱼眼相机的一些API_第1张图片我们已经通过标定得到了内参与畸变参数,接下来我们进行矫正,由于矫正会损失好多有效信息,这里我给出两个opencv 的API,我们看下

fisheye::estimateNewCameraMatrixForUndistortRectify(cameraMatrix1,distCoeffs1,image_size,R,new_cameraMatrix,0.8,image_size,1);
fisheye::initUndistortRectifyMap(cameraMatrix1,distCoeffs1, R,new_cameraMatrix,image_size,CV_16SC2,mapx,mapy);
remap(image, dst, mapx, mapy, INTER_LINEAR);

在这里我们先求出了映射表,然后再进行remap.
另外一个API直接对图像进行矫正

cv::fisheye::undistortImage(image,UndistortImg,cameraMatrix1,distCoeffs1,new_intrinsic_mat);

后者API的速度太慢,我们这里嵌入式资源有限,不考虑。

2、图像矫正
首先我们看下矫正之后的图像
车位线识别之四关于鱼眼相机的一些API_第2张图片车位线识别之四关于鱼眼相机的一些API_第3张图片可以看出来,第二张损失了很多车位线的信息,因此在这我们只能牺牲一些图像的精度,保证图像的视野,所以采用第一张图的这种矫正方式,参数可调,具体可参考opencv官网。

https://docs.opencv.org/master/db/d58/group__calib3d__fisheye.html#ga384940fdf04c03e362e94b6eb9b673c9

3、鸟瞰图像
矫正之后我们需要做一步鸟瞰,来形成上帝视角,先看图
车位线识别之四关于鱼眼相机的一些API_第4张图片后面我还会通过调节RT相机的外参,来改变视角,做完这些,我们就可以来进行车位识别了,这个前面博客已经提供了思路,不在赘述。
在这给出矫正代码,代码中我做了些优化,将矩阵计算之后输入到xml,后续对视频则不需要每帧计算。

//
// Created by lenovo on 19-5-16.
//
#include 
#include 
using namespace cv;
using namespace std;
using namespace fisheye;
Mat  image;
Mat cameraMatrix1;
cv::Mat distCoeffs1(4, 1, cv::DataType<double>::type);
Mat UndistortImg;
Mat new_intrinsic_mat;    
//Mat new_intrinsic_mat(3, 3, CV_64FC1, Scalar(0))亦可,注意数据类型;
int  fx_threshold_min=80;
int  fy_threshold_min=80;
string winname="UndistortImg";






//TrackBar发生改变的回调函数
void onChangeTrackBar(int, void* );

int main()
{
    string bar_name_1="fx";
    string bar_name_2="fy";
    image=imread("./saveImg.jpg");
    imwrite("image.jpg",image);
    Mat dst;
    cameraMatrix1=Mat::eye(3, 3, cv::DataType<double>::type);



    distCoeffs1.at<double>(0,0) = 0.061439051;
    distCoeffs1.at<double>(1,0) = 0.03187556;
    distCoeffs1.at<double>(2,0) = -0.00726151;
    distCoeffs1.at<double>(3,0) = -0.00111799;
    //distCoeffs1.at(4,0) = -0.00678974;

    //Taken from Mastring OpenCV d
    double fx = 328.61652824;
    double fy = 328.56512516;
    double cx = 629.80551148;
    double cy = 340.5442837;

    cameraMatrix1.at<double>(0, 0) = fx;
    cameraMatrix1.at<double>(1, 1) = fy;
    cameraMatrix1.at<double>(0, 2) = cx;
    cameraMatrix1.at<double>(1, 2) = cy;



    std::cout << "After calib cameraMatrix --- 1: " << cameraMatrix1 << std::endl;
    std::cout << "After calib distCoeffs: --- 1" << distCoeffs1 << std::endl;
       ////////////////////////////////////////////////////////////////////
       /////  鱼眼摄像头畸变矫正
       ////////////////////////////////////////////////////////////////////
    Size image_size(1280,720);
    Mat mapx = Mat(image_size, CV_32FC1);
    Mat mapy = Mat(image_size, CV_32FC1);
    Mat R = Mat::eye(3, 3, CV_32F);
    Mat P = Mat::eye(3, 3, CV_32F);

    Mat new_cameraMatrix=Mat::zeros(3,3,CV_32F);
    //new_cameraMatrix=
    fisheye::estimateNewCameraMatrixForUndistortRectify(cameraMatrix1,distCoeffs1,image_size,R,new_cameraMatrix,0.8,image_size,1);
    //new_cameraMatrix=getOptimalNewCameraMatrix(cameraMatrix1, distCoeffs1, image_size, 1, image_size, 0);
    cout<<"new cameraMatrix: "<<new_cameraMatrix<<endl;
    // cv::fisheye::initUndistortRectifyMap()

    fisheye::initUndistortRectifyMap(cameraMatrix1,distCoeffs1, R,new_cameraMatrix,image_size,CV_16SC2,mapx,mapy);
    //cout<
    FileStorage fs_x("../vocabulary_x.xml", FileStorage::WRITE);
    FileStorage fs_y("../vocabulary_y.xml", FileStorage::WRITE);
    fs_x<<"vocabulary_x"<<mapx;
    fs_y<<"vocabulary_y"<<mapy;


    FileStorage fs_x("../vocabulary_x.xml", FileStorage::READ);
    FileStorage fs_y("../vocabulary_y.xml", FileStorage::READ);

    fs_x["vocabulary_x"] >> mapx;
    fs_y["vocabulary_y"] >> mapy;
    double t1 = (double)getTickCount();
    remap(image, dst, mapx, mapy, INTER_LINEAR);
    //remap(image,dst,mapx,mapy,INTER_NEAREST);
    ////////////////////////////////////////////////////////////////////
    /////  鱼眼摄像头畸变矫正
    ////////////////////////////////////////////////////////////////////
    t1 = (double)getTickCount() - t1;
    std::cout << "compute time :" << t1*1000.0 / cv::getTickFrequency() << " ms \n";
    imshow("result",dst);
    imwrite("result.jpg",dst);

    //fx,fy变大(小),视场变小(大),裁剪较多(少),但细节清晰(模糊);
    //new_intrinsic_mat决定输出的畸变校正图像的范围
    //float max_lowThreshold=1.0;
    //调整输出校正图的视场
    namedWindow(winname,WINDOW_AUTOSIZE);
    createTrackbar(bar_name_1, winname, &fx_threshold_min, 100,onChangeTrackBar,0);
    createTrackbar(bar_name_2, winname, &fy_threshold_min, 100,onChangeTrackBar,0);
    //onChangeTrackBar(0,0);

    waitKey(0);
}


void onChangeTrackBar(int pos, void* )
{
    cameraMatrix1.copyTo(new_intrinsic_mat);
    new_intrinsic_mat.at<double>(0, 0) *= ((float)fx_threshold_min)/100.0;      
    //注意数据类型
    new_intrinsic_mat.at<double>(1, 1) *= ((float)fy_threshold_min)/100.0;

    //调整输出校正图的中心
    new_intrinsic_mat.at<double>(0, 2) = 0.5*UndistortImg.cols;
    new_intrinsic_mat.at<double>(1, 2) = 0.5 *UndistortImg.rows;
    double t1 = (double)getTickCount();

    cv::fisheye::undistortImage(image,UndistortImg,cameraMatrix1,distCoeffs1,new_intrinsic_mat);
    t1 = (double)getTickCount() - t1;
    std::cout << "compute time :" << t1*1000.0 / cv::getTickFrequency() << " ms \n";
    cv::imshow("UndistortImg", UndistortImg);
}

你可能感兴趣的:(图像处理,机器学习)