Coder Social home page Coder Social logo

surround-view-system-introduction's Introduction

一份简单的环视系统制作实现,包含完整的标定、投影、拼接和实时运行流程,详细文档见 doc 目录。环视系统的开源代码很少见,希望大家积极提 issue 和 pull request,让这个项目能更好地有益于入门者学习。

This is a simple implementation of a surround view system, including calibration, projection, stitching, and real-time running processes. The English documentation can be found in the doc folder.

surround-view-system-introduction's People

Contributors

hynpu avatar joshwu avatar ljhcage avatar neozhaoliang avatar slbiubiu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

surround-view-system-introduction's Issues

关于基于单应性矩阵的测距

想问一下,怎么通过单应性矩阵得到相机前面的物体到相机的距离。目前物体只有鱼眼图像中的2d box框,大致得到物体到相机的距离,需要怎么算?求老师指点一下

python run_get_weight_matrices.py报错

Traceback (most recent call last):
File "/home/ai2/work/surround-view-system-introduction/run_get_weight_matrices.py", line 36, in
main()
File "/home/ai2/work/surround-view-system-introduction/run_get_weight_matrices.py", line 24, in main
Gmat, Mmat = birdview.get_weights_and_masks(projected)
File "/home/ai2/work/surround-view-system-introduction/surround_view/birdview.py", line 301, in get_weights_and_masks
G0, M0 = utils.get_weight_mask_matrix(FI(front), LI(left))
File "/home/ai2/work/surround-view-system-introduction/surround_view/utils.py", line 115, in get_weight_mask_matrix
distToB = cv2.pointPolygonTest(polyB, (x, y), True)
cv2.error: OpenCV(4.6.0) 👎 error: (-5:Bad argument) in function 'pointPolygonTest'

Overload resolution failed:

  • Can't parse 'pt'. Sequence item with index 0 has a wrong type
  • Can't parse 'pt'. Sequence item with index 0 has a wrong type

解决办法:
for y, x in zip(*indices):
distToB = cv2.pointPolygonTest(polyB, (int(x), int(y)), True)
if distToB < dist_threshold:
distToA = cv2.pointPolygonTest(polyA, (int(x), int(y)), True)
distToB *= distToB
distToA *= distToA
G[y, x] = distToB / (distToA + distToB)

关于多线程的一些疑问

  1. 抱歉我对多线程不是很熟悉
    为什么需要stop_mutex 和 processing_mutex 这两把锁呢?
    我看到锁里面访问的都是对象的内部属性,也不是公共的部分
    以及 每个线程都初始化了自己的 stopmutex 和 processing_mutex 两把锁 ,所以线程之间也不会因为这两把锁互斥
    我不是很明白

  2. 抱歉我对qt也了解不多
    我自己写QThread必须要先初始化QApplication才可以正常运行,否则它会说事件循环必须要QAplication支持
    我查阅了qt5文档,它说重载run函数线程就不会使用事件循环,但我还是会以下报错
    QEventLoop: Cannot be used without QApplication
    但我发现好像你的代码好像并不需要QApplication,请问是怎么做到的呢?

真的十分感谢!

鱼眼摄像头内参

鱼眼摄像头的内参可以调用OpenCV等进行计算,也可以由摄像头生成厂家给出,这两者那个更为准确呢?

实车测试硬件咨询

楼主你好,请问一下在实车测试的时候,你选用CSI摄像头,连接CSI摄像头的工控机分别是什么型号,方便的话麻烦告知一下,谢谢

TypeError: only integer scalar arrays can be converted to a scalar index in run_get_projection_maps.py

Hi,

I keep on encountering this error whenever i try to run run_get_projection_maps.py and run_live_demo.py

Also, can you provide a requirements file if possible?

Setup Info:

Python 3.8.3 running on Windows 10

Steps to reproduce:

  1. cloned repo
  2. created and enabled virtual environment
  3. installed dependencies. I attached my requirements.txt
  4. Run above script python run_get_projection_maps.py -camera front -scale 0.7 0.8 -shift -150 -100
$ "./Surround Vision/.venv/Scripts/python.exe" "./Surround Vision/run_get_projection_maps.py" -camera front -scale 0.7 0.8 -shift -150 -100

