OpenCV  4.10.0
开源计算机视觉
正在加载...
正在搜索...
没有匹配内容
重新映射

上一个教程: 使用广义 Ballard 和 Guil Hough 变换进行目标检测
下一个教程: 仿射变换

原作者Ana Huamán
兼容性OpenCV >= 3.0

目标

本教程将学习如何

a. 使用 OpenCV 函数 cv::remap 实现简单的重新映射例程。

理论

什么是重新映射?

  • 从图像的一个位置获取像素,然后将它们定位在新图像的另一个位置的过程。
  • 为了实现映射过程,对于非整数像素位置可能需要执行一些插值,因为源图像和目标图像之间并不总存在一对一像素对应关系。
  • 我们可以对每个像素位置 \((x,y)\) 表示重新映射为

    \[g(x,y) = f ( h(x,y) )\]

    其中 \(g()\) 是重新映射的图像,\(f()\) 是源图像,\(h(x,y)\) 是操作 \((x,y)\) 的映射函数。

  • 让我们思考一个简单的示例。假设我们有一幅图像 \(I\),并且我们想要执行重新映射,比如

    \[h(x,y) = (I.cols - x, y )\]

    会发生什么?很容易看出图像将在 \(x\) 方向翻转。例如,考虑输入图像

观察红色圆圈如何相对于 x 改变位置(将 \(x\) 视为水平方向)

  • 在 OpenCV 中,函数 cv::remap 提供了简单的重新映射实现。

代码

  • 此程序做什么?
    • 加载图像
    • 每秒,将四种不同的重新映射过程中的 1 种应用到图像中,并将它们无限期地显示在一个窗口中。
    • 等待用户退出程序

解释

  • 加载一张图片

  • 创建目标图片和两个映射矩阵(用于 x 和 y)

  • 创建窗口来显示结果

  • 建立循环。每 1000 毫秒我们都会更新映射矩阵(mat_xmat_y)并将它们应用到源图像中

  • 用于执行重新映射的函数是 cv::remap 。我们给出了以下参数

    • src: 源图像
    • dst: 与 src 大小相同的目标图像
    • map_x: x 方向上的映射函数。它等价于 \(h(i,j)\) 的第一分量
    • map_y: 如上所述,但位于 y 方向。请注意,map_ymap_x 都与 src 大小相同
    • INTER_LINEAR: 用于非整数像素的插值类型。这是默认值。
    • BORDER_CONSTANT: 默认

    我们如何更新映射矩阵 mat_xmat_y?继续阅读

  • 更新映射矩阵: 我们将执行 4 种不同的映射
    1. 将图片缩小到其大小的一半,并将其显示在中间位置

      \[h(i,j) = ( 2 \times i - src.cols/2 + 0.5, 2 \times j - src.rows/2 + 0.5)\]

      对于所有这样的成对 \((i,j)\) :\(\dfrac{src.cols}{4}<i<\dfrac{3 \cdot src.cols}{4}\) 并且 \(\dfrac{src.rows}{4}<j<\dfrac{3 \cdot src.rows}{4}\)
    2. 将图像上下颠倒:\(h( i, j ) = (i, src.rows - j)\)
    3. 从左向右反射图像:\(h(i,j) = ( src.cols - i, j )\)
    4. b 和 c 的组合:\(h(i,j) = ( src.cols - i, src.rows - j )\)

这在下面的代码片段中有所体现。在其中,map_x 表示 h(i,j) 的第一个坐标,map_y 表示第二个坐标。

结果

  1. 在编译完上面的代码后,你可以通过输入一个图像路径来运行它。例如,以下图像
  1. 这是将其缩小到一半大小并将其置中的结果
  1. 将其上下颠倒
  1. 沿 x 方向反射
  1. 沿两个方向反射