360度环视拼接源码cuda加速

在知乎上看到了开源ADAS-360环视拼接c++版本的代码,我改写成了cuda加速版本,实测在我一万五的笔记本上未加速前c++版本12fps,cuda加速后10000fps以上,时间基本可以忽略不计。

ADAS-360环视拼接原理地址:https://zhuanlan.zhihu.com/p/644427203
环视拼接原理详细版本:https://github.com/neozhaoliang/surround-view-system-introduction/blob/master/doc/doc.md
使用文章中的AdasSourrondView c++开源项目:https://github.com/JokerEyeAdas/AdasSourrondView/tree/main
我加速后的github地址:https://github.com/zhangyeyan/360-Surround-View-CUDA-Project 

AdasSourrondView代码中是c++版本的360环视拼接,源代码有个小bug,修改下运行后可到如下图,4张原始图像环视拼接成最后一张图的效果。

frontbackleftright

在这里插入图片描述

采用查表的方法对代码进行cuda加速,首先需要找到原图和输出后的图,这两张图的坐标映射关系,把这个关系存储下来,有了这个映射关系,每次做拼接时,直接将原图的坐标点搬运到输出图像中具体的位置,使用cuda去做这个查找搬运的过程速度非常快。

通过观察AdasSourrondView c++代码可以发现,代码主要是把去畸变后的四张图直接映射到四块区域,拼接处的重影断代现象使用权重文件进行加权求和,去掉重影部分。具体的原理可以参考原作者的知乎。

环视测试图片有前后左右四张图,以左图为例子,会经过如下a,b,c,d的变换,我们要找到d图到a图,每个坐标变换的关系。
在这里插入图片描述
我们的目标是输出4张(1600,1200,10)大小的表,每个像素点需要10个元素记录下坐标变化关系。以其中一张图为例子:

#创建一个网格坐标系
ys, xs = torch.meshgrid(torch.arange(h), torch.arange(w))
#齐次坐标
xy = torch.stack([xs + 0.5, ys + 0.5, torch.ones_like(xs)], dim=-1).float()
xy = xy @ torch.from_numpy(proj @ param.project).float().inverse().T
xy[..., :2] /= xy[..., [2]]
#将坐标值从原始图像的坐标空间映射到 -1 到 1 的范围内
xy = ((xy[..., :2] - 0.5) / torch.tensor([IW, IH]))[None] * 2 - 1
remapxy = torch.stack([torch.from_numpy(x) + 0.5, torch.from_numpy(y) + 0.5], dim=-1)
#将remapxy张量转换为形状为(1, C, H, W)的张量  
output = F.grid_sample(remapxy.permute(2, 0, 1)[None], xy.float(), "bilinear", align_corners=False)[0].permute(1, 2, 0)
#将去畸变后的4张图根据M矩阵,投影到输出图的对应区域
output_coord = cv2.warpAffine(output.data.numpy(), M, dsize=(SW, SH), flags=cv2.INTER_NEAREST)

未完待续

  • 11
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
下面是一个简单的Qt程序,演示如何使用OpenCV库将四张图片环视拼接成一张全景图。请注意,这是一个简单的示例程序,仅供参考。你需要根据自己的实际需求进行修改和完善。 ```cpp #include <QApplication> #include <QGraphicsScene> #include <QGraphicsView> #include <opencv2/opencv.hpp> int main(int argc, char *argv[]) { QApplication a(argc, argv); // 加载四张图片 cv::Mat img1 = cv::imread("img1.jpg"); cv::Mat img2 = cv::imread("img2.jpg"); cv::Mat img3 = cv::imread("img3.jpg"); cv::Mat img4 = cv::imread("img4.jpg"); // 拼接四张图片 cv::Mat panorama; cv::hconcat(img1, img2, panorama); cv::hconcat(panorama, img3, panorama); cv::hconcat(panorama, img4, panorama); // 将全景图转换为QPixmap对象 QImage qimg(panorama.data, panorama.cols, panorama.rows, panorama.step, QImage::Format_RGB888); QPixmap pixmap = QPixmap::fromImage(qimg); // 创建Graphics View和Scene,显示全景图 QGraphicsScene scene; QGraphicsPixmapItem item(pixmap); scene.addItem(&item); QGraphicsView view(&scene); view.show(); // 设置Graphics View的属性,使其支持拖拽和缩放 view.setDragMode(QGraphicsView::ScrollHandDrag); view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate); view.setRenderHint(QPainter::SmoothPixmapTransform); view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse); view.setResizeAnchor(QGraphicsView::AnchorUnderMouse); view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); view.setInteractive(true); view.setDragMode(QGraphicsView::ScrollHandDrag); view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing, true); // 设置全景图的初始旋转角和平移距离 item.setRotation(-90); item.setPos(-pixmap.width() / 2, -pixmap.height() / 2); return a.exec(); } ``` 在这个示例程序中,我们首先使用OpenCV库加载了四张图片,并使用cv::hconcat函数将这四张图片拼接成一张全景图。接下来,我们将这个全景图转换为QPixmap对象,并创建了一个QGraphicsScene对象,并将这个QPixmap对象添加到这个场景中。最后,我们创建了一个QGraphicsView对象,将这个场景显示到这个视图中,并设置了一些属性,使其支持拖拽和缩放。我们还设置了全景图的初始旋转角和平移距离,以实现环视全景图的效果。 请注意,这个示例程序仅供参考。你需要根据自己的实际需求进行修改和完善。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值