使用 OpenCV 对表面投影进行图像校正

发布于 2024-12-28 02:35:12 字数 502 浏览 2 评论 0原文

OpenCV 中对投影到 3D 表面的图像应用校正的最佳方法是什么,如我的示例或 3D 表面上的投影

我对 OpenCV 棋盘角点检测的第一次测试看起来不太有希望。如果相机角度太陡,则图像太扭曲或太小(太远),无法检测到角点。另外,如果棋盘有太多字段。

我的想法是使用类似于 3D 扫描仪中使用的算法来检测表面(物体),但我不知道 OpenCV 是否可以实现这一点。即使 OpenCV 无法实现,这种对象扫描使用的算法是什么?

该图像显示了未经任何校正的外观。 表面上未校正的投影

绿色矩形是校正后的投影。 校正后的投影(绿色)

What is the best way in OpenCV to apply correction on an image projected to a 3D surface like in my examples or shown in Projection on 3D surface?

My first tests with OpenCV checkerboard corner detection didn't looked very promising. If the camera angle was too steep, the image was too distorted or too small (too far away) no corner was detected. Also if the checkerboard had too many fields.

My idea was to use an algorithm like it is used in 3D scanners to detect surfaces (objects), but I've no idea if this is possible with OpenCV. Even if it would not be possible with OpenCV, what are the algorithms used for such object scanning?

This images show how it looks like without any correction.
Uncorrected projection on surface

The green rectangles are the corrected projections.
Corrected projection (green)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

私藏温柔 2025-01-04 02:35:12

正如我用于 ProCamCalib 的标记,应该可以更可靠地检测到比棋盘图案。您可以将 ARToolkitPlus 与 ProCamCalib 一起使用,但还有其他替代方案,或者您可以制作自己的自己的小探测器。 :) 然后,利用检测到的标记角坐标,我们可以使用 OpenCV 的其余校准函数以相同的方式进行校准。

我也可以用它做一些很酷的事情,如 ProCamTracker

编辑:现在我更好地理解了这个问题,我们可以很容易地在静态场景中完成这个任务,尽管 OpenCV 不会对我们有太大帮助。首先,我们将相机放置在我们希望观看者看到校正后的投影的位置。然后,我们投影二进制图案(看起来像局部闪烁的点),并捕获这些点图案的图像。 (我们可以使它们更密集,直到它们变成条形,这是一种称为结构光的技术。)在从相机图像中检测并将这些点解码为二进制代码后,我们得到了相机<->投影仪像素对应关系,以及一定数量的无论如何,顶点,从那里它就是 100% 的图形。以下论文更详细地介绍了这些步骤:

Zollmann, S.、Langlotz, T. 和 Bimber, O.
用于任意表面上的视图相关投影的被动-主动几何校准
http://140.78.90.140/medien/ar/Pub/PAGC_final.pdf
演示视频:http://140.78.90.140/medien/ar/Pub/PAGC.avi< /a>

EDIT2:通过投影某种图案,我们可以计算出投影仪图像中与相机图像中给定像素相对应的像素坐标。我们经常使用时间点模式,因为它很容易检测和解码......实际上,OpenCV 可能会派上用场。我想我会尝试这样做的方式会是这样的。为了简单起见,我们只取 2 位。因此,我们有四个图像:00、01、10 和 11。由于我们控制投影仪图像,因此我们知道这些图像,但我们也必须在相机图像中找到它们。首先,我将使用 cvAbsDiff() 将最后一个(相机)图像 11 从第一个(相机)图像 00 中减去它,然后使用 cvThreshold() 对结果进行二值化,并在二进制中找到轮廓(或斑点)使用 cvFindContours() 进行图像处理。我们应该使用 cvContourArea() 确保每个轮廓都有一个适当的区域,同时我们可以使用 cvMoments() 找到它的质心。然后我们就可以开始处理其他图像了。对于每个轮廓,我尝试将这些边界矩形内的其他图像(也使用 cvThreshold() 相机二值化)中的 cvBoundingRect() 像素转换为 cvCountNonZero() 像素,我们可以通过 cvSetImageROI() 设置。如果非零计数很大,则应将其注册为 1,如果不是,则应注册为 0。

一旦获得了所有位,就获得了代码,然后就完成了。

Markers, as I used for ProCamCalib, should be detected more robustly than checkerboard pattern. You can use ARToolkitPlus as with ProCamCalib, but there are other alternatives, or you could make your own little detector. :) Then, with the detected corner coordinates of the markers, we can calibrate in the same way, using the rest of the calibration functions of OpenCV.

And I can do cool stuff with it too, as shown on the page of ProCamTracker.

EDIT: Now that I understand the question better, we can accomplish this for static scenes quite easily, although OpenCV won't help us much. First, we place the camera at the position from which we would like a viewer to see a corrected projection. Then, we project binary patterns (which look like locally flashing dots), and capture images of those dots patterns. (We can make them denser, until they become bars, a technique known as structured light.) After detecting from the camera images and decoding those dots into binary codes, we get the camera<->projector pixel correspondences, well some amount of vertices anyway, and from there it's 100% graphics. Here is a paper that covers these steps in some more details:

Zollmann, S., Langlotz, T. and Bimber, O.
Passive-Active Geometric Calibration for View-Dependent Projections onto Arbitrary Surfaces
http://140.78.90.140/medien/ar/Pub/PAGC_final.pdf
Demo video: http://140.78.90.140/medien/ar/Pub/PAGC.avi

EDIT2: By projecting some kind of pattern, we can figure out the pixel coordinates in the projector image that corresponds to a given pixel in the camera image. We often use temporal dot patterns because it's easy to detect and decode... And actually, OpenCV might come in handy for this. The way I think I'd try to do it would go something like this. Let's take only 2 bits for simplicity. We thus have four images: 00, 01, 10, and 11. Since we control the projector image, we know those, but we have to find them in the camera image as well. First I would take the last (camera) image, 11, and subtract it from the first (camera) image 00, using cvAbsDiff(), then binarize the result with cvThreshold(), and find the contours (or blobs) in the binary image with cvFindContours(). We should make sure each contours have an appropriate area with cvContourArea(), while we can find its centroid with cvMoments(). Then we can start doing stuff with the other images. For each contour, I'd try to take the cvBoundingRect() to cvCountNonZero() pixels in the other (also binarized with cvThreshold() camera) images, inside these bounding rectangles, which we can set via cvSetImageROI(). If the nonzero count is large, that should be registered as a 1, if not, a 0.

Once you have all the bits, you have the code, and you're done.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文