
    $h%                     P    d dl Z d dlZd dlZd dlZd dlmZ d dlmZ  G d d      Zy)    N)datetime)timezonec                   N    e Zd Zd Zd Zd Zd Zedede	fd       Z
ed        Zy	)

Proctoringc                 D    d| _         d| _        d| _        t        d       y)zE
        Initialize without loading heavy models immediately
        NFzProctoring service initialized)faceDetectorfa_models_loadedprint)selfs    0/var/www/html/engine/services/proctor/proctor.py__init__zProctoring.__init__   s$     !#./    c                 @   | j                   sq	 ddlm} ddl} |d      | _        | j                  j
                  j                          |j                  |j                  j                  dd      | _
        d| _         yy# t        $ r}t        d	|        |d}~ww xY w)
z4
        Lazy load models when first needed
        r   )YOLONz'services/proctor/models/yolov8n-face.ptFcpu)
flip_inputdeviceTzError loading models: )r
   ultralyticsr   face_alignmentr   modelfuseFaceAlignmentLandmarksTypeTWO_Dr	   	Exceptionr   )r   r   r   es       r   _load_modelszProctoring._load_models   s     "",%$()R$S!!!'',,.(66"0066$  7 
 '+# #  .qc23s   A/A? ?	BBBc           
         | j                   s| j                          |j                  dd \  }}| j                  j	                  |dd      d   }d}d}d}d}|j
                  t        |j
                        dk(  rddddS |j
                  D ]]  }	t        t        |	j                  d   j                               \  }
}}}|
dk\  s9|dk\  s?||k  sE||k  sK||
kD  sQ||kD  sW|dz  }d	}_ |j
                  D ]  }	|r nt        t        |	j                  d   j                               \  }
}}}|
dk\  r|dk\  r||k  r||k  r
||
kD  r||kD  sX||||
|f   }|j                  dk(  rs	 | j                  j                  |      }|t        |      dk(  r|d   }|t!        j"                  |
|g      z  }t!        j"                  |d   |d   |d   |d   |d   |d   gt         j$                        }t!        j"                  g dg dg dg dg dg dgt         j$                        }|}t!        j"                  |d|dz  gd||dz  gg dgt         j$                        }t!        j&                  d      }t)        j*                  ||||      \  }}}|st)        j,                  |      \  }}t!        j.                  |d   dz  |d   dz  z         }|dk  r:t!        j0                  |d    |d         }t!        j0                  |d    |      }d}nRt!        j0                  |d    |d!         }t!        j0                  |d    |      }t!        j0                  |d   |d         }t3        t!        j4                  |      d      t3        t!        j4                  |      d      t3        t!        j4                  |      d      d"}d	} |||dS # t        $ r}t        d
|        Y d}~d}~ww xY w)#z
        Analyze the frame to detect faces and compute head orientation.
        Returns:
            dict with keys: face_detected, people_count, head_pose (yaw, pitch, roll)
        Use case: Core vision engine for your proctoring system.
        N   i  F)sourceimgszverboser   )face_detectedpeople_count	head_pose   TzLandmark detection failed:       $   -   0   6   )dtype)        r/   r/   )r/   gOg      ))gfffffE皙Y@@      :)gfffffE@r0   r1   )fffff<r2   皙8)gfffff<@r2   r3   )r   r   r'   )   r'   )r   r   )r'   r   gư>)r'   r    )r'   r'   )r    r   )r    r'   )r    r    )yawpitchroll)r
   r   shaper   predictboxeslenmapintxyxytolistsizer	   get_landmarks_from_imager   r   nparrayfloat64zeroscv2solvePnP	Rodriguessqrtarctan2rounddegrees)r   framehwpredsfaceDetectedpeopleCountheadPosefirstFaceAnalyzedboxx1y1x2y2faceCrop	landmarksr   lmimagePointsmodelPointsfocalLengthcameraMatrix
