neozhaoliang / surround-view-system-introduction

A full Python implementation for real car surround view system
MIT License
857 stars 303 forks source link

透视变换问题 #50

Closed loseyourself-gan closed 1 year ago

loseyourself-gan commented 1 year ago

大佬好,我目前遇到了环视图拼接的问题,用的是一个数据集,已知相机内参和单应性矩阵

我开始用的是先去畸变,再透视变换的方法,但始终无法得到正确的结果,后面发邮件问作者

这是回复: 如果是这个的话,环视图的大小是416*416,由于SLAM对速度有要求,所以我们不能使用更大的环视图作为输入。 具体到你说的拼接方法,可以根据生成拼接表进行拼接。核心代码如下:

vector<vector<cv::Point2f>> GenerateSingleMappingTable(cv::Mat mHomography , cv::Size iImageSize , cv::Mat mK , cv::Mat mD , cv::Mat mP){
    vector<vector<cv::Point2f>> gMappingTable;
    gMappingTable.reserve(iImageSize.height);
    for (int y=0;y<iImageSize.height;y++){  
        //Generate the table of this line.
        vector<cv::Point2f> gSubMappingTable;
        gSubMappingTable.reserve(iImageSize.width);
        for (int x=0;x<iImageSize.width;x++){
            cv::Mat mPoint = (cv::Mat_<double>(3 , 1) << x , y , 1);
            mPoint = mHomography * mPoint;

            mPoint = mK.inv() * mPoint;
            cv::Point2f iPoint(mPoint.at<double>(0 , 0)/mPoint.at<double>(2 , 0) , mPoint.at<double>(1 , 0)/mPoint.at<double>(2 , 0));
            if (mPoint.at<double>(2 , 0) == 0){
                iPoint = cv::Point2f(0 , 0);
            }
            gSubMappingTable.push_back(iPoint);

        }
        cv::fisheye::distortPoints(gSubMappingTable, gSubMappingTable, mK, mD);
        for (auto & item : gSubMappingTable){
            if (item.x <= 0.0){
                item.x = 0.0;
            }else if (item.x >= (float)(iCameraImageSize.width-1)){
                item.x = (float)(iCameraImageSize.width-1);
            }
            if (item.y <=0.0){
                item.y = 0.0;
            }else if (item.y >= (float)(iCameraImageSize.height-1)){
                item.y = (float)(iCameraImageSize.height-1);
            }
        }
        gMappingTable.push_back(gSubMappingTable);
    }
    return gMappingTable;
}

我不知道这个拼接表的数据结构如何直接使用,于是参用了下面的代码

void GenerateSingleMappingTable(Mat& map1, Mat& map2, cv::Mat mHomography,cv::Size image_size, cv::Size camera_size, cv::Mat mK, cv::Mat mD) 
{
    if (map1.total() == 0 || map1.cols != image_size.width || map1.rows != image_size.height)
    {
        map1.create(image_size, CV_32FC1);
        map2.create(image_size, CV_32FC1);
    }
    for (int y = 0; y < image_size.height; y++) {
        //Generate the table of this line.
        vector<cv::Point2f> gSubMappingTable;
        gSubMappingTable.reserve(image_size.width);
        for (int x = 0; x < image_size.width; x++) {
            cv::Mat mPoint = (cv::Mat_<double>(3, 1) << x, y, 1);
            mPoint = mHomography * mPoint;
            mPoint = mK.inv() * mPoint;
            cv::Point2f iPoint(mPoint.at<double>(0, 0) / mPoint.at<double>(2, 0), mPoint.at<double>(1, 0) / mPoint.at<double>(2, 0));
            if (mPoint.at<double>(2, 0) == 0) {
                iPoint = cv::Point2f(0, 0);
            }
            gSubMappingTable.push_back(iPoint);
        }
        cv::fisheye::distortPoints(gSubMappingTable, gSubMappingTable, mK, mD);
        for (int x = 0; x < image_size.width; ++x)
        {
            map1.at<float>(y, x) = gSubMappingTable[x].x;
            map2.at<float>(y, x) = gSubMappingTable[x].y;
        }
    }
    return;
}

使用后,前和左的结果比较正确,但右和后不对,我这个代码变换后得到的是1280x1080,考虑是因为图像大小问题,但直接裁减也不能得到想要的结果,请问如何解决

loseyourself-gan commented 1 year ago

1609489071 99800000_Front 1609489071 99800000_Back 1609489071 99800000_Left 1609489071 99800000_Right

这是原图,顺序为前 后 左 右

Res_Front Res_Back

Res_Left

Res_Right

这是透视变换之后的图

neozhaoliang commented 1 year ago

你的透视变换图是完全错误的,没有一张是对的。恐怕你对原作者的代码使用方法不对。建议你仔细问问作者,如何生成正确的拼接表。

loseyourself-gan commented 1 year ago

大佬好,作者原代码中的 vector<vector> gMappingTable,我不知道如何利用直接利用这个变量将原图进行去畸变和透视变换,所以将其进行转换用了opencv中的remap方法,请问大佬知道怎么利用这个变量的方法吗 @neozhaoliang

neozhaoliang commented 1 year ago

你为啥拿别人的代码来问我。。。这你去问原作者,或者读他的文档不好吗?

loseyourself-gan commented 1 year ago

原作者是1月7号回我的,后面我又发了两封邮件一直没回我,我这边有点赶时间,才到这里来问的,他的文档我看过了,没有这方面的细节描述,谢谢大佬 @neozhaoliang

neozhaoliang commented 1 year ago

所以他这个函数的目的是什么?你参考的第二个函数的目的是什么? 你不给任何信息,是让我啃代码猜他的意思么?

loseyourself-gan commented 1 year ago

不好意思,他的函数的目的是建立原图像和鸟瞰图的像素位置对应关系(包含了去畸变和透视变换),我直接单个像素操作结果也不太对。 我用remap的原因是因为这是一个opencv自带的能实现像素之间映射的函数,但是这个remap只能用同样图像大小进行映射,所以我考虑是不是图像大小问题,谢谢大佬@neozhaoliang

neozhaoliang commented 1 year ago

抱歉你的问题是关于别人的代码,与这个项目没有什么关系,而且你提供的信息非常少,恕我难以解答。

顺便一说,提问的时候把问题描述清楚,提供足够的信息才是对别人的尊重;上来贴一大段不知所云的代码就让别人帮你解答是无礼的行为。你一口一个大佬只会让我觉得廉价。

loseyourself-gan commented 1 year ago

好的,十分抱歉