OpenCV中的图像转换

23

这个问题与此问题有关:如何去除数独方格中的凸包缺陷

我试图在Mathematica to OpenCV-Python中实现nikie的答案,但我卡在了过程的最后一步。

也就是说,我在正方形中获得了所有交点,如下所示:

enter image description here

现在,我想将其转换为一个大小为(450,450)的完美正方形,如下所示:

enter image description here

(不要介意两个图像之间的亮度差异)。

问题: 我如何在OpenCV-Python中完成这个操作?我正在使用cv2版本。


2
正如他在回答中建议的那样,只需为每个单独的单元格使用标准转换(您在第一个问题中尝试使用的那个)。 - etarion
我使用了warp perspective,它使用四个角来进行转换。您是说要使用同样的方法取每个单元格的4个点吗?这不是一个费时的过程吗? - Abid Rahman K
你在谈论嵌入式编程吗?我猜不是,因为你正在使用Python……在桌面机器上,不应该有什么明显的问题,因为只有81个单元格…… - etarion
2
@AbidRahmanK:我没有测试过,但我预计透视变换的运行时间与输出像素数量成正比。因此,如果它足够快以转换整个网格,则应该足够快以转换仅为网格大小的1/81的81个网格单元。 - Niki
2个回答

36
除了etarion的建议,您还可以使用remap函数。我编写了一个快速脚本来展示如何实现这一点。正如您所看到的,在Python中编写这个非常容易。这是测试图像:

distorted image

这是扭曲后的结果:

warped image

这里是代码:

import cv2
from scipy.interpolate import griddata
import numpy as np

grid_x, grid_y = np.mgrid[0:149:150j, 0:149:150j]
destination = np.array([[0,0], [0,49], [0,99], [0,149],
                  [49,0],[49,49],[49,99],[49,149],
                  [99,0],[99,49],[99,99],[99,149],
                  [149,0],[149,49],[149,99],[149,149]])
source = np.array([[22,22], [24,68], [26,116], [25,162],
                  [64,19],[65,64],[65,114],[64,159],
                  [107,16],[108,62],[108,111],[107,157],
                  [151,11],[151,58],[151,107],[151,156]])
grid_z = griddata(destination, source, (grid_x, grid_y), method='cubic')
map_x = np.append([], [ar[:,1] for ar in grid_z]).reshape(150,150)
map_y = np.append([], [ar[:,0] for ar in grid_z]).reshape(150,150)
map_x_32 = map_x.astype('float32')
map_y_32 = map_y.astype('float32')

orig = cv2.imread("tmp.png")
warped = cv2.remap(orig, map_x_32, map_y_32, cv2.INTER_CUBIC)
cv2.imwrite("warped.png", warped)

我想你可以搜索并找到griddata的作用。简而言之,它进行插值,我们在这里使用它将稀疏映射转换为密集映射,因为cv2.remap需要密集映射。我们只需要将值转换为float32,因为OpenCV会抱怨float64类型。请告诉我进展如何。
更新:如果你不想依赖Scipy,一种方法是在你的代码中实现2D插值函数,例如,查看Scipy中griddata的源代码或像这个http://inasafe.readthedocs.org/en/latest/_modules/engine/interpolation2d.html这样更简单的函数,只依赖于numpy。虽然我建议使用Scipy或另一个库来完成这个任务,但我理解为什么只需要CV2和numpy可能更好。我想听听你的最终代码如何解决数独问题。

1
好的,太棒了。这就是我一直在寻找的东西。我知道我可以使用cv2.remap,但不知道如何使用。但是必须使用scipy吗?不能只用numpy和cv2吗?此外,是否可以在单个步骤中对整个图像使用相同的方法(即无需将其拆分为子块)? - Abid Rahman K
1
嗨,这段代码中创建grid_x和grid_y的用途是什么?它们代表什么意思? - Abid Rahman K
http://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.griddata.html - fireant
是的,请仔细阅读上面链接中的示例,你将会对该函数的工作原理有一个很好的了解。 - fireant
@bakalolo dest 是一个常规网格,因此您可以计算值。在 src 中,您需要检测线条交叉的位置。有一种方法可以做到这一点,请参见引用问题中 @nikie 的答案 - Wodin
显示剩余5条评论

1
如果您有起点和终点(只需要4个),可以将它们插入到cv2.getPerspectiveTransform中,并在cv2.warpPerspective中使用该结果。这将为您提供一个漂亮的平坦结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接