distCoeffssuccessrot_Rsyxyzs                                  r   analyzeFramezProctoring.analyzeFrame'   s    ""{{2A1!!))c5)QRST! ;;#ekk"2a"7!& !!  ;; 	$C chhqk&8&8&:;NBB Qw27rQw27rBw2PR7q #	$ ;; L	)C  chhqk&8&8&:;NBB !GaB!GaBGPRUWPWRUBrE\*H }}! GG<<XF	
  C	Na$71B"((B8$$B ((212222$ ZZ!K ((#$#%$$ ZZ!K K88aQ'KQ'% ZZ	!L &)J!ll;\S]^OGS!}}S)1WWQtWaZ!D'1*459

AdG8QtW5A

AdG8R0AA

1T7AdG4A

AdG8R0A

1T7AdG4A !A2"2::a=!4!"**Q-3
 %)!YL	)^ *'!
 	
y  3A378s   .O	O1O,,O1c                    	 t        d       t        j                  |      }t        j                  t        j                  |t
        j                        t        j                        }|t        d      	 | j                  |      }d}d}|d   r!|d   }| j                  |d   |d   |d	         }d}	 d
dlm}	 |	j                  |dgdd      }
t!        |
t"              r't%        |
      d
kD  r|
d
   d   }| j'                  |      }t-        j.                  t1        d            j3                         }|d   |d   ||g ||d}|S # t        $ r}t        d      |d}~ww xY w# t        $ r}t)        j*                          Y d}~}d}~ww xY w)a  
        Comprehensive proctoring analysis including face detection, emotion analysis, and head pose estimation.
        
        Args:
            image_b64 (str): Base64 encoded image string
            
        Returns:
            dict: Complete analysis results with all proctoring data
            
        Raises:
            ValueError: If image decoding fails
            Exception: For other processing errors
        zStarting comprehensive analysisNzDecoded image is NonezInvalid base64 imagezNot detectedr&   r5   r6   r7   r   )DeepFaceemotionFopencv)img_pathactionsenforce_detectiondetector_backendzAsia/Kolkatar$   r%   )r$   r%   r&   dominant_emotionflags	timestamphead_orientation_readable)r   base64	b64decoderF   imdecoderB   
frombufferuint8IMREAD_COLOR
ValueErrorr   rj   describeHeadPosedeepfacerl   analyze
isinstancelistr;   fuseEmotions	traceback	print_excr   nowr   	isoformat)r   	image_b64	imageDatarM   r   visionResultsheadPoseDataheadOrientationReadabledominantEmotionrl   analysisemotionsistTimeresponse_datas                 r   comprehensiveAnalysisz Proctoring.comprehensiveAnalysis   s   	<34((3ILLy"((!CSEUEUVE} !899  ))%0 "0%(5L&*&;&;U#W%V$'# 	")''""'!)	 ( H (D)c(ma.?#A;y1"&"3"3H"= ,,x78BBD +?;).9% / )@
 g  	<34!;	<B  	"!!	"s1   A3E 4AE" 	EEE"	F	+FF	r   returnc                     | d   | d   z   | d   z   dz  }| d   | d   z   dz  }| d   }| d   }| d   }|||||d	}t        ||j                  
      S )Nfearangrydisgust   happyneutralr    sad)nervousrelaxedr   r   r   )key)maxget)r   r   r   r   r   r   	composites          r   r   zProctoring.fuseEmotions   s    F#hw&77(9:MMQRRG$x	'::a?!uo
	 9)--00r   c                 >   g }| dkD  r|j                  d       n| dk  r|j                  d       |dkD  r|j                  d       n|dk  r|j                  d       |dkD  r|j                  d       n|d	k  r|j                  d
       |rdj                  |      S dS )N   zlooking rightizlooking leftzlooking downz
looking up   zhead tilted rightizhead tilted leftz, zfacing forward)appendjoin)r5   r6   r7   orientations       r   r~   zProctoring.describeHeadPose   s    8[''83Y**>:2:{)).9S[+,,\:"9k(()<=CZ++,>?)4tyy%J:JJr   N)__name__
__module____qualname__r   r   rj   r   staticmethoddictstrr   r~    r   r   r   r      sR    0,w
rHT 1t 1 1 1  	K 	Kr   r   )	rF   numpyrB   r   rw   r   pytzr   r   r   r   r   <module>r      s"    
    ~K ~Kr   