欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

双目相机去畸变和极线平行操作

程序员文章站 2022-05-29 09:22:11
...
class StereoMatch
{
public:
    StereoMatch(void);
    virtual ~StereoMatch(void);

    int init(int imgWidth, int imgHeight, const char* xmlFilePath);

    int bmMatch(cv::Mat& frameLeft, cv::Mat& frameRight, cv::Mat& disparity, cv::Mat& imageLeft, cv::Mat& imageRight,
                cv::Mat &cropLeft, cv::Mat &cropRight);
    cv::Ptr<cv::StereoBM> m_BM = cv::StereoBM::create();
    double          m_FL;

private:

    int loadCalibData(const char* xmlFilePath);

    bool   m_Calib_Data_Loaded;
    cv::Mat m_Calib_Mat_Q;
    cv::Mat m_Calib_Mat_Remap_X_L;
    cv::Mat m_Calib_Mat_Remap_Y_L;
    cv::Mat m_Calib_Mat_Remap_X_R;
    cv::Mat m_Calib_Mat_Remap_Y_R;
    cv::Mat m_Calib_Mat_Mask_Roi;
    cv::Rect m_Calib_Roi_L;
    cv::Rect m_Calib_Roi_R;

    int m_frameWidth;
    int m_frameHeight;
    int m_numberOfDisparies;

    int m_nViewWidth;
    int m_nViewHeight;
    int m_nViewDepth;
    cv::Rect m_rect;

};



StereoMatch::StereoMatch(void)
        : m_frameWidth(0), m_frameHeight(0), m_numberOfDisparies(0)
{
}

StereoMatch::~StereoMatch(void)
{
}


int StereoMatch::init(int imgWidth, int imgHeight, const char* xmlFilePath)
{
    m_frameWidth = imgWidth;
    m_frameHeight = imgHeight;
    m_numberOfDisparies = 0;


    return loadCalibData(xmlFilePath);
}


int StereoMatch::loadCalibData(const char* xmlFilePath)
{
    try
    {
        cv::FileStorage fs(xmlFilePath, cv::FileStorage::READ);
        if (!fs.isOpened())
        {
            return (0);
        }

        cv::Size imageSize;
        cv::FileNodeIterator it = fs["imageSize"].begin();
        it >> imageSize.width >> imageSize.height;
        if (imageSize.width != m_frameWidth || imageSize.height != m_frameHeight)
        {
            return (-1);
        }

        vector<int> roiVal1;
        vector<int> roiVal2;

        fs["leftValidArea"] >> roiVal1;
        m_Calib_Roi_L.x = roiVal1[0];
        m_Calib_Roi_L.y = roiVal1[1];
        m_Calib_Roi_L.width = roiVal1[2];
        m_Calib_Roi_L.height = roiVal1[3];

        fs["rightValidArea"] >> roiVal2;
        m_Calib_Roi_R.x = roiVal2[0];
        m_Calib_Roi_R.y = roiVal2[1];
        m_Calib_Roi_R.width = roiVal2[2];
        m_Calib_Roi_R.height = roiVal2[3];


        //读取标定文件里映射矩阵

        fs["QMatrix"] >> m_Calib_Mat_Q;
        fs["remapX1"] >> m_Calib_Mat_Remap_X_L;
        fs["remapY1"] >> m_Calib_Mat_Remap_Y_L;
        fs["remapX2"] >> m_Calib_Mat_Remap_X_R;
        fs["remapY2"] >> m_Calib_Mat_Remap_Y_R;

        cv::Mat lfCamMat;
        fs["leftCameraMatrix"] >> lfCamMat;
        m_FL = lfCamMat.at<double>(0, 0);

        m_Calib_Mat_Mask_Roi = cv::Mat::zeros(m_frameHeight, m_frameWidth, CV_8UC1);
        cv::rectangle(m_Calib_Mat_Mask_Roi, m_Calib_Roi_L, cv::Scalar(255), -1);

        m_BM->setROI1(m_Calib_Roi_L);
        m_BM->setROI2(m_Calib_Roi_R);

        m_Calib_Data_Loaded = true;

        string method;
        fs["rectifyMethod"] >> method;
        if (method != "BOUGUET")
        {
            return (-2);
        }
        int y_min = (m_Calib_Roi_L.y > m_Calib_Roi_R.y) ? m_Calib_Roi_L.y : m_Calib_Roi_R.y;
        int x_min = (m_Calib_Roi_L.x > m_Calib_Roi_R.x) ? m_Calib_Roi_L.x : m_Calib_Roi_R.x;
        int y_max = (m_Calib_Roi_L.y + m_Calib_Roi_L.height < m_Calib_Roi_R.y + m_Calib_Roi_R.height) ? (m_Calib_Roi_L.y + m_Calib_Roi_L.height) : (m_Calib_Roi_R.y + m_Calib_Roi_R.height);
        int x_max = (m_Calib_Roi_L.x + m_Calib_Roi_L.width < m_Calib_Roi_R.x + m_Calib_Roi_R.width) ? (m_Calib_Roi_L.x + m_Calib_Roi_L.width) : (m_Calib_Roi_R.x + m_Calib_Roi_R.width);
        m_rect = cv::Rect(x_min, y_min, x_max - x_min, y_max - y_min);



    }
    catch (std::exception& e)
    {
        m_Calib_Data_Loaded = false;
        return (-99);
    }

    return 1;
}



