我的 OpenCV remap()ing 有什么问题?
What is wrong with my OpenCV remap()ing?
我把答案中的代码 from Image transformation in OpenCV 并尝试将其改编为我的图像。
我的源图片:
在其中,我确定了方格砖中心的像素坐标,如下所示:
我的目标分辨率是784。我计算了像素的目标坐标。我的结果代码是这样的:
import cv2
from scipy.interpolate import griddata
import numpy as np
source = np.array([
[315, 15],
[962, 18],
[526, 213],
[754, 215],
[516, 434],
[761, 433],
[225, 701],
[1036, 694],
], dtype=int)
destination = np.array([
[14, 14],
[770, 14],
[238, 238],
[546, 238],
[238, 546],
[546, 546],
[14, 770],
[770, 770]
], dtype=int)
source_image = cv2.imread('frames.png')
grid_x, grid_y = np.mgrid[0:783:784j, 0:783:784j]
grid_z = griddata(destination, source, (grid_x, grid_y), method='cubic')
map_x = np.append([], [ar[:,1] for ar in grid_z]).reshape(784,784)
map_y = np.append([], [ar[:,0] for ar in grid_z]).reshape(784,784)
map_x_32 = map_x.astype('float32')
map_y_32 = map_y.astype('float32')
warped_image = cv2.remap(source_image, map_x_32, map_y_32, cv2.INTER_CUBIC)
cv2.imwrite("/tmp/warped2.png", warped_image)
如果我 运行 这个,none 的源点最终到达了它们的预定目的地,但我得到的却是一团糟。我在此处添加了目的地点:
我哪里错了?我注意到我的网格和地图数组的分布不如示例中的那样好。是我积分太少了吗?我需要在常规网格中使用它们吗?我试过只使用外角的四个点,也没有运气。
如果您只有 8 个点用于扭曲图像并且没有真正的失真,我建议使用 here 中描述的透视变换。
您引用的 link 试图消除导致非直线的额外扭曲,但图像中的所有线条都是直的。
代码如下:
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('image.png')
rows,cols,ch = img.shape
pts1 = np.float32([
[315, 15],
[962, 18],
[225, 701],
[1036, 694],
], dtype=int)
pts2 = np.float32([
[14, 14],
[770, 14],
[14, 770],
[770, 770]
], dtype=int)
M = cv2.getPerspectiveTransform(pts1,pts2)
dst = cv2.warpPerspective(img,M,(784,784))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()
整个问题是,我再次对 numpy 的 row/column 索引而不是 x/y 感到困惑。 #opencv IRC 频道中有人指出了这一点。我的源数组和目标数组必须切换它们的列:
source = np.array([
[15, 315],
[18, 962],
[213, 526],
[215, 754],
[434, 516],
[433, 761],
[701, 225],
[694, 1036],
], dtype=int)
destination = np.array([
[14, 14],
[14, 770],
[238, 238],
[238, 546],
[546, 238],
[546, 546],
[770, 14],
[770, 770]
], dtype=int)
然后它按预期工作(忽略丑陋的扭曲,这是用于查找错误的简化坐标列表):
我把答案中的代码 from Image transformation in OpenCV 并尝试将其改编为我的图像。
我的源图片:
在其中,我确定了方格砖中心的像素坐标,如下所示:
我的目标分辨率是784。我计算了像素的目标坐标。我的结果代码是这样的:
import cv2
from scipy.interpolate import griddata
import numpy as np
source = np.array([
[315, 15],
[962, 18],
[526, 213],
[754, 215],
[516, 434],
[761, 433],
[225, 701],
[1036, 694],
], dtype=int)
destination = np.array([
[14, 14],
[770, 14],
[238, 238],
[546, 238],
[238, 546],
[546, 546],
[14, 770],
[770, 770]
], dtype=int)
source_image = cv2.imread('frames.png')
grid_x, grid_y = np.mgrid[0:783:784j, 0:783:784j]
grid_z = griddata(destination, source, (grid_x, grid_y), method='cubic')
map_x = np.append([], [ar[:,1] for ar in grid_z]).reshape(784,784)
map_y = np.append([], [ar[:,0] for ar in grid_z]).reshape(784,784)
map_x_32 = map_x.astype('float32')
map_y_32 = map_y.astype('float32')
warped_image = cv2.remap(source_image, map_x_32, map_y_32, cv2.INTER_CUBIC)
cv2.imwrite("/tmp/warped2.png", warped_image)
如果我 运行 这个,none 的源点最终到达了它们的预定目的地,但我得到的却是一团糟。我在此处添加了目的地点:
我哪里错了?我注意到我的网格和地图数组的分布不如示例中的那样好。是我积分太少了吗?我需要在常规网格中使用它们吗?我试过只使用外角的四个点,也没有运气。
如果您只有 8 个点用于扭曲图像并且没有真正的失真,我建议使用 here 中描述的透视变换。
您引用的 link 试图消除导致非直线的额外扭曲,但图像中的所有线条都是直的。
代码如下:
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('image.png')
rows,cols,ch = img.shape
pts1 = np.float32([
[315, 15],
[962, 18],
[225, 701],
[1036, 694],
], dtype=int)
pts2 = np.float32([
[14, 14],
[770, 14],
[14, 770],
[770, 770]
], dtype=int)
M = cv2.getPerspectiveTransform(pts1,pts2)
dst = cv2.warpPerspective(img,M,(784,784))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()
整个问题是,我再次对 numpy 的 row/column 索引而不是 x/y 感到困惑。 #opencv IRC 频道中有人指出了这一点。我的源数组和目标数组必须切换它们的列:
source = np.array([
[15, 315],
[18, 962],
[213, 526],
[215, 754],
[434, 516],
[433, 761],
[701, 225],
[694, 1036],
], dtype=int)
destination = np.array([
[14, 14],
[14, 770],
[238, 238],
[238, 546],
[546, 238],
[546, 546],
[770, 14],
[770, 770]
], dtype=int)
然后它按预期工作(忽略丑陋的扭曲,这是用于查找错误的简化坐标列表):