§
    o!¬j@%  ã            
       ó¤  — d Z ddlZddlmc m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                 óÆ  — d\  }}ddg}|D �]Ó}|                       |¦  «        }t          j                             |¦  «        sŒ8|                      |¬¦  «        5  t          || j        ¬¦  «        }|                      |d|› �¦  «         d}||u}|s—t          j	        d|fd	||f¦  «        d
t          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        nd
t          j        |¦  «        dœz  }	dd|	iz  }
t          t          j        |
¦  «        ¦  «        ‚dx}}|\  }}t!          ||z
  ¦  «        }t!          ||z
  ¦  «        }|                      |dd|› d|› d|› d|› d|› d�¦  «         |                      |dd|› d|› d|› d|› d|› d�¦  «         t%          |d¦  «        }|                      |d|› �¦  «         d}||u}|s—t          j	        d|fd	||f¦  «        dt          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        ndt          j        |¦  «        dœz  }	dd|	iz  }
t          t          j        |
¦  «        ¦  «        ‚dx}}|                      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©úis not©z%(py0)s is not %(py3)sÚpos©Úpy0Úpy3úassert %(py5)sÚpy5é   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 Úpos_textr   é   )r!   r   r   ÚexistsÚsubTestr   r   ÚassertIsNotNoneÚ
@pytest_arÚ_call_reprcompareÚ@py_builtinsÚlocalsÚ_should_repr_global_nameÚ	_safereprÚAssertionErrorÚ_format_explanationr:   ÚassertLessEqualr   )r    Úgt_xÚgt_yÚ
test_filesÚrel_pÚfull_prN   Ú@py_assert2Ú@py_assert1Ú@py_format4Ú@py_format6Údet_xÚdet_yÚerr_xÚerr_yrV   s                   r   Ú*test_traverse_button_ground_truth_accuracyzATestDualPassPerception.test_traverse_button_ground_truth_accuracyC   s9  € à‰
ˆˆdð FØCð
ˆ
ð
  ð 	Añ 	AˆEØ—^’^ EÑ*Ô*ˆFÝ”7—>’> &Ñ)Ô)ð Øà—’ 5�Ñ)Ô)ð Að Aå4°VÈ4ÔK]Ð^Ñ^Ô^�Ø×$Ò$ SÐ*eÐ^cÐ*eÐ*eÑfÔfÐfØ"&Ð&�s $�Ð&Ð&Ð&Õ&Ô&Ð&Ð&Ð&Ð&�s $Ð&Ñ&Ô&Ð&Õ&Ô&Ñ&Ô&Ð&Ð&Õ&Ô&�sÑ&Ô&Ð&Õ&Ô&�sÑ&Ô&Ð&Ð&Õ&Ô& $Ñ&Ô&Ð&Ð&Ñ&Ð&Ð&Ð&Ð&Ð&Ñ&Ð&Õ&Õ&Ô&Ð&Ñ&Ô&Ñ&Ô&Ð&Ð&Ð&Ð&Ð&Ø"‘��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Ø'+Ð+�x tÐ+Ð+Ð+Ð+Õ+Ô+Ð+Ð+Ð+Ð+�x tÐ+Ñ+Ô+Ð+Õ+Ô+Ñ+Ô+Ð+Ð+Õ+Ô+�xÑ+Ô+Ð+Õ+Ô+�xÑ+Ô+Ð+Ð+Õ+Ô+ tÑ+Ô+Ð+Ð+Ñ+Ð+Ð+Ð+Ð+Ð+Ñ+Ð+Õ+Õ+Ô+Ð+Ñ+Ô+Ñ+Ô+Ð+Ð+Ð+Ð+Ð+Ø×$Ò$¥S¨°!¬°tÑ);Ñ%<Ô%<¸aÑ@Ô@Ð@Ø×$Ò$¥S¨°!¬°tÑ);Ñ%<Ô%<¸aÑ@Ô@Ð@ð+Að Að Añ Aô Að Að Að Að Að Að Aøøøð Að Að Að Aùð	Að 	As   ÁI.KËK	ËK	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   rX   rY   r   r   ÚassertIsNone)r    Úneg_capturesrg   rh   rN   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)rs   rt   ru   rv   rw   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   rX   rY   Ú
assertTruer   ÚassertFalse)r    Úpos_ui_capturesrg   rh   Ú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                 ó²  — |                       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        ¦  «        ¦  «        \  }}|                      |¦  «         d}||u}	|	s—t+          j        d|	fd||f¦  «        dt/          j        ¦   «         v st+          j        |¦  «        rt+          j        |¦  «        ndt+          j        |¦  «        dœz  }
dd|
iz  }t7          t+          j        |¦  «        ¦  «        ‚dx}	}|                      |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@éÿ   rW   g      N@é   NrK   rM   ÚcoordsrO   rR   rS   gš™™™™™á?u   Ä�iá»ƒm tÆ°Æ¡ng quan u"    khÃ´ng Ä‘áº¡t ngÆ°á»¡ng sau bloomrD   rT   rE   ) r!   r   r   rX   ÚskipTestr   ÚopenÚconvertr4   ÚarrayÚfloat32ÚclipÚrandomÚnormalr8   Ú	fromarrayÚastyper6   r	   r   rZ   r[   r\   r]   r^   r_   r`   ra   rb   r;   rc   r:   )r    Ú	base_pathÚimÚarrÚnoiseÚbloomed_imgr‡   Úscoreri   rj   rk   rl   s               r   Ú(test_resilience_to_simulated_amber_bloomz?TestDualPassPerception.test_resilience_to_simulated_amber_bloom¦   sï  € à—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Ñ$Ô$Ð$Ø!Ð!ˆv˜TÐ!Ð!Ð!Ð!Õ!Ô!Ð!Ð!Ð!Ð!ˆv˜TÐ!Ñ!Ô!Ð!Õ!Ô!Ñ!Ô!Ð!Ð!Õ!Ô!ˆvÑ!Ô!Ð!Õ!Ô!ˆvÑ!Ô!Ð!Ð!Õ!Ô!˜TÑ!Ô!Ð!Ð!Ñ!Ð!Ð!Ð!Ð!Ð!Ñ!Ð!Õ!Õ!Ô!Ð!Ñ!Ô!Ñ!Ô!Ð!Ð!Ð!Ð!Ð!Ø×Ò  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   rq   r{   r‚   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œ   Úbuiltinsr]   Ú_pytest.assertion.rewriteÚ	assertionÚrewriter[   Ú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¯      sv  ððð ð € € € € € € € € € € € € €€€€Ø 	€	€	€	Ø 
€
€
€
Ø €€€Ø Ð Ð Ð Ø Ð Ð Ð Ð Ð à „‡‚��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   