Ë
    ­¹ÙjØ  ã                   ó\   — d Z ddlZddlmZmZ dZdZdZd„ Z	d„ Z
d	„ Zd
„ Zd„ Zd„ Zd„ Zd„ Zy)up  
AI Room Designer â€” QC / recognisability scoring (Stage 2, v2).

Stage 1 scored raw edge correlation, which mis-scores high-aggression modes:
when a mode replaces furniture BY DESIGN, furniture edges vanish and the raw
score reads "room rebuilt" even when the shell is untouched.

v2 adds an ARCHITECTURAL MASK: from the BEFORE photo we extract the edges that
belong to long straight structural lines (wall/ceiling junctions, window and
door outlines, floor footprint lines) via long-run line detection, dilate that
mask, and score edge survival ONLY inside it. Furniture edges outside the mask
are allowed to change freely.

Signals:
  edge_corr        â€” legacy raw edge correlation (kept for comparison)
  layout_corr      â€” blurred luminance correlation (big layout swaps)
  arch_edge_corr   â€” edge correlation inside the architectural mask (v2 hero)
  arch_survival    â€” share of before-arch edge energy with a matching after
                     edge inside the mask

Gate (v2): PASS requires arch_edge_corr >= 0.45 AND layout_corr >= 0.80.
That gate is mode-agnostic because the mask excludes furniture by construction.
é    N)ÚImageÚImageFilteré   é)   gffffffÖ?c                 óÆ   — t        j                  | «      j                  d«      j                  t        t        f«      }t        j                  |t
        j                  ¬«      S )NÚL©Údtype)r   ÚopenÚconvertÚresizeÚSIZEÚnpÚasarrayÚfloat64©ÚpathÚimgs     ú+/var/www/room-designer/pipeline/qc_score.pyÚ_grayr       s?   € Ü
�*‰*�TÓ
×
"Ñ
" 3Ó
'×
.Ñ
.´´d¨|Ó
<€CÜ�:‰:�c¤§¡Ô,Ð,ó    c                 ó  — t        j                  | «      }t        j                  | «      }| d d …dd …f   | d d …d d…f   z
  |d d …dd…f<   | dd …d d …f   | d d…d d …f   z
  |dd…d d …f<   t        j                  ||«      S )Né   éþÿÿÿé   éÿÿÿÿ)r   Ú
zeros_likeÚhypot)ÚgrayÚgxÚgys      r   Ú_edgesr"   %   s‡   € Ü	�‰�tÓ	€BÜ	�‰�tÓ	€BØ’q˜!™"�u‘+ ¢Q¨¨¨ V¡Ñ,€B‚qˆ!ˆBˆ$€w�KØ�q‘rš1�u‘+  S b Sª! V¡Ñ,€B€qˆ€tŠQ€w�KÜ�8‰8�B˜ÓÐr   c                 ó.  — | j                  «       | j                  «       z
  } |j                  «       |j                  «       z
  }t        j                  j	                  | «      t        j                  j	                  |«      z  }|rt        | |z  |z  «      S dS )Nç        )ÚravelÚmeanr   ÚlinalgÚnormÚfloat)ÚaÚbÚdenoms      r   Ú_corrr-   -   sl   € Ø	�‰‹	�A—F‘F“HÑ€AØ	�‰‹	�A—F‘F“HÑ€AÜ�I‰I�N‰N˜1Ó¤§	¡	§¡¨qÓ 1Ñ1€EÙ#(Œ5��Q‘˜‘ÓÐ1¨cÐ1r   c                 ó  — t        j                  | «      j                  d«      j                  t        t        f«      }|j                  t        j                  d«      «      }t        j                  |t        j                  ¬«      S )Nr   é   r	   )r   r   r   r   r   Úfilterr   ÚGaussianBlurr   r   r   r   s     r   Ú_blurr2   4   sX   € Ü
�*‰*�TÓ
×
"Ñ
" 3Ó
'×
.Ñ
.´´d¨|Ó
<€CØ
�*‰*”[×-Ñ-¨bÓ1Ó
2€CÜ�:‰:�c¤§¡Ô,Ð,r   c                 óh   ‡— t        j                  |«      |z  Št        j                  ˆfd„|| «      S )Nc                 ó4   •— t        j                  | ‰d¬«      S )NÚsame)Úmode)r   Úconvolve)ÚrÚkernels    €r   ú<lambda>z_moving_avg.<locals>.<lambda><   s   ø€ ¬¯©°Q¸ÀVÔ)L€ r   )r   ÚonesÚapply_along_axis)ÚmÚwindowÚaxisr9   s      @r   Ú_moving_avgr@   :   s,   ø€ Ü�W‰W�V‹_˜vÑ%€FÜ×ÑÓLÈdÐTUÓVÐVr   c           
      óÜ  — | | j                  «       xs dz  }|dkD  j                  t        j                  «      }t	        |t
        d¬«      t        kD  }t	        |t
        d¬«      t        kD  }||z  }|j                  «       }dD ]:  }dD ]3  }|t        j                  t        j                  ||d¬«      |d¬«      z  }Œ5 Œ< dx|dd	…dd…f<   |d
