
    i=                     *   S r SSKrSSKrSSKJrJrJrJr  SS\R                  S\\\
\
\
\
4      S\S\\\4   4S jjrS\R                  S\\
\
\
\
4   S\\\\   \4   4S	 jrSS\\
\
\
\
4   S
\
S\
S\4S jjrSS\S\S\4S jjrS\S\4S jrS\R                  S\\
\
\
\
4   S\S\S\\\4   4
S jrS\R                  S\R                  S\4S jrSS\\R                     S\S\\\\\
   4   4S jjrS\R                  S\\\
\
\
\
4      4S jrg)zb
Image Quality Validation Service
Provides comprehensive validation for face registration images.
    N)TupleListDictOptionalimage	face_bbox	thresholdreturnc                     [         R                  " U [         R                  5      nU(       a  Uu  pEpgX5XW-   2XDU-   24   n[         R                  " U[         R                  5      R                  5       nX:  n	X4$ )aI  
Detect blur using Laplacian variance method.

Args:
    image: Input image (BGR format)
    face_bbox: Optional face bounding box (x, y, w, h). If None, uses entire image.
    threshold: Minimum variance threshold (default: 80 - more lenient, focuses on face clarity)

Returns:
    Tuple of (is_blurry: bool, blur_score: float)
)cv2cvtColorCOLOR_BGR2GRAY	LaplacianCV_64Fvar)
r   r   r	   grayxywhlaplacian_var	is_blurrys
             6/var/www/fran/franai/services/image_quality_service.pydetect_blurr   
   sp     <<s112D 
aacE1qS5L! MM$

