Exquisite explanation of OpenCV algorithm: based on Python and C++, geometric transformation-projection transformation

Exquisite explanation of OpenCV algorithm: based on Python and C++, geometric transformation-projection transformation

Opencv_C_algorithm/perspective at master · ZouJiu1/Opencv_C_algorithm (github.com)?github.com/ZouJiu1/Opencv_C_algorithm/tree/master/perspective

“OpenCV Algorithm Exquisite Analysis: Based on Python and C++” (edited by Zhang Ping) [Introduction_Book Review_Online Reading] – Dangdang Books (dangdang.com)?product.dangdang.com/25182999.html

Affine transformation

The affine transformation of 2dim space can be expressed by the formula

(

x

^

y

^

)

=

[

a

11

a

12

a

twenty one

a

twenty two

]

(

x

y

)

+

(

b

1

b

2

)

\left(?x?y\right)=\left[a11a12a21a22\right] \left(xy\right) + \left(b1b2\right)

(x^y^)=[a11?a21a12?a22](xy?) + (b1?b2)

If you use 3dim, it is

(

x

^

y

^

1

)

=

[

a

11

a

12

a

13

a

twenty one

a

twenty two

a

twenty three

0

0

1

]

(

x

y

1

)

\left(?x?y1\right)=\left[a11a12a13a21a22a23001\right] \left(xy1\right)

?x^y^?1?
?=
?a11?a21?0?a12?a22?0?a13?a23?1?
?
?xy1?
?

$A=\left[\begin{matrix}a_{11} & amp;a_{12} & amp;a_{13}\ a_{21} & amp;a_{22} & amp;a_{23 } \ 0 & amp;0 & amp;1\end{matrix}\right] $ is called the affine transformation matrix. The last row has always been [0, 0, 1] and will not change. The main affine transformation Including: translation, zooming, that is, reducing and enlarging, and rotation.

Projection transformation

Similar to affine transformation, the difference is that the value in the last row of the transformation matrix is not fixed (0, 0, 1), but a changing value, that is, the projection transformation matrix is

(

x

^

y

^

z

^

)

=

[

a

11

a

12

a

13

a

twenty one

a

twenty two

a

twenty three

a

31

a

32

a

33

]

(

x

y

z

)

\left(?x?y?z\right)=\left[a11a12a13a21a22a23a31a32a33\right] \left(xyz\right)

?x^y^?z^?
?=
?a11?a21?a31a12?a22?a32a13?a23?a33
?
?xyz?
?, the projection transformation is 3dim, but the affine transformation is 2dim. Projective transformation is a transformation in space, while affine transformation is a transformation in a plane.

Projection transformation needs to meet conditions: the object is planar, and the 3dim transformation of the object is modeled through 2dim projection transformation, which is a dedicated 2dim projection transformation.

The way to calculate the projection transformation matrix is cv2.getPerspectiveTransform. Since there are 9 parameters in total, at least 9 equations, that is, 2×2 coordinates, are needed to solve.

def get():
    inpoint = np.array([[0, 0], [200, 0], [0, 200], [200, 200]], dtype=np.float32)
    outpoint = np.array([[100, 20], [200, 20], [60, 60], [260, 60]], dtype=np.float32)
    matrix = cv2.getPerspectiveTransform(inpoint, outpoint)
    return matrix
array([[ 5.0e-01, -3.5e-01, 1.0e + 02],
       [0.0e + 00, 5.0e-02, 2.0e + 01],
       [-0.0e + 00, -2.5e-03, 1.0e + 00]])

After calculating the projection transformation matrix, you can perform projection transformation on the image. The specific program can be seen:

After calculating the projection transformation matrix, you can use cv2.warpPerspective to do the projection transformation, or calculate the coordinates of each pixel after transformation to evaluate.

import os
importsys
filepath = os.path.abspath(__file__)
nam = filepath.split(os.sep)[-1]
filepath = filepath.replace(nam, "")
sys.path.append(filepath)

import cv2
import numpy as np

def get():
    inpoint = np.array([[0, 0], [200, 0], [0, 200], [200, 200]], dtype=np.float32)
    outpoint = np.array([[100, 20], [200, 20], [60, 60], [260, 60]], dtype=np.float32)
    matrix = cv2.getPerspectiveTransform(inpoint, outpoint)
    return matrix

def perspective_image():
    kk = cv2.__version__
    pth = os.path.join(filepath, r'..\shift\sunoray.png')
    img = cv2.imread(pth)
    h, w, c = img.shape
    
    color = [255, 0, 0]
    perspectiveimg = np.zeros_like(img)
    perspective[...] = color

    inpoint = np.array([[0, 0], [w - 1, 0], [0, h-1], [w-1, h-1]], dtype=np.float32)
    outpoint = np.array([[100, 100], [w - 20, 20], [60, h - 100], [w-100, h - 60]], dtype=np.float32)
    A = cv2.getPerspectiveTransform(inpoint, outpoint)
    
    # perspectimg = cv2.warpPerspective(img, A, (w, h))

    for i in range(h):
        for j in range(w):
            p = np.array([j, i, 1]).reshape((-1, 1))
            out = np.matmul(A, p)
            x = int(out[0][0])
            y = int(out[1][0])
            if x < 0 or x >= w or y < 0 or y >= h:
                continue
            perspectivemg[y, x, :] = img[i, j, :]

    cv2.imwrite(os.path.join(filepath, r'sunoray_perspective.jpg'), perspectivemg)

if __name__ == "__main__":
    get()
    perspective_image()

https://zhuanlan.zhihu.com/p/659540096