I have found a perspective matrix using:
import numpy as np
import cv2 as cv
points_src = np.single([[0, 0], [0, 1], [1, 1], [1, 0]])
points_dst = np.single([[0.5, 0.5], [0.5, 2], [2, 2], [2, 0.5]])
perspective_matrix = cv.getPerspectiveTransform(points_src, points_dst)
Which yields the expected:
>>> perspective_matrix
array([[1.5, 0. , 0.5],
[0. , 1.5, 0.5],
[0. , 0. , 1. ]])
However, when I try and transform points using perspectiveTransform:
points_original = np.single([[0, 0]])
points_transformed = cv.perspectiveTransform(points_original, perspective_matrix)
I get the following error:
"error: (-215:Assertion failed) scn 1 == m.cols in function 'cv::perspectiveTransform'"
I have tried padding the points_original coordinates with a trailing 1 (np.single([[0, 0, 1]])), as it looks like is done in the documentation, as well as adding more points (np.single([[0, 0], [1, 1]]) or np.single([[0, 0, 1], [1, 1, 1]])), removing a layer of nesting in the lists (np.single([0, 0]), np.single([0, 0, 0])), etc, etc, and I can't figure out what is still going wrong. TIA.
CodePudding user response:
Answering my own question based on the helpful comments received from @Dan Mašek.
According to the docs, src should be:
input two-channel or three-channel floating-point array.
In order for OpenCV to map the numpy array to cv::Mat (the C class that OpenCV uses), the channels (usually RGB components, but in this case coordinates) need to be the 3rd dimension/axis (first dimension are rows, second columns).
Either create the properly shaped array, by adding another level of nesting to the initial list: np.single([[[0, 0]]]), or reshape the existing array: np.single([[0, 0]]).reshape(-1,1,2). This results in as many rows as necessary (one in this case), one column per row, and two channels per column.
TLDR:
I just required an extra layer of nesting, for example:
points_original = np.single([[[0, 0]]])
points_transformed = cv.perspectiveTransform(points_original, perspective_matrix)