3779M)I##    c                    [         R                  " U [         R                  5      nUu  p4pVXXF-   2X3U-   24   n[         R                  " U[         R                  5      n[        [        R
                  " U5      5      n	[        R                  " US:  R                  [        5      5      n
UR                  n[        X-  5      n[        [        R
                  " U5      5      n[        [        R                  " U5      5      n[        [        R                  " U5      5      n[        [        R                  " U5      5      n[        UU-
  5      n[        [        R                  " US:H  5      UR                  -  5      n[        [        R                  " US:H  5      UR                  -  5      n[        R                  " UR                  [        S9nSUXDU-   2X3U-   24'   UU   n[!        U5      S:  a  [        [        R
                  " U5      5      OU	nSnUUU-   :  n[        R                  " US:  R                  [        5      5      n[        UUR                  -  5      n[        R                  " US:  R                  [        5      5      n[        UUR                  -  5      nUUUUUUUUUU	UUUX-
  S	.n/ nU	S
:  a  UR#                  S5        OU	S:  a  UR#                  S5        US:  a  UR#                  S5        US
:  a  UR#                  S5        OUS:  a  UR#                  S5        US:  a  UR#                  S5        US:  a  UR#                  S5        U(       a  US:  a  UR#                  S5        US:  a  UR#                  S5        US:  a  UR#                  S5        US:  a  UR#                  S5        XS-   :  a  UR#                  S5        US:  a  UR#                  S5        [!        U5      S:H  UU4$ )z
Comprehensive lighting validation for both face region and overall environment.

Args:
    image: Input image (BGR format)
    face_bbox: Face bounding box (x, y, w, h)

Returns:
    Tuple of (is_valid: bool, issues: List[str], metrics: Dict)
   r      )dtypeFF         )face_mean_brightnessface_brightness_stdface_min_brightnessface_max_brightnessface_contrastface_clipped_darkface_clipped_brightface_very_bright_percentageface_moderate_bright_percentageenv_brightnessenv_glare_percentagebackground_brightness
is_backlitbrightness_diff<   environment_too_darkenvironment_too_brightQ?excessive_glareface_too_darkface_too_bright333333?(   backlit   low_contrast皙?underexposed333333?overexposed
   uniform_lighting)r   r   r   floatnpmeansumastypeintsizestdminmaxonesshapeboollenappend)r   r   	gray_fullr   r   r   r   face_region	gray_facer,   env_glare_pixelsenv_total_pixelsr-   r#   r$   r%   r&   r'   r(   r)   maskbackground_regionr.   backlight_thresholdr/   face_very_bright_pixelsr*   face_moderate_bright_pixelsr+   metricsissuess                                  r   validate_lightingr^   %   s    UC$6$67I JA!!#q1u%K[#*<*<=I 2779-.Nvvy366s;< ~~ !1!DE !!34y 12bffY/0bffY/0+.AABMbffY!^4y~~EFyC'7 89>> IJ 779??$/DDQ3A#!$ADEVAWZ[A[E"''*;"<=ao
 &)=@S)SSJ !ffi#o%=%=c%BC"'(?)..(P"Q #%&&)c/)A)A#)F"G&+,G)..,X&Y# !5222&.2'B+J( 4!6 /@G" F
 ,-	#	./ d"'(
 b o&		#'( S '( #T)'( 2MM)$ rn% 4n%T!m$ r11'( R()v;!VW,,r   min_size
ideal_sizec                 N    U u    p4n[        XE5      nXa:  a  gXb:  a  gXa-
  X!-
  -  $ )a   
Calculate score based on face size.
Larger faces are generally better for recognition.

Args:
    face_bbox: Face bounding box (x, y, w, h)
    min_size: Minimum acceptable face size
    ideal_size: Ideal face size

Returns:
    Score between 0.0 and 1.0
              ?)rK   )r   r_   r`   _r   r   	face_sizes          r   calculate_face_size_scorerf      s=     JAqQA	I		  $)>??r   
blur_scorec                 H    XS-  :  a  gX:  a  X-
  U-  $ [        SX-  5      $ )z
Convert blur score to sharpness score (0.0 to 1.0).

Args:
    blur_score: Laplacian variance score
    threshold: Minimum acceptable threshold

Returns:
    Score between 0.0 and 1.0
   rc   rb   )rL   )rg   r	   s     r   calculate_sharpness_scorerj      s7     ]"		 &)33 3
.//r   r\   c                    SnU R                  SS5      nUS:  d  US:  a  US-  nOUS:  d  US:  a  US	-  nU R                  S
S5      nUS:  a  US-  nOUS:  a  US-  nU R                  SS5      nUS:  d  US:  a  US-  nOUS:  d  US:  a  US	-  nU R                  SS5      nUS:  a  US-  nU R                  SS5      nUS:  a  US-  nOUS:  a  US-  nXBS-   :  a  US-  nU R                  SS5      (       a  US-  nU R                  SS5      nUS:  a  US-  nOUS:  a  US-  nU R                  S S!5      S:  a  US	-  nU R                  S"S!5      S#:  a  US-  nU R                  S$S5      S%:  a  US	-  nU$ )&z
Calculate lighting quality score from lighting metrics.

Args:
    metrics: Dictionary from validate_lighting()

Returns:
    Score between 0.0 and 1.0
rc   r,      r1   r"   r8   P      333333?r-   rb   r4   g?g{Gz?gffffff?r#      Z      r&      r*   r=   r?   g      ?r/   Fr'   d      2   r(   r   r)   g?r$      )get)r\   scorer,   	env_glareface_brightnessr&   face_very_bright_pctcontrasts           r    calculate_lighting_quality_scorer~      s    E [[!137Nns2	"	 4 2C8I4	T	 kk"8#>O4	2	3!6 "++&;SAS  #;;'DcJd"		$ ",, {{<'' {{?C0H"}	B {{&*T1{{(!,t3 {{("-2Lr   lighting_metricsc                     [        U5      n[        U5      n[        U5      nSSSSS.nSnUUUUS.n	U	S   US   -  U	S   US   -  -   U	S   US   -  -   U	S   US   -  -   n
U
UUUUS	.nX4$ )
a*  
Calculate overall quality score for an image.

Args:
    image: Input image (BGR format)
    face_bbox: Face bounding box (x, y, w, h)
    blur_score: Blur score from detect_blur()
    lighting_metrics: Metrics from validate_lighting()

Returns:
    Tuple of (total_score: float, breakdown: Dict)
r8   r=   )	sharpnessre   lighting
face_anglerc   r   re   r   r   )totalr   re   r   r   )rj   rf   r~   )r   r   rg   r   r   re   r   weightsr   scorestotal_score	breakdowns               r   calculate_quality_scorer   )  s     **5I))4I/0@AH 	G J  	F 	{gk22{gk22	3zWZ00	1 	|w|44	5   I !!r   
embedding1
embedding2c                     [         R                  " X5      n[         R                  R                  U 5      n[         R                  R                  U5      nUS:X  d  US:X  a  gX#U-  -  $ )z
Calculate cosine similarity between two embeddings.

Args:
    embedding1: First embedding vector
    embedding2: Second embedding vector

Returns:
    Cosine similarity score between -1.0 and 1.0 (typically 0.0 to 1.0 for face embeddings)
r   rb   )rD   dotlinalgnorm)r   r   dot_productnorm1norm2s        r   cosine_similarityr   `  sS     &&0KIINN:&EIINN:&EzUaZ%-((r   
embeddingsc                     [        U 5      S:  a  SS/ 4$ U S   n/ nSn[        U SS SS9 H3  u  pV[        X&5      n[        XG5      nXq:  d  M"  UR	                  U5        M5     [        U5      S:H  XC4$ )a%  
Validate that all embeddings are from the same person by comparing to first embedding.

Args:
    embeddings: List of embedding vectors
    threshold: Minimum cosine similarity threshold (default: 0.6)

Returns:
    Tuple of (is_valid: bool, min_similarity: float, failed_indices: List[int])
ri   Trc   r      N)start)rP   	enumerater   rK   rQ   )r   r	   	referencefailed_indicesmin_similarityi	embedding
similaritys           r   validate_embedding_consistencyr   u  s     :S"}1INN!*QR.:&y<
^8!!!!$	 ; ~!#^CCr   c                     [         R                  " U [         R                  5      n[         R                  " [         R                  R
                  S-   5      nUR                  USS5      n[        U5      S:X  a  g[        US S9n[        U5      $ )z
Detect face in image using OpenCV Haar Cascade.

Args:
    image: Input image (BGR format)

Returns:
    Face bounding box (x, y, w, h) or None if no face detected
z#haarcascade_frontalface_default.xmlg?   r   Nc                     U S   U S   -  $ )Nri       )fs    r   <lambda>&detect_face_in_image.<locals>.<lambda>  s    AaD1Q4Kr   )key)
r   r   r   CascadeClassifierdatahaarcascadesdetectMultiScalerP   rL   tuple)r   r   face_cascadefaceslargest_faces        r   detect_face_in_imager     sv     <<s112D(()>)>Af)fgL))$Q7E
5zQ u"78Lr   )N      T@)rm   r"   )r   )ro   )__doc__r   numpyrD   typingr   r   r   r   ndarrayrH   rC   rO   r   strr^   rf   rj   r~   r   r   r   r   r   r   r   <module>r      s     . .$rzz $huS#sC=O7P.Q $ej $v{  }A  CH  }H  wI $6J-RZZ J-E#sC:L4M J-RWX\^bcf^gimXmRn J-Z@sCc/A)B @c @dg @rw @20% 0E 0U 0*Fd Fu FR4"2:: 4"%S#s@R:S 4"',4"@D4"INuVZ{I[4"n)"** )"** ) )*DtBJJ/? DE D\abfhmostwoxbx\y D6

 xc3S>P8Q/R r   