§
    o!¬j@%  ã            
       óŠ  — d Z ddlZddlZddlZddlZddlZddlmZ ej	         
                    dej	                             ej	                             ej	                             e¦  «        d¦  «        ¦  «        ¦  «         ddlmZmZmZmZmZmZ ddlmZmZ  G d„ dej        ¦  «        Zed	k    r ej        ¦   «          dS dS )
už  Bá»™ kiá»ƒm thá»­ Ä‘Æ¡n vá»‹ cho Dual-Pass CLAHE & Robust Perception (Doc 48/56/61).

XÃ¡c minh:
1. Thuáº­t toÃ¡n CLAHE vÃ  Sobel Edge thuáº§n NumPy tÄƒng cÆ°á»�ng tÆ°Æ¡ng pháº£n vÃ  triá»‡t tiÃªu bloom Ã¡nh sÃ¡ng.
2. Nháº­n diá»‡n nÃºt TRAVERSE Ä‘áº¡t Ä‘á»™ chÃ­nh xÃ¡c 100% vá»›i sai sá»‘ <= 3 pixel so vá»›i ground truth (1091, 747).
3. KhÃ¡ng 100% false-positives trÃªn cÃ¡c áº£nh chá»¥p sÃ n 3D Hideout khi chÆ°a má»Ÿ giao diá»‡n Atlas.
4. XÃ¡c minh tráº¡ng thÃ¡i má»Ÿ cá»§a giao diá»‡n Map Device (is_atlas_ui_open_robust) trÃªn toÃ n bá»™ capture thá»±c táº¿.
5. Kiá»ƒm chá»©ng kháº£ nÄƒng khÃ¡ng nhiá»…u Ã¡nh sÃ¡ng vÃ ng/cam giáº£ láº­p (Simulated Amber Bloom).
é    N)ÚImageú..)Úapply_clahe_fastÚdual_pass_enhance_imageÚfind_traverse_button_dual_passÚis_atlas_ui_open_robustÚmatch_traverse_template_edgeÚsobel_edge_magnitude)Úis_atlas_ui_openÚfind_button_by_textc                   óV   — e Zd ZdZed„ ¦   «         Zdedefd„Zd„ Zd„ Z	d„ Z
d	„ Zd
„ ZdS )ÚTestDualPassPerceptionuT   Kiá»ƒm thá»­ táº§ng thá»‹ giÃ¡c mÃ¡y tÃ­nh Dual-Pass CLAHE & Edge Template Matching.c                 ó$  — t           j                             t           j                             t           j                             t
          ¦  «        d¦  «        ¦  «        | _        t           j                             | j        dd¦  «        | _        d S )Nr   Úcapturesztraverse_button_crop.png)ÚosÚpathÚabspathÚjoinÚdirnameÚ__file__Ú	repo_rootÚtemplate_path)Úclss    ú7C:\Projects\AutoPOE2\tests\test_dual_pass_perception.pyÚ
setUpClassz!TestDualPassPerception.setUpClass"   sY   € åœŸš­¬¯ªµR´W·_²_ÅXÑ5NÔ5NÐPTÑ(UÔ(UÑVÔVˆŒÝœGŸLšL¨¬¸
ÐD^Ñ_Ô_ˆÔÐÐó    Úrel_pathÚreturnc                 óL   — t           j                             | j        |¦  «        S )N)r   r   r   r   )Úselfr   s     r   Ú	_get_pathz TestDualPassPerception._get_path'   s   € ÝŒw�|Š|˜DœN¨HÑ5Ô5Ð5r   c                 óÄ  — t          j        dt           j        ¬¦  «        }d|dd…dd…f<   d|dd…dd…f<   d|dd	…d
d…f<   t          |dd¬¦  «        }|                      |j        d¦  «         |                      |j        t           j        ¦  «         t          |d         ¦  «        t          |d         ¦  «        z
  }t          t          |d         ¦  «        t          |d         ¦  «        z
  ¦  «        }|  	                    ||¦  «         t          |¦  «        }|                      |j        d¦  «         |                      t          |d         ¦  «        d¦  «         dS )uf   1. Kiá»ƒm chá»©ng tÃ­nh toÃ¡n lÃ½ cá»§a CLAHE vÃ  Sobel gradient trÃªn ma tráº­n sá»‘ thá»±c nghiá»‡m.)éd   éÈ   ©Údtypeé   Nr#   éð   r$   é(   é<   éŒ   é    )é   r-   g       @)Ú	grid_sizeÚ
