TOC
How does warp Perspective work?
1.warp perspective with cv2
if __name__ == "__main__":
# coordinate: (y,x), left_top, right_rop, left_bottom, right_bottom
src = np.float32([[20.0, 0.0], [20.0 ,315.0], [186.0, 17.2], [181.0, 299.0]])
dst = np.float32([[0.0, 0.0], [0.0, 315.0], [202.0, 7.0], [200.0, 306.0]])
# load image
warp_img = cv2.imread("./my_wide_angle_orig.jpg")
warp_img = cv2.cvtColor(warp_img, cv2.COLOR_BGR2RGB)
print("warp_img: ",warp_img.shape) # (638, 958, 3)
width = int(warp_img.shape[1]/3)
height = int(warp_img.shape[0]/3)
warp_img = cv2.resize(warp_img, (width,height), interpolation=cv2.INTER_LINEAR)
print("warp_img.shape:",warp_img.shape) # (212, 319, 3)
## orig image
plt.subplot(121),
plt.title("warp_img")
plt.imshow(warp_img)
# cv2 warp perspective
cv2_matrix = cv2.getPerspectiveTransform(src, dst)
print("cv2_matrix:\n",cv2_matrix)
cv2_fix_img = cv2.warpPerspective(warp_img, cv2_matrix, (width,height))
plt.subplot(122),
plt.title('cv2_fix_img')
plt.imshow(cv2_fix_img)
plt.show()
2.Implement it in our way
Step1 calculate warp matrix:
my_warp_matrix reshape:
[[ 1.13729359e+00 -8.24289989e-18 -2.27458717e+01]
[-6.10786436e-02 9.69843448e-01 1.22157287e+00]
[-3.44743207e-04 -7.38466280e-05 1.00000000e+00]]
Step2. use the warp matrix to warp perspective
codes are:
import numpy as np
from matplotlib import pyplot as plt
import cv2
class MyPerspectiveTransform:
def calcWarpMatrix(self, src, dst):
A_matrix = [];
B_vector = [];
for src_i, src_v in enumerate(src):
# X0
A_matrix.append( [src_v[0], src_v[1], 1, 0, 0, 0,
-src_v[0]*dst[src_i][0], - src_v[1]*dst[src_i][0] ]);
B_vector.append(dst[src_i][0]);
# Y0
A_matrix.append( [0, 0, 0, src_v[0], src_v[1], 1, -src_v[0]*dst[src_i][1],
-src_v[1]*dst[src_i][1] ]);
B_vector.append(dst[src_i][1]);
A_matrix = np.array(A_matrix)
B_vector = np.array(B_vector)
A_matrix = np.mat(A_matrix)
B_vector = np.expand_dims(B_vector, axis = 1)
# A_matrix * warp_matrix = B_vector
# So, A_vectro = A_matrix^-1 * B_vector
warp_matrix = A_matrix.I * B_vector
warp_matrix = np.insert(warp_matrix, warp_matrix.shape[0],1)
warp_matrix = warp_matrix.reshape((3,3))
print("my_warp_matrix reshape:\n", warp_matrix);
self.warp_matrix = warp_matrix;
return warp_matrix;
def myWarpPerspective(self,warp_img):
# for c in range(warp_img.shape):
fix_matrix = self.warp_matrix;
a_11 = fix_matrix[0,0]
a_12 = fix_matrix[0,1]
a_13 = fix_matrix[0,2]
a_21 = fix_matrix[1,0]
a_22 = fix_matrix[1,1]
a_23 = fix_matrix[1,2]
a_31 = fix_matrix[2,0]
a_32 = fix_matrix[2,1]
a_33 = fix_matrix[2,2]
fix_img = np.zeros((warp_img.shape));
max_y = warp_img.shape[0] - 1;
max_x = warp_img.shape[1] - 1;
for height_i in range(warp_img.shape[0]): # height or y
for width_i in range(warp_img.shape[1]): # width or x
Y_fix = height_i;
X_fix = width_i;
# get y by
y_denominator = (a_31*Y_fix - a_21)*a_12 - (a_31*Y_fix - a_21)*a_32*X_fix - (a_31*X_fix - a_11)*a_22 + (a_31*X_fix - a_11)*a_32*Y_fix ;
y = ( (a_23 - a_33*Y_fix - ((a_31*Y_fix - a_21)*a_13)/(a_31*X_fix - a_11)
+ ((a_31*Y_fix - a_21)*a_33*X_fix)/(a_31*X_fix - a_11) )
* (a_31*X_fix - a_11) ) / y_denominator
x = (a_12*y + a_13 - (a_32*y*X_fix + a_33*X_fix)) / (a_31*X_fix - a_11)
# print("height_i:",height_i,",width_i:",width_i,",y:",y,",fix_x:",x)
y = int(np.round(y))
x = int(np.round(x))
if y < 0:
y = 0;
if y > max_y:
y = max_y;
if x < 0:
x = 0;
if x > max_x:
x = max_x;
c_i = 0;
fix_img[height_i,width_i,c_i] = warp_img[y,x,c_i]
c_i = 1;
fix_img[height_i,width_i,c_i] = warp_img[y,x,c_i]
c_i = 2;
fix_img[height_i,width_i,c_i] = warp_img[y,x,c_i]
print("height_i:",height_i,",width_i:",width_i,",y:",y,"fix_x:",x)
return fix_img
if __name__ == "__main__":
# coordinate: (y,x), left_top, right_rop, left_bottom, right_bottom
src = np.float32([[20.0, 0.0], [20.0 ,315.0], [186.0, 17.2], [181.0, 299.0]])
dst = np.float32([[0.0, 0.0], [0.0, 315.0], [202.0, 7.0], [200.0, 306.0]])
myPerspectiveTransform = MyPerspectiveTransform()
myPerspectiveTransform.calcWarpMatrix(src, dst) # my (x,y)
# load image
warp_img = cv2.imread("./my_wide_angle_orig.jpg")
warp_img = cv2.cvtColor(warp_img, cv2.COLOR_BGR2RGB)
print("warp_img: ",warp_img.shape) # (638, 958, 3)
width = int(warp_img.shape[1]/3)
height = int(warp_img.shape[0]/3)
warp_img = cv2.resize(warp_img, (width,height), interpolation=cv2.INTER_LINEAR)
print(width,",height:",height,", ",warp_img.shape) # (212, 319, 3)
#
plt.subplot(121),
plt.title("warp_img"),#plt.xticks([]);plt.yticks([]);
plt.imshow(warp_img)
# Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers)
fix_img = myPerspectiveTransform.myWarpPerspective(warp_img)
fix_img = (fix_img).astype(np.uint8)
plt.subplot(122),
plt.imshow(fix_img)
plt.title('my_fix_img'),#plt.xticks([]),plt.yticks([]);
plt.show()
Here shows how to get x
and y
, codes:
'''
# get x
(a_31*x + a_32*y + a_33) * X_fix = (a_11*x + a_12*y + a_13)
=> a_31*x*X_fix + a_32*y*X_fix + a_33*X_fix = a_11*x + a_12*y + a_13
=> a_31*x*X_fix - a_11*x = a_12*y + a_13 - (a_32*y*X_fix + a_33*X_fix)
=> x = [a_12*y + a_13 - (a_32*y*X_fix + a_33*X_fix)] / (a_31*X_fix - a_11)
# get y
(a_31*x + a_32*y + a_33) * Y_fix = (a_21*x + a_22*y + a_23)
=> a_31*x*Y_fix + a_32*y* Y_fix + a_33*Y_fix - a_21*x = (a_22*y + a_23)
=> a_31*x*Y_fix - a_21*x = (a_22*y + a_23) - (a_32*y*Y_fix + a_33*Y_fix)
=> (a_31*Y_fix - a_21)*x = (a_22*y + a_23) - (a_32*y*Y_fix + a_33*Y_fix)
# get y without x, remove x
=> (a_31*Y_fix - a_21){[a_12*y + a_13 - a_32*y*X_fix - a_33*X_fix] / (a_31*X_fix - a_11)}
= (a_22*y + a_23) - (a_32*y*Y_fix + a_33*Y_fix)
=> (a_31*Y_fix - a_21){[a_12*y + a_13 - a_32*y*X_fix - a_33*X_fix] / (a_31*X_fix - a_11)}
= a_22*y + a_23 - a_32*y*Y_fix - a_33*Y_fix
=> [(a_31*Y_fix - a_21)*a_12*y] / (a_31*X_fix - a_11) +
[(a_31*Y_fix - a_21)*a_13] / (a_31*X_fix - a_11) -
[(a_31*Y_fix - a_21)*a_32*y*X_fix] / (a_31*X_fix - a_11) -
[(a_31*Y_fix - a_21)*a_33*X_fix] / (a_31*X_fix - a_11) = a_22*y + a_23 - a_32*y*Y_fix - a_33*Y_fix
=> [(a_31*Y_fix - a_21)*a_12*y] / (a_31*X_fix - a_11) +
[(a_31*Y_fix - a_21)*a_13] / (a_31*X_fix - a_11) -
[(a_31*Y_fix - a_21)*a_32*y*X_fix] / (a_31*X_fix - a_11) -
[(a_31*Y_fix - a_21)*a_33*X_fix] / (a_31*X_fix - a_11) - a_22*y + a_32*y*Y_fix = a_23 - a_33*Y_fix
=> [(a_31*Y_fix - a_21)*a_12*y] / (a_31*X_fix - a_11) -
[(a_31*Y_fix - a_21)*a_32*y*X_fix] / (a_31*X_fix - a_11) - a_22*y + a_32*y*Y_fix
= a_23 - a_33*Y_fix
- [(a_31*Y_fix - a_21)*a_13] / (a_31*X_fix - a_11)
+ [(a_31*Y_fix - a_21)*a_33*X_fix] / (a_31*X_fix - a_11)
=> { [(a_31*Y_fix - a_21)*a_12*y] - [(a_31*Y_fix - a_21)*a_32*y*X_fix] - (a_31*X_fix - a_11)* a_22*y + (a_31*X_fix - a_11)*a_32*y*Y_fix }
/ (a_31*X_fix - a_11)
= a_23 - a_33*Y_fix
- [(a_31*Y_fix - a_21)*a_13] / (a_31*X_fix - a_11)
+ [(a_31*Y_fix - a_21)*a_33*X_fix] / (a_31*X_fix - a_11)
=>{ [(a_31*Y_fix - a_21)*a_12*y] - [(a_31*Y_fix - a_21)*a_32*y*X_fix] - (a_31*X_fix - a_11)* a_22*y + (a_31*X_fix - a_11)*a_32*y*Y_fix }
= {a_23 - a_33*Y_fix
- [(a_31*Y_fix - a_21)*a_13] / (a_31*X_fix - a_11)
+ [(a_31*Y_fix - a_21)*a_33*X_fix] / (a_31*X_fix - a_11)} * (a_31*X_fix - a_11)
=> y * { [(a_31*Y_fix - a_21)*a_12] - [(a_31*Y_fix - a_21)*a_32*X_fix] - (a_31*X_fix - a_11)* a_22 + (a_31*X_fix - a_11)*a_32*Y_fix }
= {a_23 - a_33*Y_fix
- [(a_31*Y_fix - a_21)*a_13] / (a_31*X_fix - a_11)
+ [(a_31*Y_fix - a_21)*a_33*X_fix] / (a_31*X_fix - a_11) } * (a_31*X_fix - a_11)
=> y = { {a_23 - a_33*Y_fix
- [(a_31*Y_fix - a_21)*a_13]/(a_31*X_fix - a_11)
+ [(a_31*Y_fix - a_21)*a_33*X_fix]/(a_31*X_fix - a_11) }
* (a_31*X_fix - a_11) }
/ { [(a_31*Y_fix - a_21)*a_12] - [(a_31*Y_fix - a_21)*a_32*X_fix] - (a_31*X_fix - a_11)* a_22 + (a_31*X_fix - a_11)*a_32*Y_fix }
At the end, replace the curly bracket and square brackets with bracket while execute it python.
'''
「点个赞」
点个赞
使用微信扫描二维码完成支付
