I'd like to use the same affine matrix M on some individual (x,y) points as I use on images with cv2.warpAffine. It seems cv2.transform is the way to go . When I try send an Nx2 matrix of points I get negged (
src = np.array([
[x1,y1],[x2,y2],[x3,y3],[x4,y4]], dtype = "float32")
print('source shape '+str(src.shape))
dst=cv2.transform(src,M)
cv2.error: /home/jeremy/sw/opencv-3.1.0/modules/core/src/matmul.cpp:1947: error: (-215) scn == m.cols || scn + 1 == m.cols in function transform
I can get the transform I want just using numpy arithmetic :
dst = np.dot(src,M[:,0:2]) +M[:,2]
print('dest:{}'.format(dst))
But would like to understand whats going on . The docs say that cv2.transform wants a number of channels equal to number of columns in M but I'm not clear what the channels would be - maybe an 'x' channel and 'y' channel, but then would would the third be, and what would the different rows signify?
OpenCV on Python often wants points in the form
np.array([ [[x1, y1]], ..., [[xn, yn]] ])
This is not clear in the documentation for cv2.transform()
but is more clear in the documentation for other functions that use points, like cv2.perspectiveTransform()
where they mention coordinates to be on separate channels:
src – input two-channel or three-channel floating-point array
Transforms can also be used in 3D (using a 4x4
perspective transformation matrix) so that would explain the ability to use two- or three-channel arrays in cv2.transform()
.
The channel is the last dimension of the source array. Let's read the docs of cv2.transform() at the beginning.
To the question:
Because the function transforms each element from the parameter src
, the dimension of src
is required to be bigger than 2.
import cv2
import numpy as np
rotation_mat = np.array([[0.8660254, 0.5, -216.41978046], [-0.5, 0.8660254, 264.31038357]]) # 2x3
rotate_box = np.array([[410, 495], [756, 295], [956, 642], [610, 842]]) # 2x2
result_box = cv2.transform(rotate_box, rotation_mat) # error: (-215:Assertion failed) scn == m.cols || scn + 1 == m.cols in function 'transform'
The reason is the dimension of each element of rotate_box
is (2,)
. The transform by multiplication on matrices can not proceed.
To another answer: As long as the last dimension fits, other dimensions do not matter. Continue the above snippet:
rotate_box_1 = np.array([rotate_box]) # 1x4x2
result_box = cv2.transform(rotate_box_1, rotation_mat) # 1x4x2
rotate_box_2 = np.array([[[410, 495]], [[756, 295]], [[956, 642]], [[610, 842]]]) # 4x1x2
result_box = cv2.transform(rotate_box_2, rotation_mat) # 4x1x2
To reader:
Note the shape returned by cv2.transform()
is the same as the src
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With