clip_limit)é2   éx   )r0   é–   )r0   éc   )ÚnpÚzerosÚuint8r   ÚassertEqualÚshaper&   ÚintÚabsÚassertGreaterEqualr
   ÚassertGreater)r    ÚsynthÚenhancedÚcontrast_beforeÚcontrast_afterÚedgess         r   Ú test_clahe_and_edge_filters_mathz7TestDualPassPerception.test_clahe_and_edge_filters_math*   sW  € õ ”˜­2¬8Ð4Ñ4Ô4ˆØˆˆaˆaˆa��#�ˆg‰Øˆˆaˆaˆa���ˆg‰à #ˆˆb�ˆe�S˜�WˆnÑõ $ E°VÈÐLÑLÔLˆØ×Ò˜œ¨Ñ4Ô4Ð4Ø×Ò˜œ­¬Ñ2Ô2Ð2õ ˜e GœnÑ-Ô-µ°E¸'´NÑ0CÔ0CÑCˆÝ�S ¨'Ô!2Ñ3Ô3µc¸(À7Ô:KÑ6LÔ6LÑLÑMÔMˆØ×Ò °Ñ@Ô@Ð@õ % XÑ.Ô.ˆØ×Ò˜œ jÑ1Ô1Ð1à×Ò�3˜u Vœ}Ñ-Ô-¨sÑ3Ô3Ð3Ð3Ð3r   c                 óJ  — d\  }}ddg}|D �]•}|                       |¦  «        }t          j                             |¦  «        sŒ8|                      |¬¦  «        5  t          || j        ¬¦  «        }|                      |d|› �¦  «         |€J ‚|\  }}t          ||z
  ¦  «        }	t          ||z
  ¦  «        }
|  	                    |	dd	|	› d
|› d|› d|› d|› d�¦  «         |  	                    |
dd|
› d
|› d|› d|› d|› d�¦  «         t          |d¦  «        }|                      |d|› �¦  «         |€J ‚|  	                    t          |d         |z
  ¦  «        d¦  «         |  	                    t          |d         |z
  ¦  «        d¦  «         ddd¦  «         n# 1 swxY w Y   �Œ—dS )uu   2. XÃ¡c minh nÃºt TRAVERSE Ä‘áº¡t Ä‘á»™ chÃ­nh xÃ¡c 100% vá»›i sai sá»‘ <= 3 pixel so vá»›i ground truth (1091, 747).)éC  éë  ú7captures/20260913_102100_639_AFTER_CLICK_ATLAS_NODE.pngú5captures/20260913_102457_287_AFTER_CLICK_TRAVERSE.png©Úfile©r   u1   KhÃ´ng phÃ¡t hiá»‡n Ä‘Æ°á»£c nÃºt TRAVERSE trong Né   u   Sai sá»‘ trá»¥c X u$   px vÆ°á»£t quÃ¡ ngÆ°á»¡ng 3px táº¡i z (detected: z, GT: (z, z))u   Sai sá»‘ trá»¥c Y ÚTRAVERSEu'   find_button_by_text tháº¥t báº¡i táº¡i r   é   )r!   r   r   ÚexistsÚsubTestr   r   ÚassertIsNotNoner:   ÚassertLessEqualr   )r    Úgt_xÚgt_yÚ