int StereoMatch::bmMatch(cv::Mat& frameLeft, cv::Mat& frameRight, cv::Mat& disparity, cv::Mat& imageLeft, cv::Mat& imageRight,
                         cv::Mat &cropLeft, cv::Mat &cropRight)
{
    if (frameLeft.empty() || frameRight.empty())
    {
        disparity = cv::Scalar(0);
        return 0;
    }
    if (m_frameWidth == 0 || m_frameHeight == 0)
    {

        //calib_paras_zed_1280x720_1219_new
//        if (init(frameLeft.cols, frameLeft.rows, "../../calib/calib_paras_ZED_1280x720_201912261133.xml") == 0)
        if (init(frameLeft.cols, frameLeft.rows, "../../calib/calib_paras_zed_1280x720_1219_new.xml") == 0)
        {
            return 0;
        }

    }
    //利用映射矩阵m_Calib_Mat_Remap_X_L m_Calib_Mat_Remap_Y_L去左右两目相机的畸变,且极线平行

    if (m_Calib_Data_Loaded)
        remap(frameLeft, imageLeft, m_Calib_Mat_Remap_X_L, m_Calib_Mat_Remap_Y_L, cv::INTER_LINEAR);
    else
        frameLeft.copyTo(imageLeft);

    if (m_Calib_Data_Loaded)
        remap(frameRight, imageRight, m_Calib_Mat_Remap_X_R, m_Calib_Mat_Remap_Y_R, cv::INTER_LINEAR);
    else
        frameRight.copyTo(imageRight);
    //切出左右两目共视部分

    cropLeft = cv::Mat(imageLeft, m_rect);
    cropRight = cv::Mat(imageRight, m_rect);

    return 1;
}
//AWB
void AWB(cv::Mat &src, cv::Mat &dst)
{
    vector<Mat> imageRGB;
    cv::split(src, imageRGB);

    double R, G, B;
    B = cv::mean(imageRGB[0])[0];
    G = cv::mean(imageRGB[1])[0];
    R = cv::mean(imageRGB[2])[0];

    if (B != 0 && G != 0 && R != 0) {
        double KR, KG, KB;
        KB = (R + G + B) / (3 * B);
        KG = (R + G + B) / (3 * G);
        KR = (R + G + B) / (3 * R);

        imageRGB[0] = imageRGB[0] * KB;
        imageRGB[1] = imageRGB[1] * KG;
        imageRGB[2] = imageRGB[2] * KR;
    }

    cv::merge(imageRGB, dst);
}
void LoadTimestamps(const string &strPathToSequence, vector<double> &vTimestamps)
{
    ifstream fTimes;
    string strPathTimeFile = strPathToSequence + "/video_time.txt";
    fTimes.open(strPathTimeFile.c_str());

    vTimestamps.reserve(5000);

    while (!fTimes.eof()) {
        string s;
        getline(fTimes, s);
        if (!s.empty())
        {
            string tmp = s.substr(0,s.find_first_of("\r"));

            double t;
            stringstream ss;
            ss<<s;
            ss >> t;

            vTimestamps.push_back(t/1e9);
        }
    }
}
bool flag_end;
int main()
{
    std::string pathToTimes = "/home/yunlei/Datasets/Homer02_zed_1280x720/";
    std::vector<double> vTimes;
    LoadTimestamps(pathToTimes, vTimes);
//    for(int i = 0; i<vTimes.size(); i++)
//    {
//        std::cout<<setprecision(14)<<vTimes[i]*1e9<<std::endl;
//    }
    std::vector<double> vTimesTrack;
    //ORB_SLAM2::System SLAM("../../Vocabulary/ORBvoc.txt","./zed_1249x603_20191226.yaml",ORB_SLAM2::System::STEREO,true);

    int cunt = 0;
    StereoMatch sm;
    VideoCapture capture_left;
    VideoCapture capture_right;
    Mat frame_left;
    Mat frame_right;

    capture_left.open("/home/yunlei/Datasets/Homer02_zed_1280x720/left.mp4");
    std::string output_path_left = "/home/yunlei/Datasets/Homer02_zed_1280x720/leftCrop//";

    capture_right.open("/home/yunlei/Datasets/Homer02_zed_1280x720/right.mp4");
    std::string output_path_right = "/home/yunlei/Datasets/Homer02_zed_1280x720/rightCrop/";

    Mat disparity;
    Mat rectifyImageL, rectifyImageR;
    Mat cropLeft, cropRight;

    if (!capture_left.isOpened()) {
        std::cout << "capture_left open failed!" << std::endl;
    }
    if (!capture_right.isOpened()) {
        std::cout << "capture_right open failed!" << std::endl;
    }

    while (capture_left.isOpened() && capture_right.isOpened())
    {
        capture_left >> frame_left;
        if (frame_left.empty())
        {
            cout << "frame right is empty! cunt = " << cunt << std::endl;
            break;//continue;
        }
        capture_right >> frame_right;
        if (frame_right.empty())
        {
            flag_end = false;
            cout << "frame right is empty! cunt = " << cunt << std::endl;
            break;//continue;
        }
        std::stringstream ss;
        ss<<cunt;
        string frameName;
        ss>>frameName;

        string leftFramePath = output_path_left + frameName + ".png";
        string rightFramePath = output_path_right + frameName + ".png";

        sm.bmMatch(frame_left, frame_right, disparity, rectifyImageL, rectifyImageR, cropLeft, cropRight);
        AWB(cropLeft, cropLeft);
        AWB(cropRight, cropRight);




       cv::imshow("leftOri", frame_left);
      cv::waitKey(10);
       cv::imshow("rightOri", frame_right);
      cv::waitKey(10);
      cv::imshow("leftCrop", cropLeft);
      cv::waitKey(10);
      cv::imshow("rightCrop", cropRight);
      cv::waitKey(10);
    
        ///Just for test
        // joint left and right image into one image.
//将两幅进行去畸变的图像拼接到一起,并画上横线,可以直观的查看,去畸变的效果
//先列,后行
        int imgWidth = cropLeft.cols;
        int imgHeight = cropLeft.rows;
        cv::Mat testImg(imgHeight,2*imgWidth+1, cropLeft.type());

        cropLeft.copyTo(testImg(cv::Rect(0,0, imgWidth,imgHeight)));
        cropRight.copyTo(testImg(cv::Rect(imgWidth+1,0,imgWidth, imgHeight)));
        //std::cout<<"testImg size: "<<testImg.cols<<"x"<<testImg.rows<<std::endl;

        cv::Point startPoint = cv::Point(0,0);
        cv::Point endPoint = cv::Point(2*imgWidth+1, 50);
        int tmpHeight = 0;
        for(int i = 0; i<imgHeight/30; i++)
        {

            startPoint = cv::Point(0,tmpHeight);
            endPoint = cv::Point(2*imgWidth+1, tmpHeight);
            cv::line(testImg, startPoint, endPoint, cv::Scalar(0,255,0));
            tmpHeight+=30;
        }


        if(cunt == 50)
        {
            cv::imshow("testImg", testImg);
            cv::waitKey(0);
        }
        cunt++;
      cv::imwrite(leftFramePath, cropLeft);
      cv::imwrite(rightFramePath, cropRight);

    }
     cout << "the video is end! " << "-----------------" << endl;

    return 0;
}

 

相关标签: 机器视觉