d…dd…f<   dx|dd…dd	…f<   |dd…d
d…f<   |S )zHBoolean mask of structural (long straight line) edges in the BEFORE map.g      ð?ç      Ð?r   )r?   r   )éýÿÿÿr   r   r   r   r   é   FNé   éüÿÿÿ)	ÚmaxÚastyper   r   r@   ÚLINE_LENÚLINE_THRÚcopyÚroll)	Úedge_mapÚeÚbinaryÚhÚvÚmaskÚdÚdyÚdxs	            r   Úarchitectural_maskrV   ?   sö   € à�H—L‘L“NÒ) cÑ*€AØ�$‰h×ÑœrŸz™zÓ*€FÜ�FœH¨1Ô-´Ñ8€AÜ�FœH¨1Ô-´Ñ8€AØˆq‰5€Dà�	‰	‹€AØ&ò @ˆØ*ò 	@ˆBØ”—‘œŸ™  r°Ô2°B¸QÔ?Ñ?‰Añ	@ð@ð !Ð €A€b€q€bŠ!€e�Hˆq�‘’a�‰yØ Ð €A‚aˆˆ!ˆ€e�Hˆq’�B‘C�‰yØ€Hr   c           
      ó|  — t        t        | «      «      t        t        |«      «      }}t        |«      }||   ||   }}||j                  «       r|j                  «       dz  ndkD  }|j	                  «       rBt        ||   |j                  «       r|j                  «       dz  ndkD  j                  «       «      nd}t        t        ||«      d«      t        t        t        | «      t        |«      «      d«      t        t        ||«      d«      t        |d«      t        t        |j                  «       «      dz  d«      dœS )	NrB   r   g333333Ã?r$   rD   éd   r   )Ú	edge_corrÚlayout_corrÚarch_edge_corrÚarch_survivalÚarch_mask_coverage_pct)
r"   r   rV   rG   Úanyr)   r&   Úroundr-   r2   )	Úbefore_pathÚ
after_pathÚebÚearR   ÚmbÚmaÚstrongÚsurvivals	            r   Úscorerh   Q   sÿ   € Ü”E˜+Ó&Ó'¬´°jÓ0AÓ)Bˆ€BÜ˜bÓ!€DØ�‰X�r˜$‘xˆ€Bà b§f¡f¤h�2—6‘6“8˜d’?°AÑ6€FØTZ×T^ÑT^ÔT`Œu�b˜‘j°r·v±v´x B§F¡F£H¨t¢OÀQÑG×MÑMÓOÔPÐfi€Häœ5  R›=¨!Ó,ÜœU¤5¨Ó#5´u¸ZÓ7HÓIÈ1ÓMÜ¤ b¨"£¨qÓ1Ü˜x¨Ó+Ü"'¬¨d¯i©i«kÓ(:¸SÑ(@À!Ó"Dñð r   c                 óD   — | d   | d   }}|dk\  r|dk\  ry|dk\  r|dk\  ryy	)
u8   Stage 2 gate â€” architecture-first, furniture-agnostic.r[   rZ   gÍÌÌÌÌÌÜ?gš™™™™™é?u2   PASS â€” shell preserved (architectural-mask gate)g333333Ó?gffffffæ?u.   PARTIAL â€” shell mostly held, review visuallyu-   FAIL â€” shell drifted; regeneration required© )Úscoresr*   Úls      r   Úverdictrm   a   s9   € àÐ"Ñ# V¨MÑ%:€q€AØˆD‚y�Q˜$’YØCØˆD‚y�Q˜$’YØ?Ø:r   )Ú__doc__Únumpyr   ÚPILr   r   r   rI   rJ   r   r"   r-   r2   r@   rV   rh   rm   rj   r   r   ú<module>rq      sJ   ðñó. ß "à
€Ø€Ø€ò-ò
ò2ò-òWò
ò$ó ;r   