test_filesÚrel_pÚfull_pÚposÚdet_xÚdet_yÚerr_xÚerr_yÚpos_texts               r   Ú*test_traverse_button_ground_truth_accuracyzATestDualPassPerception.test_traverse_button_ground_truth_accuracyC   sË  € à‰
ˆˆdð FØCð
ˆ
ð
  ð 	Añ 	AˆEØ—^’^ EÑ*Ô*ˆFÝ”7—>’> &Ñ)Ô)ð Øà—’ 5�Ñ)Ô)ð Að Aå4°VÈ4ÔK]Ð^Ñ^Ô^�Ø×$Ò$ SÐ*eÐ^cÐ*eÐ*eÑfÔfÐfØ���Ø"‘��uÝ˜E D™LÑ)Ô)�Ý˜E D™LÑ)Ô)�à×$Ò$Ø˜1ð  N°5ð  Nð  NÐ^cð  Nð  NÐqtð  Nð  Nð  ~Bð  Nð  Nð  FJð  Nð  Nð  Nñô ð ð ×$Ò$Ø˜1ð  N°5ð  Nð  NÐ^cð  Nð  NÐqtð  Nð  Nð  ~Bð  Nð  Nð  FJð  Nð  Nð  Nñô ð õ
 /¨v°zÑBÔB�Ø×$Ò$ XÐ/`ÐY^Ð/`Ð/`ÑaÔaÐaØÐ+Ð+Ð+Ø×$Ò$¥S¨°!¬°tÑ);Ñ%<Ô%<¸aÑ@Ô@Ð@Ø×$Ò$¥S¨°!¬°tÑ);Ñ%<Ô%<¸aÑ@Ô@Ð@ð+Að Að Añ Aô Að Að Að Að Að Að Aøøøð Að Að Að Aùð	Að 	As   ÁD0FÆF	ÆF	c           
      óD  — g d¢}|D ]˜}|                       |¦  «        }t          j                             |¦  «        sŒ7|                      |¬¦  «        5  t          || j        ¬¦  «        }|                      |d|› d|› d�¦  «         ddd¦  «         n# 1 swxY w Y   Œ™dS )uh   3. KhÃ¡ng 100% false-positives trÃªn cÃ¡c áº£nh chá»¥p sÃ n Hideout 3D khi chÆ°a má»Ÿ giao diá»‡n Atlas.)úcaptures/current_map_device.pngú#captures/after_click_map_device.pngz%captures/hideout_map_device_check.pngúFcaptures/pipeline_run/20260914_213227_453_STAGE2_MAP_DEVICE_OPENED.pngúBcaptures/pipeline_run/20260914_213230_352_STAGE3_NODE_SELECTED.pngú?captures/pipeline_run/20260914_213232_001_STAGE3_NODE_READY.pngz"captures/crop_failure_traverse.pngrH   rJ   u]   Bá»‹ False-Positive! NÃºt TRAVERSE khÃ´ng Ä‘Æ°á»£c phÃ©p xuáº¥t hiá»‡n trong áº£nh Ã¢m tÃ­nh u    (nháº­n diá»‡n: ú)N)r!   r   r   rN   rO   r   r   ÚassertIsNone)r    Úneg_capturesrU   rV   rW   s        r   Ú>test_traverse_button_zero_false_positives_on_negative_captureszUTestDualPassPerception.test_traverse_button_zero_false_positives_on_negative_capturesh   s   € ð
ð 
ð 
ˆð "ð 
	ð 
	ˆEØ—^’^ EÑ*Ô*ˆFÝ”7—>’> &Ñ)Ô)ð Øà—’ 5�Ñ)Ô)ð ð Ý4°VÈ4ÔK]Ð^Ñ^Ô^�Ø×!Ò!Øð SÐtyð  Sð  Sð  MPð  Sð  Sð  Sñô ð ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð øð
	ð 
	s   Á4BÂB	ÂB	c                 óR  — g d¢}|D ]Œ}|                       |¦  «        }t          j                             |¦  «        sŒ7|                      |d¬¦  «        5  |                      t          |¦  «        d|› �¦  «         ddd¦  «         n# 1 swxY w Y   Œ�g d¢}|D ]Œ}|                       |¦  «        }t          j                             |¦  «        sŒ7|                      |d¬¦  «        5  |                      t          |¦  «        d|› �¦  «         ddd¦  «         n# 1 swxY w Y   Œ�dS )	uo   4. XÃ¡c minh tráº¡ng thÃ¡i má»Ÿ giao diá»‡n Atlas / Map Device (is_atlas_ui_open_robust) trÃªn artifact tháº­t.)zFcaptures/pipeline_run/20260913_215721_622_STAGE2_MAP_DEVICE_OPENED.pngzFcaptures/pipeline_run/20260913_220052_769_STAGE2_MAP_DEVICE_OPENED.pngzFcaptures/pipeline_run/20260914_004936_950_STAGE2_MAP_DEVICE_OPENED.pngrF   rG   T)rI   ÚexpecteduS   Giao diá»‡n Atlas thá»±c sá»± má»Ÿ nhÆ°ng is_atlas_ui_open_robust bÃ¡o False táº¡i N)r_   r`   ra   rb   rc   Fu^   Giao diá»‡n Atlas chÆ°a má»Ÿ (sÃ n 3D Hideout) nhÆ°ng is_atlas_ui_open_robust bÃ¡o True táº¡i )r!   r   r   rN   rO   Ú
