
    h0                         S r SSKJr  SSKJr  SSKJr  SSKrSSKrSSKJrJ	r	  S r
S rS	 rS
 rS rSS jrS rSS jrSS jrS rS rS rS rS rg)a[  
Functions about transforming mesh(changing the position: modify vertices).
1. forward: transform(transform, camera, project).
2. backward: estimate transform matrix from correspondences.

Preparation knowledge:
transform&camera model:
https://cs184.eecs.berkeley.edu/lecture/transforms-2
Part I: camera geometry and single view geometry in MVGCV
    )absolute_import)division)print_functionN)cossinc           	         [         R                  " U S   5      [         R                  " U S   5      [         R                  " U S   5      p2n[         R                  " / SQS[        U5      [	        U5      * /S[	        U5      [        U5      //5      n[         R                  " [        U5      S[	        U5      // SQ[	        U5      * S[        U5      //5      n[         R                  " [        U5      [	        U5      * S/[	        U5      [        U5      S// SQ/5      nUR                  UR                  U5      5      nUR                  [         R                  5      $ )a  get rotation matrix from three rotation angles(degree). right-handed.
Args:
    angles: [3,]. x, y, z angles
    x: pitch. positive for looking down.
    y: yaw. positive for looking left. 
    z: roll. positive for tilting head right. 
Returns:
    R: [3, 3]. rotation matrix.
r         r	   r   r   r   r	   r   r   r   r	   )npdeg2radarrayr   r   dotastypefloat32anglesxyzRxRyRzRs           l/var/www/fran/franai/venv/lib/python3.13/site-packages/insightface/thirdparty/face3d/mesh_numpy/transform.pyangle2matrixr      s    jj#RZZq	%:BJJvay<Q!A	xx%SVs1vg&SVs1v&( )B 
xx3q61c!f%%q6'1c!f%' (B 
xx#a&3q6'1%a&3q61%%' (B 	ffRVVBZA88BJJ    c           	      @   U S   U S   U S   p2n[         R                  " / SQS[        U5      [        U5      /S[        U5      * [        U5      //5      n[         R                  " [        U5      S[        U5      * // SQ[        U5      S[        U5      //5      n[         R                  " [        U5      [        U5      S/[        U5      * [        U5      S// SQ/5      nUR	                  U5      R	                  U5      nUR                  [         R                  5      $ )zget rotation matrix from three rotation angles(radian). The same as in 3DDFA.
Args:
    angles: [3,]. x, y, z angles
    x: pitch.
    y: yaw. 
    z: roll. 
Returns:
    R: 3x3. rotation matrix.
r   r	   r
   r   r   r   )r   r   r   r   r   r   r   r   s           r   angle2matrix_3ddfar!   /   s     QiF1I!A 
xx%SVc!f%c!fWA') *B 
xx3q61s1vg&%a&!SV$& 'B 
xx#a&#a&!$q6'CFA&%' (B 	r
rA88BJJr   c                 R    [        U5      nU R                  UR                  5      nU$ )a  rotate vertices. 
X_new = R.dot(X). X: 3 x 1   
Args:
    vertices: [nver, 3]. 
    rx, ry, rz: degree angles
    rx: pitch. positive for looking down 
    ry: yaw. positive for looking left
    rz: roll. positive for tilting head right
Returns:
    rotated vertices: [nver, 3]
)r   r   T)verticesr   r   rotated_verticess       r   rotater&   N   s'     	VA||ACC(r   c                     [         R                  " [         R                  " U[         R                  S95      nXR	                  UR
                  5      -  U[         R                  SS24   -   nU$ )a  similarity transform. dof = 7.
3D: s*R.dot(X) + t
Homo: M = [[sR, t],[0^T, 1]].  M.dot(X)
Args:(float32)
    vertices: [nver, 3]. 
    s: [1,]. scale factor.
    R: [3,3]. rotation matrix.
    t3d: [3,]. 3d translation vector.
Returns:
    transformed vertices: [nver, 3]
dtypeN)r   squeezer   r   r   r#   newaxis)r$   sr   t3dtransformed_verticess        r   similarity_transformr/   _   sO     **RXXc2::6
7C||ACC003rzz1}3EEr   c                     Sn[         R                  " [         R                  " U S-  SS95      n[         R                  " X!5      nX-  $ )Ng-q=r
   r   )axis)r   sqrtsummaximum)r   epsilonnorms      r   	normalizer7   s   s9    G77266!Q$q)*D::d$D6Mr   c                 n   Uc'  [         R                  " / SQ[         R                  5      nUc'  [         R                  " / SQ[         R                  5      n[         R                  " U5      R                  [         R                  5      n[         R                  " U5      R                  [         R                  5      n[	        X!-
  5      * n[	        [         R
                  " X45      5      n[         R
                  " XE5      n[         R                  " XVU45      nX-
  nUR                  UR                  5      nU$ )a  'look at' transformation: from world space to camera space
standard camera space: 
    camera located at the origin. 
    looking down negative z-axis. 
    vertical vector is y-axis.
Xcam = R(X - C)
Homo: [[R, -RC], [0, 1]]
Args:
  vertices: [nver, 3] 
  eye: [3,] the XYZ world space position of the camera.
  at: [3,] a position along the center of the camera's gaze.
  up: [3,] up direction 
Returns:
  transformed_vertices: [nver, 3]
)r   r   r   r   )	r   r   r   r   r7   crossstackr   r#   )	r$   eyeatupz_aixsx_aixsy_axisr   r.   s	            r   lookat_camerarA   y   s      
z88Irzz*b	z88Irzz*b
((3-

rzz
*C	"		RZZ	(B!!Frxx+,FXXf%F
&&)*A#>/33ACC8r   c                 "    U R                  5       $ )a  scaled orthographic projection(just delete z)
    assumes: variations in depth over the object is small relative to the mean distance from camera to object
    x -> x*f/z, y -> x*f/z, z -> f.
    for point i,j. zi~=zj. so just delete z
    ** often used in face
    Homo: P = [[1,0,0,0], [0,1,0,0], [0,0,1,0]]
Args:
    vertices: [nver, 3]
Returns:
    projected_vertices: [nver, 3] if isKeepZ=True. [nver, 2] if isKeepZ=False.
copy)r$   s    r   orthographic_projectrE      s     ==?r   c           
         [         R                  " U5      nU[         R                  " U5      -  nU* nXR-  nU* n[         R                  " X7-  SSS/SX5-  SS/SSXC-   * XC-
  -  SU-  U-  XC-
  -  // SQ/5      n	[         R                  " U [         R
                  " U R                  S   S45      45      n
U
R                  U	R                  5      nXSS2SS24   -  nUSS2SS24   nUSS2S4   * USS2S4'   U$ )a  perspective projection.
Args:
    vertices: [nver, 3]
    fovy: vertical angular field of view. degree.
    aspect_ratio : width / height of field of view
    near : depth of near clipping plane
    far : depth of far clipping plane
Returns:
    projected_vertices: [nver, 3] 
r   )r   r   r   r	   N   r
   )	r   r   tanr   hstackonesshaper   r#   )r$   fovyaspect_rationearfartopbottomrightleftPvertices_homoprojected_verticess               r   perspective_projectrY      s    ::dD
rvvd|
CTFE6D 	4:q!Q'TXq!$Q#(SX.3tSX0FG  	!A IIx(..2CQ1G)HIJM&**133/+qt,DD+AbqbD11!A#66qs r   c                    U R                  5       nU(       a,  USS2S4   U-  S-  USS2S4'   USS2S4   U-  S-  USS2S4'   USS2S4   US-  -   USS2S4'   USS2S4   US-  -   USS2S4'   XSS2S4   -
  S-
  USS2S4'   U$ )a  change vertices to image coord system
3d system: XYZ, center(0, 0, 0)
2d image: x(u), y(v). center(w/2, h/2), flip y-axis. 
Args:
    vertices: [nver, 3]
    h: height of the rendering
    w : width of the rendering
Returns:
    projected_vertices: [nver, 3]  
Nr   r
   r	   rC   )r$   hwis_perspectiveimage_verticess        r   to_imager_      s     ]]_N,QqS1!3A5qs,QqS1!3A5qs(1-!3N1Q3(1-!3N1Q3QqS11A5N1Q3r   c                     [         R                  " U [         R                  " U R                  S   S/5      45      n[         R                  R                  X!5      S   R                  nU$ )zUsing least-squares solution 
Args:
    X: [n, 3]. 3d points(fixed)
    Y: [n, 3]. corresponding 3d points(moving). Y = PX
Returns:
    P_Affine: (3, 4). Affine camera matrix (the third row is [0, 0, 0, 1]).
r	   r   )r   rK   rL   rM   linalglstsqr#   )XYX_homorV   s       r   estimate_affine_matrix_3d23drf      sN     YY277AGGAJq>234F
		"1%''AHr   c                 @   U R                   oR                   nUR                  S   U R                  S   :X  d   eUR                  S   nUS:  d   e[        R                  " US5      nU[        R                  " USS2[        R
                  4   SU/5      -
  n[        R                  " [        R                  " [        R                  " US-  S5      5      5      n[        R                  " S5      U-  nXQ-  n[        R                  " S[        R                  S9nU=US'   US	'   U* U-  USS2S4'   SUS
'   [        R                  " U [        R                  " SU45      45      n[        R                  " U S5      nU [        R                  " USS2[        R
                  4   SU/5      -
  n USS2SS24   U -
  n[        R                  " [        R                  " [        R                  " U S-  S5      5      5      n[        R                  " S5      U-  nXP-  n [        R                  " S[        R                  S9n	U=U	S'   =U	S	'   U	S
'   U* U-  U	SS2S4'   SU	S'   [        R                  " US-  S4[        R                  S9n
[        R                  " U [        R                  " SU45      45      R                   nXzSU2SS24'   XzUS2SS24'   [        R                  " USS/5      n[        R                  R                  U
5      R                  U5      n[        R                  " S[        R                  S9nUSS2S4   USSS24'   USS2S4   USSS24'   SUS'   [        R                  R!                  U5      R                  UR                  U	5      5      nU$ )a  Using Golden Standard Algorithm for estimating an affine camera
    matrix P from world to image correspondences.
    See Alg.7.2. in MVGCV 
    Code Ref: https://github.com/patrikhuber/eos/blob/master/include/eos/fitting/affine_camera_estimation.hpp
    x_homo = X_homo.dot(P_Affine)
Args:
    X: [n, 3]. corresponding 3d points(fixed)
    x: [n, 2]. n>=4. 2d points(moving). x = PX
Returns:
    P_Affine: [3, 4]. Affine camera matrix
r	      Nr
   r   )rI   rI   r(   r   r   r	   r	   r
   r
   rI   )rh   rh      rH   )rI   rh   )rH   rH   )r#   rM   r   meantiler+   r2   r3   zerosr   vstackrL   reshapera   pinvr   inv)rc   r   nrm   average_normscaler#   re   mUAbp_8rV   P_Affines                  r   estimate_affine_matrix_3d22dr}      s    	
AQ771:#$#	
A6N6 771a=D	BGGDBJJ'!Q00A77277266!Q$?34LGGAJ%E	A


+AAdGaguU{Abqb!eHAdG YY277Aq6?+,F771a=D	BGGDBJJ'!Q00Arr!tqA77277266!Q$?34LGGAJ%E	A


+A"''AdG'ag$uU{Abqb!eHAdG 	!A#q2::.AYY277Aq6?+,..Fbqb"1"fIab!"fI


1r1gA ))..



"C
,A"1"a%jAadG!"a%jAadGAfI yy}}Q##AEE!H-HOr   c                    U SS2S4   nU SS2SS24   nU SS2SS24   n[         R                  R                  U5      [         R                  R                  U5      -   S-  nU[         R                  R                  U5      -  nU[         R                  R                  U5      -  n[         R                  " XV5      n[         R                  " XVU4S5      nXHU4$ )zdecompositing camera matrix P
Args: 
    P: (3, 4). Affine Camera Matrix.
Returns:
    s: scale factor.
    R: (3, 3). rotation matrix.
    t: (3,). translation. 
NrI   r   r	   r
   g       @)r   ra   r6   r9   concatenate)	rV   tR1R2r,   r1r2r3r   s	            r   P2sRtr   /  s     	
!Q$A	
1Q37B	
1Q37B		biinnR0	0#5A	BIINN2	B	BIINN2	B	"	B
|Q'A7Nr   c                     [         R                  " U 5      n[         R                  " X5      n[         R                  " SU R                  S9n[         R
                  R                  X2-
  5      nUS:  $ )zMchecks if a matrix is a valid rotation matrix(whether orthogonal or not)
    rI   r(   ư>)r   	transposer   identityr)   ra   r6   )r   RtshouldBeIdentityIrt   s        r   isRotationMatrixr   D  sQ     
aBvvb}
Aqww'A
		q+,At8Or   c                 6   [         (       d   e[        R                  " U S   U S   -  U S   U S   -  -   5      nUS:  nU(       dV  [        R                  " U S   U S   5      n[        R                  " U S   * U5      n[        R                  " U S   U S   5      nO;[        R                  " U S   * U S   5      n[        R                  " U S   * U5      nS	nUS
-  [        R
                  -  US
-  [        R
                  -  US
-  [        R
                  -  pnXgU4$ )z}get three Euler angles from Rotation Matrix
Args:
    R: (3,3). rotation matrix
Returns:
    x: pitch
    y: yaw
    z: roll
ri   )r	   r   r   )r
   r	   rk   )r
   r   )r	   r
   rj   r      )r   mathr2   atan2r   pi)	r   sysingularr   r   r   rxryrzs	            r   matrix2angler   M  s     	1S6AcF?afqvo5	6BDyHJJqv#'JJ#w#JJqvqv&JJ#w#'JJ#w# 3ruuaeBEEk1S5;BB2:r   )NN)g      ?g?g     @@)F)__doc__
__future__r   r   r   numpyr   r   r   r   r   r!   r&   r/   r7   rA   rE   rY   r_   rf   r}   r   r   r    r   r   <module>r      sg   	 '  %    6 >" ( D F2
<|*r   