Opencv,重新映射:从文件保存并加载map1和map2

发布于 2025-01-13 11:13:38 字数 565 浏览 0 评论 0原文

为了获得更好的性能,我只想计算一次map1和map2,然后将其与remap()一起使用。两个映射的类型均为 CV_32FC1。我尝试将地图保存为 .bmp 图像或 .exr 文件,然后像这样加载它:

cv::Mat map1, map2, out_img;
map1 = cv::imread("map1.bmp", IMREAD_GRAYSCALE);
map2 = cv::imread("map2.bmp", IMREAD_GRAYSCALE);
map1.convertTo(map1, CV_32FC1);
map2.convertTo(map2, CV_32FC1);
cv::remap(in_img, out_img, map1, map2, cv::INTER_CUBIC, cv::BORDER_CONSTANT, cv::Scalar(0, 0, 0));

但我得到了黑色图像(out_img)。如果我在运行时计算map1和map2,一切都会正常,但它比从文件加载花费的时间要多得多。 我还尝试将地图存储为 xml 文件,但速度要慢得多。 所以我的问题是:有什么方法可以在每次我想使用 remap() 时不计算map1和map2?

For better performance i want to calculate map1 and map2 only once and then use it with remap(). Both maps are of type CV_32FC1. I tried to save the maps as .bmp images or .exr files and then load it like this:

cv::Mat map1, map2, out_img;
map1 = cv::imread("map1.bmp", IMREAD_GRAYSCALE);
map2 = cv::imread("map2.bmp", IMREAD_GRAYSCALE);
map1.convertTo(map1, CV_32FC1);
map2.convertTo(map2, CV_32FC1);
cv::remap(in_img, out_img, map1, map2, cv::INTER_CUBIC, cv::BORDER_CONSTANT, cv::Scalar(0, 0, 0));

But i get a black image (out_img). Everything works fine if i calculate map1 and map2 in runtime, but it tooks much more time than loading from file.
I also tried to store maps as xml files, but it is much more slowly.
So my question is: is there any way to not to calculate map1 and map2 everytime i want to use remap()?

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

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

发布评论

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

评论(2

黎夕旧梦 2025-01-20 11:13:38

有类似的问题,这是我的解决方案:

  • 在 initUn DistortRectifyMap 之后,您将得到 map1 和 map2,因为 CV_32FC1
  • 计算每个贴图各自的最小值和最大值并存储它们(它们稍后将用于帮助重新缩放)
  • 标准化贴图( Normalize(map1,map1,0,255, cv::NORM_MINMAX)),将其转换为 CV_8UC1 (convertTo(map1, CV_8UC1)) 然后存储它
  • 加载地图以及最小值和最大值,使用convertTo(map1, CV_32FC1) 然后归一化(map1,map1,minMap1,maxMap2, cv::NORM_MINMAX)。
  • 加载您想要去扭曲的图像并应用之前加载的贴图。

使用 .png 而不是 .bmp。请注意,从 CV_32FC1 到 CV_8UC1 再回到 CV_32FC1 会使图像更平滑。
性能比使用 unactor 快约 7 倍。
希望有帮助!

Had a similar problem, here is my solution:

  • after initUndistortRectifyMap you will get map1 and map2 as CV_32FC1
  • calculate the respective min and max values for each map and store them (they will be used later on to aid in the rescaling)
  • normalize the map (normalize(map1,map1,0,255, cv::NORM_MINMAX)), convert it to CV_8UC1 (convertTo(map1, CV_8UC1)) and then store it
  • load the map and the min and max values, use convertTo(map1, CV_32FC1) and afterwards normalize(map1,map1,minMap1,maxMap2, cv::NORM_MINMAX).
  • load the image you want to undistort and apply the previously loaded map.

Used .png instead of .bmp. Beware that going from CV_32FC1 to CV_8UC1 and back to CV_32FC1 makes the image smoother.
Performance was about 7x faster than using undistort.
Hope it helps!

十年不长 2025-01-20 11:13:38

还有其他一些选择。

一般来说,imread 需要 IMREAD_UNCHANGED 标志,否则它有助于将内容转换为 3 通道 8 位。

另存为 TIFF,它本身支持 float32

这要求您单独保存每个贴图,因为 imwrite 不想保存 2 通道图像 (np.dstack)。或者您插入第三个通道,其中没有任何重要内容。

这还假设 OpenCV 是在支持 TIFF 的情况下构建的。我听说情况并非总是如此,但这种情况很少见。

使用 convertMaps 获取 16 位值

并以任何可以无损存储 16 位数据的格式存储(PNG、TIFF)。 ConvertMaps 返回一个包含整数部分的 16SC2 映射和一个包含小数部分的 16UC1 映射(对于 5+5 位插值查找表来说,实际上是 10 位)。

# have xmap, ymap

(imap, fmap) = cv.convertMaps(map1=xmap, map2=ymap, dstmap1type=cv.CV_16SC2)
stacked = np.dstack([imap.astype(np.uint16), fmap])

# imwrite

# imread with IMREAD_UNCHANGED flag

imap = stacked[:,:,0:2].astype(np.int16)
fmap = stacked[:,:,2]
(xmap2, ymap2) = cv.convertMaps(map1=imap, map2=fmap, dstmap1type=cv.CV_32FC1)

# assert np.allclose(xmap, xmap2) and np.allclose(ymap, ymap2)

There are a few other options.

Generally, imread requires the IMREAD_UNCHANGED flag or else it helpfully converts things into 3-channel 8-bit.

Save as TIFF, which natively supports float32

That requires you to save each map individually because imwrite doesn't want to save a 2-channel image (np.dstack). Or you insert a third channel with nothing important in it.

This also assumes that OpenCV was built with support for TIFF. I hear that's not always the case but it's rare.

use convertMaps to obtain 16-bit values

And store in any format that can store 16 bit data without loss (PNG, TIFF). convertMaps returns one 16SC2 map containing the integer parts and a 16UC1 map containing fractional parts (practically 10 bit for 5+5 bit interpolation lookup table).

# have xmap, ymap

(imap, fmap) = cv.convertMaps(map1=xmap, map2=ymap, dstmap1type=cv.CV_16SC2)
stacked = np.dstack([imap.astype(np.uint16), fmap])

# imwrite

# imread with IMREAD_UNCHANGED flag

imap = stacked[:,:,0:2].astype(np.int16)
fmap = stacked[:,:,2]
(xmap2, ymap2) = cv.convertMaps(map1=imap, map2=fmap, dstmap1type=cv.CV_32FC1)

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