assertTruer   ÚassertFalse)r    Úpos_ui_capturesrU   rV   Úneg_ui_capturess        r   Ú0test_atlas_ui_open_verification_on_real_captureszGTestDualPassPerception.test_atlas_ui_open_verification_on_real_captures€   sØ  € ð
ð 
ð 
ˆð %ð 	ð 	ˆEØ—^’^ EÑ*Ô*ˆFÝ”7—>’> &Ñ)Ô)ð ØØ—’ 5°4�Ñ8Ô8ð ð Ø—’Ý+¨FÑ3Ô3ØqÐjoÐqÐqñô ð ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð øð
ð 
ð 
ˆð %ð 	ð 	ˆEØ—^’^ EÑ*Ô*ˆFÝ”7—>’> &Ñ)Ô)ð ØØ—’ 5°5�Ñ9Ô9ð ð Ø× Ò Ý+¨FÑ3Ô3Ø|ÐuzÐ|Ð|ñô ð ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð øð		ð 	s$   Á'BÂB	ÂB	Ã('DÄD	Ä"D	c                 ót  — |                       d¦  «        }t          j                             |¦  «        s|                      d¦  «         t          j        |¦  «                             d¦  «        }t          j	        |t          j
        ¬¦  «        }t          j        |dd…dd…d	f         d
