如何使用opencv自动将源图像转换为目标图像



>IMAGE 我在左边有源图像。我使用油漆中的网格手动扭曲了此图像,结果在右侧。我想知道 opencv 是否提供了任何比较两个图像并提供一些转换矩阵的功能,我可以将其用于进一步使用。例如,将此矩阵传递给视频,我像右侧的图像一样扭曲了视频。

我感谢这个社区的帮助:)

我想知道 opencv 是否提供任何比较两个图像并提供一些我可以进一步使用的转换矩阵的功能。

OpenCV 或任何其他库都无法计算非线性变换的变换矩阵。不可能将非线性变换表示为变换矩阵。但是,人们可能会发现一个变换矩阵,它将是非线性变换的线性近似。这种近似不一定会产生令人满意的结果。

由于您扭曲的图像具有检查图案,因此您可以通过正方形角的移动来描述失真。我建议您尝试以下两步法:

步骤1:在原始图像和扭曲图像中查找角落。
OpenCV具有许多用于相机校准的功能,专为检查图案图像而设计。以下函数使用 OpenCV 中的 cv2.findChessboardCorners 函数来查找角点。注意:get_chessboard_corner_points返回相对坐标,而不是确切坐标。

def get_chessboard_corner_points(img, corner_shape=(10,15)):
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.01)
success, corners = cv2.findChessboardCorners(img, corner_shape)
if success:
corners = cv2.cornerSubPix(img, corners, (11,11), (-1,-1), criteria)
corners = np.squeeze(corners, axis=1)
for i in range(len(corners)):
corners[i] = (corners[i][0]/img.shape[1], corners[i][1]/img.shape[0])
#You may also try adding boundary points of the image by uncommenting the next line.
#corners = np.append(corners, np.array([[0,0],[0,1],[1,0],[1,1]]), 0)
#In addition you may also add other boundary points acording to your needs
return corners
return []

第2步: 使用插值和上一步中找到的点扭曲视频的每一帧。
现在,当您有要点时,您需要编写失真部分。distort_image功能将完成这项工作,但您可以根据需要进行更改。注:srcdest包含相对坐标。对于目标图像,我们分别以src_exactdest_exact计算并保持精确的坐标。然后,来自 SciPy 的网格数据用于插值。

def distort_image(img, src, dest):
height, width = img.shape[:2]
src_exact = []
dest_exact = []
for i in range(len(src)):
src_exact.append((int(src[i][1]*height), int(src[i][0]*width)))
dest_exact.append((int(dest[i][1]*height), int(dest[i][0]*width)))
grid_x, grid_y = np.mgrid[0:height - 1:complex(0, height), 0:width - 1:complex(0, width)]
grid_z = griddata(dest_exact, src_exact, (grid_x, grid_y), method='cubic')
map_x = np.append([], [ar[:, 1] for ar in grid_z]).reshape(height, width)
map_y = np.append([], [ar[:, 0] for ar in grid_z]).reshape(height, width)
map_x_32 = map_x.astype('float32')
map_y_32 = map_y.astype('float32')
distorted = cv2.remap(img, map_x_32, map_y_32, cv2.INTER_CUBIC)
return distorted

这里有几行允许您测试上面介绍的功能。

import cv2
import numpy as np
from scipy.interpolate import griddata
TEST_IMG_PATH = "" #path to original grid 
SOURCE_IMG_PATH = "" #path to distorted grid 
DEST_IMG_PATH = "" #path to image to be distorted(this can be replaced by a video frame)
CORNER_SHAPE = (10, 15)
src_img = cv2.cvtColor(cv2.imread(SOURCE_IMG_PATH), cv2.COLOR_BGR2GRAY)
dest_img = cv2.cvtColor(cv2.imread(DEST_IMG_PATH), cv2.COLOR_BGR2GRAY)
test = cv2.cvtColor(cv2.imread(TEST_IMG_PATH), cv2.COLOR_BGR2RGB)
src_points = get_chessboard_corner_points(src_img, CORNER_SHAPE)
dest_points = get_chessboard_corner_points(dest_img, CORNER_SHAPE)
if len(src_points) != 0 and len(dest_points) != 0:  
result = distort_image(test, src_points, dest_points)

最新更新