OpenCV 中的图像转换
问题描述
这个问题与这个问题有关: 函数.我写了一个快速脚本来展示如何做到这一点.如您所见,这在 Python 中非常简单.这是测试图片:
这是变形后的结果:
这里是代码:
导入 cv2从 scipy.interpolate 导入网格数据将 numpy 导入为 npgrid_x, grid_y = np.mgrid[0:149:150j, 0:149:150j]目的地 = 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]])源 = 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(目标,源,(grid_x,grid_y),方法='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")扭曲 = cv2.remap(原始,map_x_32,map_y_32,cv2.INTER_CUBIC)cv2.imwrite("warped.png", 扭曲)
我想你可以用谷歌搜索一下 griddata 是做什么的.简而言之,它进行插值,在这里我们使用它来将稀疏映射转换为密集映射,因为 cv2.remap 需要密集映射.我们只需要将值转换为 float32,因为 OpenCV 抱怨 float64 类型.请告诉我进展如何.
更新:如果你不想依赖Scipy,一种方法是在你的代码中实现2d插值功能,例如看Scipy中griddata的源代码或更简单的像这样 http://inasafe.readthedocs.org/en/latest/_modules/engine/interpolation2d.html 仅依赖于 numpy.不过,我建议为此使用 Scipy 或其他库,尽管我明白为什么只需要 CV2 和 numpy 对于这样的情况可能会更好.我想听听您的最终代码如何解决数独问题.
This question is related to this question: How to remove convexity defects in sudoku square
I was trying to implement nikie's answer
in Mathematica to OpenCV-Python
. But i am stuck at the final step of procedure.
ie I got the all intersection points in square like below:
Now, i want to transform this into a perfect square of size (450,450) as given below:
(Never mind the brightness difference of two images).
Question:
How can i do this in OpenCV-Python? I am using cv2
version.
Apart from etarion's suggestion, you could also use the remap function. I wrote a quick script to show how you can do this. As you see coding this is really easy in Python. This is the test image:
and this is the result after warping:
And here is the code:
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)
I suppose you can google and find what griddata does. In short, it does interpolation and here we use it to convert sparse mappings to dense mappings as cv2.remap requires dense mappings. We just need to convert to the values to float32 as OpenCV complains about the float64 type. Please let me know how it goes.
Update: If you don't want to rely on Scipy, one way is to implement the 2d interpolation function in your code, for example, see the source code of griddata in Scipy or a simpler one like this http://inasafe.readthedocs.org/en/latest/_modules/engine/interpolation2d.html which depends only on numpy. Though, I'd suggest to use Scipy or another library for this, though I see why requiring only CV2 and numpy may be better for a case like this. I'd like to hear how your final code solves Sudokus.
相关文章