z   d	d¦  «        |dd…dd…d	f<   t          j        |dd…dd…df         dz   d	d¦  «        |dd…dd…df<   t          j                             d	d|dd…dd…f         j        ¦  «        }t          j        |dd…dd…f         |z   d	d¦  «        |dd…dd…f<   t          j        |                     t          j        ¦  «        ¦  «        }t%          |t          j        | j        ¦  «        ¦  «        \  }}|                      |¦  «         |€J ‚|                      |dd|› d�¦  «         |                      t/          |d	         dz
  ¦  «        d¦  «         |                      t/          |d         dz
  ¦  «        d¦  «         dS )uf   5. Kiá»ƒm chá»©ng kháº£ nÄƒng khÃ¡ng nhiá»…u Ã¡nh sÃ¡ng vÃ ng/cam giáº£ láº­p (Amber Bloom & Flicker).rF   u#   Thiáº¿u capture 20260913_102100_639ÚRGBr%   iÐ  i  iè  i°  r   g      T@éÿ   rM   g      N@é   Ngš™™™™™á?u   Ä�iá»ƒm tÆ°Æ¡ng quan u"    khÃ´ng Ä‘áº¡t ngÆ°á»¡ng sau bloomrD   rK   rE   )r!   r   r   rN   ÚskipTestr   ÚopenÚconvertr4   ÚarrayÚfloat32ÚclipÚrandomÚnormalr8   Ú	fromarrayÚastyper6   r	   r   rP   r;   rQ   r:   )r    Ú	base_pathÚimÚarrÚnoiseÚbloomed_imgÚcoordsÚscores           r   Ú(test_resilience_to_simulated_amber_bloomz?TestDualPassPerception.test_resilience_to_simulated_amber_bloom¦   s9  € à—N’NÐ#\Ñ]Ô]ˆ	ÝŒw�~Š~˜iÑ(Ô(ð 	AØ�MŠMÐ?Ñ@Ô@Ð@åŒZ˜	Ñ"Ô"×*Ò*¨5Ñ1Ô1ˆÝŒh�r¥¤Ð,Ñ,Ô,ˆõ &(¤W¨S°°S°¸$¸t¸)ÀQÐ1FÔ-GÈ$Ñ-NÐPQÐSVÑ%WÔ%WˆˆC�ˆG�T˜$�Y Ð!Ñ"Ý%'¤W¨S°°S°¸$¸t¸)ÀQÐ1FÔ-GÈ$Ñ-NÐPQÐSVÑ%WÔ%WˆˆC�ˆG�T˜$�Y Ð!Ñ"õ ”	× Ò   B¨¨C°¨G°T¸$°YÐ,>Ô(?Ô(EÑFÔFˆÝ"$¤'¨#¨c°#¨g°t¸D°yÐ.@Ô*AÀEÑ*IÈ1ÈcÑ"RÔ"RˆˆC�ˆG�T˜$�YÐÑå”o c§j¢jµ´Ñ&:Ô&:Ñ;Ô;ˆõ 5°[Å%Ä*ÈTÔM_ÑB`ÔB`ÑaÔa‰ˆ�Ø×Ò˜VÑ$Ô$Ð$ØÐ!Ð!Ð!Ø×Ò  tÐ-nÀUÐ-nÐ-nÐ-nÑoÔoÐoØ×Ò�S ¨¤¨TÑ!1Ñ2Ô2°AÑ6Ô6Ð6Ø×Ò�S ¨¤¨S¡Ñ1Ô1°1Ñ5Ô5Ð5Ð5Ð5r   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Úclassmethodr   Ústrr!   rB   r]   rg   rn   r„   © r   r   r   r      s¨   € € € € € Ø^Ð^àð`ð `ñ „[ð`ð6 #ð 6¨#ð 6ð 6ð 6ð 6ð4ð 4ð 4ð2#Að #Að #AðJð ð ð0$ð $ð $ðL6ð 6ð 6ð 6ð 6r   r   Ú__main__)rˆ   Úmathr   ÚsysÚunittestÚnumpyr4   ÚPILr   r   Úinsertr   r   r   r   Úsrc.common.vision_filtersr   r   r   r   r	   r
   Úsrc.common.vision_ocrr   r   ÚTestCaser   r…   Úmainr‹   r   r   ú<module>r—      s\  ððð ð €€€Ø 	€	€	€	Ø 
€
€
€
Ø €€€Ø Ð Ð Ð Ø Ð Ð Ð Ð Ð à „‡‚��2”7—?’? 2¤7§<¢<°´·²ÀÑ0IÔ0IÈ4Ñ#PÔ#PÑQÔQÑ RÔ RÐ Rðð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð HÐ GÐ GÐ GÐ GÐ GÐ GÐ Gða6ð a6ð a6ð a6ð a6˜XÔ.ñ a6ô a6ð a6ðH ˆzÒÐØ€H„M�O„O€O€O€Oð Ðr   