Traceback (most recent call last):
  File "./Surround Vision/run_get_projection_maps.py", line 73, in <module>
    main()
  File "./Surround Vision/run_get_projection_maps.py", line 62, in main
    camera = FisheyeCameraModel(camera_file, camera_name)
  File ".\Surround Vision\surround_view\fisheye_camera.py", line 28, in __init__
    self.load_camera_params()
  File ".\Surround Vision\surround_view\fisheye_camera.py", line 49, in load_camera_params
    self.update_undistort_maps()
  File ".\Surround Vision\surround_view\fisheye_camera.py", line 59, in update_undistort_maps
    self.undistort_maps = cv2.fisheye.initUndistortRectifyMap(
TypeError: only integer scalar arrays can be converted to a scalar index

摄像头视角及焦距

您好,请问您的摄像头是多少度的?焦距是多少?
我用的180°,焦距1.4mm,但是看不到标定布的角落。

代码似乎有问题

run_get_projection_maps.py 第24行 proj_image = camera_model.project(image) 中 project的参数应该是矫正后的und_img,而不是原图像image

拼接处出现重影是投影不精准导致?

感谢作者的优秀工作!我尝试搭建一个简陋的系统,发现最后拼接的全景图拼接处的棋盘格总是会出现重影,我猜测是投影矫正有误差导致两张鸟瞰图拼接时无法对齐,经过像素权重计算后出现重影问题,这样理解不知是否正确?
另外有个想法,拼接时根据棋盘格对两张鸟瞰图进行匹配,这样就能保证不会出现重影问题,类似于一些常见的全景拼接方法,不知是否可行?
BirdView

鸟瞰图扭曲

老师您好,我按照您docs文档用C++做了复现,用您提供的参数和输入图基本复现了您docs文档中的结果。和您的结果基本是一模一样的
问题是:当我自己使用汽车和标定布按照相同的步骤计算鸟瞰图,发现鸟瞰图大体上正确,但是有扭曲变形,不像您的鸟瞰图结果标定布的边边都是平直的。请问您的团队在探索过程中遇到过这种问题吗?可能是啥原因造成的呢?

鸟瞰图时间戳与输入图像对应

您好我想在输出鸟瞰图时同时输出处理图像的时间戳该怎么处理呢?我看到在给buffer传输图像的时候有输入时间戳数据但是后面好像没有时间戳的处理

权重矩阵定时更新

请教一个问题,实际场景中由于行驶环境不同导致光照不一样,那么亮度均衡和权重矩阵是不是要实时更新呢?还有就是是应该先融合拼缝后亮度均衡还是反过来?

关于这个项目

老师您好,我目前在做这个项目,想请教您scale和shift参数调整有没有好的办法,因为我一直拿不到自己感兴趣的那部分区域

透视变换问题

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

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

这是回复:
如果是这个的话,环视图的大小是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,考虑是因为图像大小问题,但直接裁减也不能得到想要的结果,请问如何解决

Please can you help my proejct?

I'm very impressed with your project and I'm trying your project.

At doc.md, I confirmed that you used the SF3326-100-RCCB camera. And I checked the specification of the product.

My cam is 120degree and it's narrow than yours. Is it ok to make surroundview?

一个罗技 usb摄像头还有一个笔记本自身的摄像头,能稍微看一下效果吗

运行python run_live_demo.py 后,
显示
Cannot open camera 0
Cannot open camera 2
其中设备号0和2(0是笔记本自身的摄像头,2是罗技 usb摄像头)我是根据以下opencv代码试出来的
import cv2
import numpy as np
cv2.namedWindow('testcamera')
capture = cv2.VideoCapture(0) #'0'代表从摄像头读入,'./video.avi'代表读入视频 #2代表从usb摄像头读入
capture.isOpened()
num = 0
while 1:
ret, frame = capture.read()
cv2.imshow('testcamera', frame)
key = cv2.waitKey(1)
num += 1
if key == 1048603: #
break

capture.release()
cv2.destroyAllWindows()

摄像头外参

你好,zhaoliang! 有个问题我想请教一下,就是摄像头的标定不是分为内参,外参吗?我在几个yaml配置文件中只看到camera_matrix,dist_coeffs这两个内参,以及project_matrix投影矩阵,没看见R、T外参,那外参是在什么地方起作用的?谢谢!

这里面是否有融合超声波雷达

你好,doc目录image文件夹下的result.mp4文件看起来像是融合了超声波雷达,请问融合超声波雷达的这部分代码有开源吗

如何获取鸟瞰图中点的空间坐标

您好,感谢分享。
我在运行run_live_demo.py的时候,总是会跑到一半卡死,定位卡在birdview.get(),但是多线程我也不太了解,请问可能是什么情况呢?

麻烦您的解答

运行calibration时不能捕捉到12个点?

图片
进行标定时,终端输入 python run_calibrate_camera.py --no_gst
无法捕捉到12个点 怎么办? 我的是杰瑞微通的1080pusb相机 ,进行标定时终端该输入一行什么命令?

usb相机占用usb控制器带宽的问题

我用的4个usb2.0的相机,但运行过程中因为uvc驱动的问题,一个相机会占用很多usb控制器的带宽,导致同时只能打开2个相机,这个似乎是Linux系统的问题。想请问下你是如何解决这个问题的呢?
另外能方便请问下你的相机选型吗?

The error of "python run_get_weight_matrices.py"

Hi, the error when runs "run_get_weight_matrices.py". Please help, thank you very much!

File "run_get_weight_matrices.py", line 36, in
main()
File "run_get_weight_matrices.py", line 24, in main
Gmat, Mmat = birdview.get_weights_and_masks(projected)
File "/home/idriver/work/AVP/surround-view-system-introduction-master/surround_view/birdview.py", line 301, in get_weights_and_masks
G0, M0 = utils.get_weight_mask_matrix(FI(front), LI(left))
File "/home/idriver/work/AVP/surround-view-system-introduction-master/surround_view/utils.py", line 114, in get_weight_mask_matrix
distToB = cv2.pointPolygonTest(polyB, (x, y), True)
cv2.error: OpenCV(4.5.5) 👎 error: (-5:Bad argument) in function 'pointPolygonTest'

Overload resolution failed:

  • Can't parse 'pt'. Sequence item with index 0 has a wrong type
  • Can't parse 'pt'. Sequence item with index 0 has a wrong type

怎么直接得到从原始画面到投影画面的查找表

老师您好,您在文档doc.md中的-具体实现的注意事项-中提及到的第二点,“同理对于 project_matrix 也不难获得一个查找表”这句话不太理解? 从畸变图到校正图应用cv2.fisheye.initUndistortRectifyMap()结合相机内参和畸变系数得到查找表mapx,mapy,那从校正图到鸟瞰图的查找表new_map要用到哪个函数?得到这个new_map后怎么与mapx和mapy合并才能直接从原图到鸟瞰图。求老师指点,谢谢您了,之前打扰过您一次了,非常感谢。

拼接时图像的缩放率不一致,以及具体的修改标志点的鸟瞰图的像素坐标的代码位置以及先后顺序

2023-02-10 12-17-01 的屏幕截图

想问下python run_get_projection_maps.py -camera前后左右后面跟的具体参数值,不知道为什么我拼接的图像底部那一块缩放率和其他三块完全不一样(我选择的-scale都是 0.7 0.8,标志点设置的顺序相同均为(左上,右上,左下,右下)只有最后两个shift参数值不同)

手动修改标志点的像素坐标是在代码的哪个地方(是文档里面project_keypoints的地方吗?),以及是在确定四个标志点生成单独鸟瞰图之后再修改鸟瞰图中的像素坐标,(这一整块都不是很明白)
感谢作者大大解答

相机视角FOV

老师您好:
请教您下,左右两侧的鱼眼相机去畸变之后的视场大小是不是应该要比前后置鱼眼相机的市场大小大呀,为了保证有较大的重叠区域

238DFB21-C9AD-4b1b-9D8E-CA3EC605BE9F

摄像头推荐

请问,有没有好的摄像头推荐,信号传输网线或者usb的。可以给个摄像头链接吗

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.