§
    �Wêj–  ã                  ó	  — U d Z ddlmZ ddlmZ ddlmZ ddlZddl	Z
ddlmZmZ ddlmZ dgd„Z	 dhdid„Zdjd„Zdkd#„Zdld(„Z G d)„ d*¦  «        Zed+k    �r5ddlZddlZddlZ ej        d,¬-¦  «        Ze                     d.d/¬0¦  «         e                     d1d2¬0¦  «         e                     d3ed4d5¬6¦  «         e                     d7ed8d9¬6¦  «         e                     d:edd;¬6¦  «         e                     d<ed=d>¬6¦  «         e                     d?ed@dA¬6¦  «         e                     dBdCg dD¢dE¬F¦  «         e                     dGedHdI¬6¦  «         e                     dJddK¬L¦  «         e                     ¦   «         Z  ee j!        e j"        e j#        e j$        e j%        e j&        ¬M¦  «        Z' ee j(        ¦  «        Z(e j)        r ee j)        ¦  «        ndZ)e)�e) *                    dNdN¬O¦  «         g Z+dPe,dQ<   e j-        D ]|Z.e+ /                     e0e( 1                    dRe.› �¦  «        ¦  «        ¦  «         e+ /                     e0e( 1                    dRe. 2                    ¦   «         › �¦  «        ¦  «        ¦  «         Œ} e0 e3e+¦  «        ¦  «        Z+e+s e4dSe(› �¦  «         n!e)rdTndUZ5 e4dV e6e+¦  «        › dWe5› dX�¦  «         e+D �]ÉZ7 ej8         e9e7¦  «        ¦  «        Z:e:€ e4dYe7j;        › �¦  «         Œ2e7 <                    dZ¦  «        Z=e= >                    ¦   «         rD e?e=d[¦  «        5 Z@ ejA        e@¦  «        ZBddd¦  «         n# 1 swxY w Y   d\ e6eB¦  «        › d]�ZCndZBd^ZCe' D                    e:eB¦  «        ZEeB€*eEjF        �# e6e' G                    eEjF        ¦  «        ¦  «        neB� e6eB¦  «        ndZH e4e7j;        › d_eC› d`eH› da e6eEjI        ¦  «        › db e6eEjJ        ¦  «        › �	¦  «         e' K                    e:eEeBe jL        ¬c¦  «        ZMe)�>e)e7jN        › dde7jO        › �z  ZP ejQ         e9eP¦  «        eM¦  «          e4deeP› �¦  «         �ŒŒdfe7j;        › �ZR ejS        eReM¦  «          ejT        d¦  «          ejU        eR¦  «         �ŒÉdS dS )ma˜  
TableGridExtractorV1B.py

Hybrid table grid extractor combining:
  - Rule-based candidate grid lines from bbox geometry (same as V1A).
  - V1-style heatmap threshold + 1D CCL to define active intervals.
  - A candidate line survives if its position falls inside any active
    interval; its confidence score is then 1.0. Lines outside every
    active interval receive score 0.0 and are discarded.

Design philosophy
-----------------
V1  : heatmap CCL determines position directly (coarse but fast).
V1A : bbox geometry determines position; heatmap value at the position
      acts as a soft confidence filter.
V1B : bbox geometry determines position (precise); heatmap CCL defines
      which regions are "active" at all (coarse region gate). A candidate
      that lands inside an active CCL interval is accepted unconditionally
      (score = 1.0). This separates localisation (rule-based) from
      region-level detection (heatmap CCL).

bbox source priority
--------------------
- Caller-supplied bboxes : used as-is.
- bboxes=None            : extracted automatically from the db_prob map
                           produced by the same inference pass (same as V1A).
é    )Úannotations)ÚPath)ÚOptionalNé   )ÚGridPredictionÚCellInfo)Úmake_sessionÚcandidate_boundariesÚsetÚall_cell_bboxesÚlistÚis_horizontal_coordÚboolÚmin_empty_gap_sizeÚfloatÚreturnc           	     óX  — | sg S t          t          | ¦  «        ¦  «        }t          ¦   «         }t          t	          |¦  «        dz
  ¦  «        D �]@}||         }||dz            }||z
  }	|	dk     rŒ"d}
|D ]â}|\  }}}}|rlt          ||z
  ¦  «        |k    pAt          ||z
  ¦  «        |k    p+t          ||z
  ¦  «        |k    pt          ||z
  ¦  «        |k    }|sŒf||k    r
||k     rd}
 nmŒwt          ||z
  ¦  «        |k    pAt          ||z
  ¦  «        |k    p+t          ||z
  ¦  «        |k    pt          ||z
  ¦  «        |k    }|sŒÒ||k    r
||k     rd}
 nŒã|
r5|                     t          t          ||z   dz  ¦  «        ¦  «        ¦  «         �ŒBt          t          |¦  «        ¦  «        S )z•
    Derive grid lines from candidate boundary coordinates by detecting
    empty strips between cell bboxes (V3 algorithm, unchanged from V1A).
    r   r   TFé   )	Úsortedr   r   ÚrangeÚlenÚabsÚaddÚintÚround)r
   r   r   r   Úsorted_boundariesÚfinal_linesÚiÚcoord1Úcoord2Úgap_sizeÚis_empty_stripÚbboxÚbx1Úby1Úbx2Úby2Úsame_rowÚsame_cols                     ú›/Users/tedpeters/Documents/Projects/Claude Projects/TPC Houses/house-viewer/.venv/lib/python3.11/site-packages/pymupdf/layout/onnx/TableGridExtractorV1B.pyÚ_find_grid_lines_by_empty_spacer+   -   s  € ð  ð Øˆ	å�tÐ$8Ñ9Ô9Ñ:Ô:ÐÝ‘%”%€Kå•3Ð(Ñ)Ô)¨AÑ-Ñ.Ô.ð %?ñ %?ˆØ" 1Ô%ˆØ" 1 q¡5Ô)ˆØ˜F‘?ˆà�aŠ<ˆ<ØàˆØ#ð 	ð 	ˆDØ!%ÑˆC��c˜3Ø"ð å˜˜f™Ñ%Ô%Ð);Ò;ð <Ý˜˜f™Ñ%Ô%Ð);Ò;ð<å˜˜f™Ñ%Ô%Ð);Ò;ð<õ ˜˜f™Ñ%Ô%Ð);Ò;ð	 ð  ð ØØ˜’<�< C¨&¢L LØ%*�NØ�Eøõ ˜˜f™Ñ%Ô%Ð);Ò;ð <Ý˜˜f™Ñ%Ô%Ð);Ò;ð<å˜˜f™Ñ%Ô%Ð);Ò;ð<õ ˜˜f™Ñ%Ô%Ð);Ò;ð	 ð  ð ØØ˜’<�< C¨&¢L LØ%*�NØ�Eøàð 	?Ø�OŠO�C¥ v°¡¸!Ñ&;Ñ <Ô <Ñ=Ô=Ñ>Ô>Ð>ùå•$�{Ñ#Ô#Ñ$Ô$Ð$ó    ç      @ÚbboxesÚorig_hr   Úorig_wÚgrid_margin_pxÚtuplec                óh  — t          ¦   «         }t          ¦   «         }g }| D �]f}|\  }}	}
}t          t          |¦  «        ¦  «        t          t          |	¦  «        ¦  «        }}t          t          |
¦  «        ¦  «        t          t          |¦  «        ¦  «        }}t          d|¦  «        t          d|¦  «        }}t	          ||¦  «        t	          ||¦  «        }}||k    s||k    rŒÇ||z
  }||z
  }|dk    rdnd}|dk    rdnd}||z   }||z   }||z
  }||z
  }|                     ||||g¦  «         |                     |¦  «         |                     |¦  «         |                     |¦  «         |                     |¦  «         �Œht          ||d|¬¦  «        }t          ||d|¬¦  «        }|||fS )z§
    Derive candidate h/v grid lines from cell bboxes (unchanged from V1A).

    Returns
    -------
    (candidate_h_lines, candidate_v_lines, cells_bbox_shrunk)
    r   é   r   T)r   r   F)r   r   r   ÚmaxÚminÚappendr   r+   )r.   r/   r0   r1   Úall_h_boundariesÚall_v_boundariesÚcells_bbox_shrunkr#   Úx1_fÚy1_fÚx2_fÚy2_fÚx1Úy1Úx2Úy2ÚwÚhÚx_shrinkÚy_shrinkÚsx1Úsy1Úsx2Úsy2Úh_linesÚv_liness                             r*   Úextract_candidate_gridrM   g   så  € õ  ™EœEÐÝ™EœEÐØÐàð "ñ "ˆØ!%Ñˆˆd�D˜$å•U˜4‘[”[Ñ!Ô!¥3¥u¨T¡{¤{Ñ#3Ô#3ˆBˆÝ•U˜4‘[”[Ñ!Ô!¥3¥u¨T¡{¤{Ñ#3Ô#3ˆBˆÝ�Q˜‘”�S  B™ZœZˆBˆÝ�V˜R‘”¥# f¨b¡/¤/ˆBˆà�Š8ˆ8�r˜R’x�xØà�‰GˆØ�‰GˆØ˜Qš˜�1�1 AˆØ˜Qš˜�1�1 AˆØ�8‰mˆØ�8‰mˆØ�8‰mˆØ�8‰mˆØ× Ò  # s¨C°Ð!5Ñ6Ô6Ð6à×Ò˜SÑ!Ô!Ð!Ø×Ò˜SÑ!Ô!Ð!Ø×Ò˜SÑ!Ô!Ð!Ø×Ò˜SÑ!Ô!Ð!Ñ!å-ØÐ+Ø Ø)ðñ ô €Gõ
 .ØÐ+Ø!Ø)ðñ ô €Gð �GÐ.Ð.Ð.r,   Úheatmapú
np.ndarrayÚ	thresholdúlist[tuple[int, int]]c                óì   — | |k    }g }d}d}t          |¦  «        D ].\  }}|r|sd}|}Œ|s|r|                     ||dz
  f¦  «         d}Œ/|r'|                     |t          | ¦  «        dz
  f¦  «         |S )a„  
    Apply threshold to a 1D heatmap and return the (start, end) pixel
    intervals of every connected active component.

    Parameters
    ----------
    heatmap   : 1D float32 array (already resized to image pixel space)
    threshold : minimum activation value

    Returns
    -------
    List of (start_px, end_px) tuples, inclusive on both ends, sorted by
    start position.
    Fr   Tr   )Ú	enumerater7   r   )rN   rP   ÚactiveÚ	intervalsÚin_groupÚgroup_startr   Ú	is_actives           r*   Ú_ccl_1d_active_intervalsrY   ¤   s·   € ð$ ˜	Ò!€FØ')€IØ€HØ€Kå! &Ñ)Ô)ð ð ‰ˆˆ9Øð 	˜Xð 	ØˆHØˆKˆKØð 	˜xð 	Ø×Ò˜k¨1¨q©5Ð1Ñ2Ô2Ð2ØˆHøàð :Ø×Ò˜+¥s¨7¡|¤|°aÑ'7Ð8Ñ9Ô9Ð9àÐr,   Úpositions_pxrU   útuple[np.ndarray, np.ndarray]c                ó–  — t          j        t          | ¦  «        t           j        ¬¦  «        }t          j        t          | ¦  «        t           j        ¬¦  «        }t          |¦  «        }t	          | ¦  «        D ]M\  }}|t          t          |¦  «        |dz
  ¦  «                 ||<   |D ]\  }}	||cxk    r|	k    r
n Œd||<    nŒŒN||fS )ak  
    Assign score 1.0 to each candidate position that falls inside at least
    one CCL active interval; assign 0.0 otherwise.
    Also return the heatmap value at each candidate position for top_k ranking.

    Parameters
    ----------
    positions_px : list of integer candidate positions in pixel space
    intervals    : list of (start, end) active intervals from CCL
    heatmap      : 1D float32 heatmap array in pixel space

    Returns
    -------
    gate_scores  : np.ndarray of float32, 1.0 if inside interval else 0.0
    heat_scores  : np.ndarray of float32, heatmap value at each candidate position
    ©Údtyper   ç      ð?)ÚnpÚzerosr   Úfloat32rS   r6   r   )
rZ   rU   rN   Úgate_scoresÚheat_scoresÚnr   ÚposÚstartÚends
             r*   Ú"_score_candidates_by_ccl_intervalsri   É   sÞ   € õ* ”(�3˜|Ñ,Ô,µB´JÐ?Ñ?Ô?€KÝ”(�3˜|Ñ,Ô,µB´JÐ?Ñ?Ô?€KÝˆG‰Œ€AÝ˜LÑ)Ô)ð ð ‰ˆˆ3Ø ¥¥S¨¡X¤X¨q°1©uÑ!5Ô!5Ô6ˆ�A‰Ø#ð 	ð 	‰JˆE�3Ø˜Ð"Ð"Ò"Ð"˜sÒ"Ð"Ð"Ð"Ð"Ø!$�˜A‘Ø�ð #øð ˜Ð#Ð#r,   ÚlinesÚheat_mapÚdictÚtop_kc                óä   ‡‡‡	— t          ¦   «         }|D ]N\  Š	Šˆˆ	fd„| D ¦   «         }|sŒt          |ˆfd„d¬¦  «        }|d|…         D ]}|                     |¦  «         ŒŒOt          |¦  «        S )a‘  
    Within each CCL active interval, retain at most top_k candidates ranked
    by their heatmap value (highest first). Candidates not covered by any
    interval are passed through unchanged (they have already been gate-filtered
    before this call, so in practice none should remain).

    Parameters
    ----------
    lines     : list of candidate positions that passed the CCL gate
    intervals : list of (start, end) active intervals
    heat_map  : dict mapping position -> heatmap value for each line
    top_k     : maximum number of candidates to keep per interval

    Returns
    -------
    Sorted list of surviving candidate positions.
    c                ó4   •— g | ]}‰|cxk    r‰k    ¯n n|‘ŒS © rp   )Ú.0Úyrh   rg   s     €€r*   ú
<listcomp>z-_apply_top_k_per_interval.<locals>.<listcomp>  s:   ø€ Ð9Ð9Ð9˜ u°Ð'8Ð'8Ò'8Ð'8°SÒ'8Ð'8Ð'8Ð'8Ð'8�1Ð'8Ð'8Ð'8r,   c                ó0   •— ‰                      | d¦  «        S )Nç        )Úget)rr   rk   s    €r*   ú<lambda>z+_apply_top_k_per_interval.<locals>.<lambda>  s   ø€ °x·|²|ÀAÀsÑ7KÔ7K€ r,   T)ÚkeyÚreverseN)r   r   r   )
rj   rU   rk   rm   ÚkeptÚmembersÚmembers_sortedrr   rh   rg   s
     `     @@r*   Ú_apply_top_k_per_intervalr}   ê   s£   øøø€ õ. ‘”€DØð ð ‰
ˆˆsØ9Ð9Ð9Ð9Ð9˜eÐ9Ñ9Ô9ˆØð 	ØÝ Ð-KÐ-KÐ-KÐ-KÐUYÐZÑZÔZˆØ   Ô'ð 	ð 	ˆAØ�HŠH�Q‰KŒKˆKˆKð	å�$‰<Œ<Ðr,   c                  ó„   — e Zd ZdZ	 	 	 	 	 	 	 d2d3d„Zd4d„Zd5d„Zed6d#„¦   «         Z	 d7d8d&„Z		 	 	 d9d:d*„Z
d;d-„Z	 	 d<d=d1„ZdS )>ÚTableGridExtractorV1BaŽ  
    Hybrid table grid extractor (V1B).

    Candidate grid lines are derived from cell bbox geometry (V3 rule-based
    algorithm, same as V1A). Active regions are determined by applying V1-style
    heatmap threshold + 1D CCL. A candidate line is kept (score = 1.0) if and
    only if it falls inside a CCL active interval; otherwise it is rejected
    (score = 0.0).

    This decouples localisation (bbox geometry, pixel-accurate) from region
    detection (heatmap CCL, coarse but model-driven).

    When bboxes=None is passed, cell bboxes are extracted automatically from
    the db_prob map produced by the same inference pass (same as V1A).
    ç333333Ã?çš™™™™™Ù?r-   ç333333Ó?é
   r   NÚ	onnx_pathú
str | PathÚh_on_thresholdr   Úv_on_thresholdr1   Údb_prob_thresholdÚdb_min_arear   rm   Ú	providersúlist | Noner   ÚNonec	                óÀ  — |€dg}t          |¦  «        | _        || _        || _        || _        || _        || _        || _        t          t          | j        ¦  «        |¦  «        | _
        | j
                             ¦   «         d         }	t          |	j        d         ¦  «        | _        t          |	j        d         ¦  «        | _        d„ | j
                             ¦   «         D ¦   «         }
|
                     d¦  «        | _        |
                     d¦  «        | _        d	|
v r|
                     d	¦  «        nd| _        t+          j        d
d| j        | j        ft*          j        ¬¦  «        }| j
                             dd|i¦  «        }t          || j                 j        d
         ¦  «        | _        t          || j                 j        d
         ¦  «        | _        dS )a2  
        Parameters
        ----------
        onnx_path          : path to exported GridModelV1 .onnx file
        h_on_threshold     : heatmap activation threshold for h CCL intervals
        v_on_threshold     : heatmap activation threshold for v CCL intervals
        grid_margin_px     : alignment tolerance for candidate grid extraction
        db_prob_threshold  : binarization threshold for automatic DB bbox extraction
        db_min_area        : minimum contour area (px) accepted during DB extraction
        top_k              : max candidates kept per CCL interval ranked by heatmap
                             value; candidates beyond top_k are dropped. Use 0 or
                             a negative value to disable (keep all).
        providers          : ONNX Runtime execution providers
        NÚCPUExecutionProviderr   r   r4   c                ó   — g | ]	}|j         ‘Œ
S rp   )Úname)rq   Úos     r*   rs   z2TableGridExtractorV1B.__init__.<locals>.<listcomp>L  s   € ÐAÐAÐA 1˜œÐAÐAÐAr,   Ú	h_heatmapÚ	v_heatmapÚdb_probr   r]   Úimage)r   r„   r†   r‡   r1   rˆ   r‰   rm   r	   ÚstrÚ_sessÚ
get_inputsr   ÚshapeÚ_input_hÚ_input_wÚget_outputsÚindexÚ_idx_h_heatmapÚ_idx_v_heatmapÚ_idx_db_probr`   ra   rb   ÚrunÚ_out_hÚ_out_w)Úselfr„   r†   r‡   r1   rˆ   r‰   rm   rŠ   ÚinpÚoutput_namesÚdummyÚoutputss                r*   Ú__init__zTableGridExtractorV1B.__init__!  s   € ð2 ÐØ/Ð0ˆIå!% i¡¤ˆŒØ!/ˆÔØ!/ˆÔØ!/ˆÔØ!2ˆÔØ!,ˆÔØ!&ˆŒ
å!¥# d¤nÑ"5Ô"5°yÑAÔAˆŒ
àŒj×#Ò#Ñ%Ô% aÔ(ˆÝ˜CœI aœLÑ)Ô)ˆŒÝ˜CœI aœLÑ)Ô)ˆŒð BÐA¨¬
×(>Ò(>Ñ(@Ô(@ÐAÑAÔAˆØ*×0Ò0°Ñ=Ô=ˆÔØ*×0Ò0°Ñ=Ô=ˆÔØ?HÈLÐ?XÐ?X˜l×0Ò0°Ñ;Ô;Ð;Ð^bˆÔå”(˜A˜q $¤-°´Ð?ÅrÄzÐRÑRÔRˆØ”*—.’. ¨°Ð'7Ñ8Ô8ˆÝ˜' $Ô"5Ô6Ô<¸QÔ?Ñ@Ô@ˆŒÝ˜' $Ô"5Ô6Ô<¸QÔ?Ñ@Ô@ˆŒˆˆr,   Ú	image_bgrrO   r2   c                ó*  — ddl }|j        dd…         \  }} |j        || j        | j        f¦  «        }|dd…dd…ddd…f                              t          j        ¦  «        }|                     ¦   «         | 	                    ¦   «         }}||k    r||z
  ||z
  z  }nt          j
        |¦  «        }|                     ddd¦  «        t          j                 }	| j                             dd|	i¦  «        }
|
| j                 d         }|
| j                 d         } |j        |t          j        dd…f                              t          j        ¦  «        |df|j        ¬¦  «        d         } |j        |t          j        dd…f                              t          j        ¦  «        |df|j        ¬¦  «        d         }d}| j        �J|
| j                 d         } |j        |                     t          j        ¦  «        ||f|j        ¬¦  «        }|||fS )	a  
        Run GridModelV1 inference and return heatmaps and db_prob map,
        all resized to the original image dimensions.

        Returns
        -------
        (h_heatmap, v_heatmap, db_prob_map)
        h_heatmap   : (orig_h,)          float32
        v_heatmap   : (orig_w,)          float32
        db_prob_map : (orig_h, orig_w)   float32, or None if not exported
        r   Nr   éÿÿÿÿr   r•   ©Úinterpolation)r   r   )Úcv2r™   Úresizer›   rš   Úastyper`   rb   r6   r5   Ú
zeros_likeÚ	transposeÚnewaxisr—   r¡   rž   rŸ   ÚINTER_LINEARr    )r¤   rª   r¯   r/   r0   Úimg_resizedÚimg_rgbÚmnÚmxr¥   r¨   Úh_rawÚv_rawr’   r“   Údb_prob_mapÚdb_raws                    r*   Ú_run_inferencez$TableGridExtractorV1B._run_inferenceZ  s  € ð 	ˆ
ˆ
ˆ
à"œ¨¨!¨Ô,‰ˆ�à �c”j ¨T¬]¸D¼MÐ,JÑKÔKˆØ˜a˜a˜a    D D b D˜jÔ)×0Ò0µ´Ñ<Ô<ˆØ—’‘” §¢¡¤ˆBˆØ�Š7ˆ7Ø ‘|¨¨R©Ñ0ˆGˆGå”m GÑ,Ô,ˆGØ×Ò  1 aÑ(Ô(­¬Ô4ˆà”*—.’. ¨° ~Ñ6Ô6ˆà˜Ô+Ô,¨QÔ/ˆØ˜Ô+Ô,¨QÔ/ˆð �C”JØ•"”*˜a˜a˜a�-Ô ×'Ò'­¬
Ñ3Ô3Ø�QˆKØÔ*ð
ñ 
ô 
ð ô	ˆ	ð
 �C”JØ•"”*˜a˜a˜a�-Ô ×'Ò'­¬
Ñ3Ô3Ø�QˆKØÔ*ð
ñ 
ô 
ð ô	ˆ	ð *.ˆØÔÐ(Ø˜TÔ.Ô/°Ô5ˆFØ$˜#œ*Ø—’�bœjÑ)Ô)Ø˜Ð Ø!Ô.ðñ ô ˆKð ˜) [Ð0Ð0r,   r¼   r   c                óP  — ddl }|| j        k                         t          j        ¦  «        dz  } |j        ||j        |j        ¦  «        \  }}g }|D ]R} |j        |¦  «        }|| j	        k     rŒ |j
        |¦  «        \  }	}
}}|                     |	|
|	|z   |
|z   g¦  «         ŒS|S )a  
        Extract cell bounding boxes from a DB probability map.

        Steps
        -----
        1. Binarize with db_prob_threshold.
        2. Find external contours.
        3. Accept contours whose area >= db_min_area as [x1, y1, x2, y2] boxes.
        r   Néÿ   )r¯   rˆ   r±   r`   Úuint8ÚfindContoursÚRETR_EXTERNALÚCHAIN_APPROX_SIMPLEÚcontourArear‰   ÚboundingRectr7   )r¤   r¼   r¯   ÚbinaryÚcontoursÚ_r.   ÚcontourÚareaÚxrr   rC   rD   s                r*   Ú_extract_bboxes_from_dbz-TableGridExtractorV1B._extract_bboxes_from_db“  sÑ   € ð 	ˆ
ˆ
ˆ
à Ô!7Ò7×?Ò?ÅÄÑIÔIÈCÑOˆØ&�cÔ&Ø�CÔ% sÔ'>ñ
ô 
‰ˆ�!ð ˆØð 	0ð 	0ˆGØ"�3”? 7Ñ+Ô+ˆDØ�dÔ&Ò&Ð&ØØ)˜Ô)¨'Ñ2Ô2‰JˆAˆq�!�QØ�MŠM˜1˜a  Q¡¨¨A©Ð.Ñ/Ô/Ð/Ð/Øˆr,   rj   úlist[float]ÚcentersÚ
image_sizec                ó˜  ‡‡— | s| S t          | ¦  «        }d}|�r/d}|s�n)dg|z   t          |¦  «        gz   Št          ‰¦  «        dz
  }ˆˆfd„t          |¦  «        D ¦   «         }|d         r|d         dk    rd|d<   d}Œj|d         r|r|                     ¦   «          d}Œ‹g }d}t          t          |¦  «        ¦  «        D ]t}	|rd}Œ||	dz            }
|
rE|	dz   t          |¦  «        k     r/|                     ||	         ||	dz            z   dz  ¦  «         d}d}ŒY|                     ||	         ¦  «         Œut          |¦  «        }|�°/|S )	zŽ
        Remove adjacent line pairs that have no bbox center between them.
        Behaviour is identical to V1A._filter_empty_lines.
        TFru   r   c                óL   •‡— g | ]Št          ˆˆfd „‰D ¦   «         ¦  «         ‘Œ S )c              3  óV   •K  — | ]#}‰‰         |cxk     o‰‰d z            k     nc V — Œ$dS )r   Nrp   )rq   ÚcÚedgesr   s     €€r*   ú	<genexpr>zGTableGridExtractorV1B._filter_empty_lines.<locals>.<listcomp>.<genexpr>È  sK   øè è € ÐEÐE¸˜˜aœ 1Ð3Ð3Ò3Ð3 u¨Q°©U¤|Ò3Ð3Ð3Ð3ÐEÐEÐEÐEÐEÐEr,   )Úany)rq   r   rÏ   rÕ   s    @€€r*   rs   z=TableGridExtractorV1B._filter_empty_lines.<locals>.<listcomp>Ç  sM   øø€ ð ð ð àõ ÐEÐEÐEÐEÐE¸WÐEÑEÔEÑEÔEÐEðð ð r,   r   r¬   ç       @)r   r   r   r   Úpopr7   )rj   rÏ   rÐ   ÚcurrentÚchangedÚn_gapsÚ	gap_emptyÚmergedÚ	skip_nextr   Úgap_right_emptyrÕ   s    `         @r*   Ú_filter_empty_linesz)TableGridExtractorV1B._filter_empty_lines°  s¹  øø€ ð ð 	ØˆLå˜‘-”-ˆØˆàñ #	%ØˆGØð ÙØ�U˜W‘_­¨jÑ(9Ô(9Ð':Ñ:ˆEÝ˜‘Z”Z !‘^ˆFðð ð ð ð å˜v™œðñ ô ˆIð
 ˜Œ|ð  ¨¤
¨cÒ 1Ð 1Ø �˜‘
Ø�Øà˜Œ}ð  ð Ø—’‘”�Ø�Øà"$ˆFØˆIÝ�3˜w™<œ<Ñ(Ô(ð 
.ð 
.�Øð Ø %�IØØ"+¨A°©EÔ"2�Ø"ð . q¨1¡u­s°7©|¬|Ò';Ð';Ø—M’M 7¨1¤:°¸¸A¹´Ñ#>À#Ñ"EÑFÔFÐFØ $�IØ $�G�Gà—M’M '¨!¤*Ñ-Ô-Ð-Ð-Ý˜V‘n”nˆGðG ñ #	%ðJ ˆr,   r.   r   c           	     ó4  ‡‡‡‡— |j         dd…         \  }}|                      |¦  «        \  }}}|€&|€t          d¦  «        ‚|                      |¦  «        }t	          |||| j        ¦  «        \  }}	}
t          || j        ¦  «        }t          || j        ¦  «        }t          |||¦  «        \  ŠŠt          |	||¦  «        \  ŠŠd„ t          |‰¦  «        D ¦   «         }d„ t          |	‰¦  «        D ¦   «         }| j        dk    rfˆˆfd„t          |¦  «        D ¦   «         }ˆˆfd„t          |	¦  «        D ¦   «         }t          |||| j        ¦  «        }t          |||| j        ¦  «        }t          t          |¦  «        t          |¦  «        ||‰‰|¬	¦  «        S )
a  
        Derive candidate grid lines from bboxes and gate them by V1-style
        CCL active intervals extracted from the heatmap.

        Scoring rule
        ------------
        - Build CCL active intervals from the resized heatmap using threshold.
        - Candidate line position falls inside an interval  -> score = 1.0 (kept).
        - Candidate line position falls outside all intervals -> score = 0.0 (dropped).

        Parameters
        ----------
        image_bgr : cropped table BGR image (any size)
        bboxes    : list of [x1, y1, x2, y2] cell bbox pixel coordinates.
                    When None, extracted automatically from the db_prob map.

        Returns
        -------
        GridPrediction with filtered h/v lines and binary confidence scores.
        Nr   zcbboxes=None requires the ONNX model to export 'db_prob', but it was not found in the model outputs.c                ó$   — g | ]\  }}|d k    ¯|‘ŒS ©ru   rp   ©rq   rr   Úss      r*   rs   z6TableGridExtractorV1B.predict_grid.<locals>.<listcomp>  ó!   € ÐBÐBÐB™˜˜A¸!¸cº'¸'�1¸'¸'¸'r,   c                ó$   — g | ]\  }}|d k    ¯|‘ŒS rä   rp   ©rq   rÌ   ræ   s      r*   rs   z6TableGridExtractorV1B.predict_grid.<locals>.<listcomp>  rç   r,   r   c                óZ   •— i | ]'\  }}‰|         d k    ¯|t          ‰|         ¦  «        “Œ(S rä   ©r   )rq   r   rr   Úh_heatÚh_scoress      €€r*   ú
<dictcomp>z6TableGridExtractorV1B.predict_grid.<locals>.<dictcomp>$  óF   ø€ ð Nð Nð NÙ"˜a ¸8ÀA¼;ÈÒ;LÐ;Lð �U 6¨!¤9Ñ-Ô-Ø;LÐ;LÐ;Lr,   c                óZ   •— i | ]'\  }}‰|         d k    ¯|t          ‰|         ¦  «        “Œ(S rä   rë   )rq   r   rÌ   Úv_heatÚv_scoress      €€r*   rî   z6TableGridExtractorV1B.predict_grid.<locals>.<dictcomp>&  rï   r,   ©rK   rL   r’   r“   Úh_confidencesÚv_confidencesr¼   )r™   r¾   ÚRuntimeErrorrÍ   rM   r1   rY   r†   r‡   ri   Úziprm   rS   r}   r   r   )r¤   rª   r.   r/   r0   r’   r“   r¼   Úcand_hÚcand_vrÉ   Úh_intervalsÚv_intervalsrK   rL   Ú
h_heat_mapÚ
v_heat_maprì   rí   rñ   rò   s                    @@@@r*   Úpredict_gridz"TableGridExtractorV1B.predict_gridë  s  øøøø€ ð2 #œ¨¨!¨Ô,‰ˆ�à,0×,?Ò,?À	Ñ,JÔ,JÑ)ˆ	�9˜kàˆ>ØÐ"Ý"ðAñô ð ð ×1Ò1°+Ñ>Ô>ˆFõ 3Ø�F˜F DÔ$7ñ
ô 
Ñˆ�˜õ
 /¨y¸$Ô:MÑNÔNˆÝ.¨y¸$Ô:MÑNÔNˆõ >¸fÀkÐS\Ñ]Ô]Ñˆ�&Ý=¸fÀkÐS\Ñ]Ô]Ñˆ�&ð CÐB¥ V¨XÑ!6Ô!6ÐBÑBÔBˆØBÐB¥ V¨XÑ!6Ô!6ÐBÑBÔBˆð Œ:˜Š>ˆ>ðNð Nð Nð Nð NÝ&/°Ñ&7Ô&7ðNñ Nô NˆJðNð Nð Nð Nð NÝ&/°Ñ&7Ô&7ðNñ Nô NˆJõ 0°¸ÀjÐRVÔR\Ñ]Ô]ˆGÝ/°¸ÀjÐRVÔR\Ñ]Ô]ˆGåÝ˜7‘O”OÝ˜7‘O”OØØØ"Ø"Ø#ð
ñ 
ô 
ð 	
r,   çš™™™™™¹?ÚtextsÚspan_thresholdc                ó
  — t          |t          t          j        f¦  «        rÎt	          |¦  «        dk    r»|j        dd…         \  }}|                      |¦  «        \  }}}t          g g t          j        |t          j	        ¬¦  «        t          j        |t          j	        ¬¦  «        t          j
        g t          j	        ¬¦  «        t          j
        g t          j	        ¬¦  «        |¬¦  «        g fS |                      ||¦  «        }	|€$|	j        �|                      |	j        ¦  «        ng }
nt          |¦  «        }
|
s|	g fS t          |j        d         ¦  «        }t          |j        d         ¦  «        }t          d„ |
D ¦   «         ¦  «        }t          d„ |
D ¦   «         ¦  «        }|                      |	j        ||¦  «        }|                      |	j        ||¦  «        }t          |||	j        |	j        |	j        |	j        |	j        ¬¦  «        }	t          j        |
t          j	        ¬¦  «        }|                      ||	|¬	¦  «        }|�9|D ]6}d|j        cxk    rt	          |¦  «        k     rn Œ$||j                 |_        Œ7|	|fS )
a7  
        Predict grid and assign bboxes to grid cells.

        Parameters
        ----------
        image_bgr      : cropped table BGR image
        bboxes         : list of [x1, y1, x2, y2] in crop space, or None to
                         extract bboxes automatically from the DB output.
                         An empty list bypasses all processing.
        texts          : text strings aligned with bboxes
        span_threshold : fractional overlap to trigger span expansion

        Returns
        -------
        (GridPrediction, list[CellInfo])
        r   Nr   r]   ró   r   c              3  ór   K  — | ]2}t          |d          ¦  «        t          |d         ¦  «        z   dz  V — Œ3dS )r   r   rØ   Nrë   ©rq   Úbs     r*   rÖ   z0TableGridExtractorV1B.predict.<locals>.<genexpr>h  ó@   è è € ÐUÐU¸q�%  !¤™+œ+­¨a°¬d©¬Ñ3°sÑ:ÐUÐUÐUÐUÐUÐUr,   c              3  ór   K  — | ]2}t          |d          ¦  «        t          |d         ¦  «        z   dz  V — Œ3dS )r   r4   rØ   Nrë   r  s     r*   rÖ   z0TableGridExtractorV1B.predict.<locals>.<genexpr>i  r  r,   )Úbboxes_pageÚgridr  )Ú
isinstancer   r`   Úndarrayr   r™   r¾   r   ra   rb   Úarrayrþ   r¼   rÍ   r   r   rá   rK   rL   r’   r“   rô   rõ   ÚasarrayÚ_post_process_gridÚbbox_idxÚtext)r¤   rª   r.   r   r  r/   r0   rÉ   r¼   r	  Úeffective_bboxesÚcrop_hÚcrop_wÚcx_listÚcy_listÚ
filtered_hÚ
filtered_vÚ
bboxes_arrÚcellsÚcells                       r*   ÚpredictzTableGridExtractorV1B.predict6  sŸ  € õ. �f�t¥R¤ZÐ0Ñ1Ô1ð 	µc¸&±k´kÀQÒ6FÐ6FØ&œ_¨R¨a¨RÔ0‰NˆF�FØ $× 3Ò 3°IÑ >Ô >ÑˆAˆq�+Ý!ØØÝœ( 6µ´Ð<Ñ<Ô<Ýœ( 6µ´Ð<Ñ<Ô<Ý œh rµ´Ð<Ñ<Ô<Ý œh rµ´Ð<Ñ<Ô<Ø'ðñ ô ð ðð ð × Ò  ¨FÑ3Ô3ˆð ˆ>àÔ#Ð/ð  $×;Ò;¸DÔ<LÑMÔMÐMØ57ð Ðõ  $ F™|œ|Ðàð 	Ø˜�8ˆOå�y” qÔ)Ñ*Ô*ˆÝ�y” qÔ)Ñ*Ô*ˆÝÐUÐUÐDTÐUÑUÔUÑUÔUˆÝÐUÐUÐDTÐUÑUÔUÑUÔUˆà×-Ò-¨d¬l¸GÀVÑLÔLˆ
Ø×-Ò-¨d¬l¸GÀVÑLÔLˆ
åØØØ”nØ”nØÔ,ØÔ,ØÔ(ð
ñ 
ô 
ˆõ ”ZÐ 0½¼
ÐCÑCÔCˆ
Ø×'Ò'Ø"ØØ)ð (ñ 
ô 
ˆð ÐØð 5ð 5�Ø˜œÐ2Ð2Ò2Ð2­¨E©
¬
Ò2Ð2Ð2Ð2Ð2Ø % d¤mÔ 4�D”Iøà�Uˆ{Ðr,   r  r	  c                óº  — |j         rKt          |j         ¦  «        d         }dgt          |j         ¦  «        z   t          |dz  |dz   ¦  «        gz   }nddg}|j        rKt          |j        ¦  «        d         }dgt          |j        ¦  «        z   t          |dz  |dz   ¦  «        gz   }nddg}dd„}g }	t	          |¦  «        D �]\  }
}t          |d         ¦  «        }t          |d         ¦  «        }t          |d         ¦  «        }t          |d         ¦  «        }||z   dz  }||z   dz  } |||¦  «        } |||¦  «        }||dz   }}||dz   }}|}|dk    r>||         ||dz
           z
  }|dk    r||         |z
  |z  |k    r|dz
  }|dz  }nn|dk    °>|}|t          |¦  «        dz
  k     rQ||dz            ||         z
  }|dk    r |||dz            z
  |z  |k    r|dz   }|dz  }nn|t          |¦  «        dz
  k     °Q|}|dk    r>||         ||dz
           z
  }|dk    r||         |z
  |z  |k    r|dz
  }|dz  }nn|dk    °>|}|t          |¦  «        dz
  k     rQ||dz            ||         z
  }|dk    r |||dz            z
  |z  |k    r|dz   }|dz  }nn|t          |¦  «        dz
  k     °Q|	                     t          |
||||||¬¦  «        ¦  «         �Œ|	S )Nr¬   ru   r   r   r_   rf   r   rÕ   r   r   r   c                óÌ   — t          t          |¦  «        dz
  ¦  «        D ]%}||         | cxk    r||dz            k     rn Œ!|c S Œ&t          dt          |¦  «        dz
  ¦  «        S )Nr   r   r   )r   r   r5   )rf   rÕ   r   s      r*   Úfind_cell_idxz?TableGridExtractorV1B._post_process_grid.<locals>.find_cell_idxœ  sy   € Ý�3˜u™:œ:¨™>Ñ*Ô*ð ð �Ø˜”8˜sÐ1Ð1Ò1Ð1 U¨1¨q©5¤\Ò1Ð1Ð1Ð1Ð1Ø�H�H�Hð 2å�q�#˜e™*œ* q™.Ñ)Ô)Ð)r,   r   r4   rØ   )r  Ú	row_startÚrow_endÚ	col_startÚcol_endÚrowÚcol)rf   r   rÕ   r   r   r   )	rK   r   r5   rL   rS   r   r   r7   r   )r¤   r  r	  r  Úlast_hÚ	row_edgesÚlast_vÚ	col_edgesr  Úresultsr   r#   Úx0Úy0r?   r@   ÚcxÚcyÚbase_rowÚbase_colr  r   r!  r"  ÚrrD   rÔ   rC   s                               r*   r  z(TableGridExtractorV1B._post_process_gridŠ  sª  € ð Œ<ð 	#Ý˜DœLÑ)Ô)¨"Ô-ˆFØ˜¥ t¤|Ñ 4Ô 4Ñ4½¸FÀQ¹JÈÐQRÉ
Ñ8SÔ8SÐ7TÑTˆIˆIà˜c˜
ˆIàŒ<ð 	#Ý˜DœLÑ)Ô)¨"Ô-ˆFØ˜¥ t¤|Ñ 4Ô 4Ñ4½¸FÀQ¹JÈÐQRÉ
Ñ8SÔ8SÐ7TÑTˆIˆIà˜c˜
ˆIð	*ð 	*ð 	*ð 	*ð ˆÝ  Ñ-Ô-ð 2	ñ 2	‰GˆAˆtÝ�t˜A”w‘”ˆBÝ�t˜A”w‘”ˆBÝ�t˜A”w‘”ˆBÝ�t˜A”w‘”ˆBØ�r‘'˜S‘ˆBØ�r‘'˜S‘ˆBà$�} R¨Ñ3Ô3ˆHØ$�} R¨Ñ3Ô3ˆHØ!)¨8°a©<�wˆIØ!)¨8°a©<�wˆIàˆAØ�a’%�%Ø˜a”L 9¨Q°©UÔ#3Ñ3�Ø�q’5�5˜i¨œl¨RÑ/°1Ñ4°~ÒEÐEØ ! A¡�IØ˜‘F�A�Aàð �a’%�%ð ˆAØ•c˜)‘n”n qÑ(Ò(Ð(Ø˜a !™eÔ$ y°¤|Ñ3�Ø�q’5�5˜b 9¨Q°©UÔ#3Ñ3°qÑ8¸>ÒIÐIØ !™e�GØ˜‘F�A�Aàð •c˜)‘n”n qÑ(Ò(Ð(ð ˆAØ�a’%�%Ø˜a”L 9¨Q°©UÔ#3Ñ3�Ø�q’5�5˜i¨œl¨RÑ/°1Ñ4°~ÒEÐEØ ! A¡�IØ˜‘F�A�Aàð �a’%�%ð ˆAØ•c˜)‘n”n qÑ(Ò(Ð(Ø˜a !™eÔ$ y°¤|Ñ3�Ø�q’5�5˜b 9¨Q°©UÔ#3Ñ3°qÑ8¸>ÒIÐIØ !™e�GØ˜‘F�A�Aàð •c˜)‘n”n qÑ(Ò(Ð(ð �NŠN�8Ø i¸Ø#¨WØ (ðñ ô ñ ô ð ñ ð ˆr,   éè  ÚpredÚmax_dimc                óÖ  — ddl }|j        dd…         \  }}|�t          |¦  «        }n$|j        �|                      |j        ¦  «        }ng }t          |||| j        ¦  «        \  }	}
}t          |j        | j	        ¦  «        }t          |j
        | j        ¦  «        }t          |	||j        ¦  «        \  }}t          |
||j
        ¦  «        \  }}t          |j        ¦  «        }t          |j        ¦  «        }|                     ¦   «         }|                     ¦   «         }|D ]\  }} |j        |d|f||fdd¦  «         Œ|D ]\  }} |j        ||df||fdd¦  «         Œ |j        |d|dd|¦  «         |D ]+}d„ |D ¦   «         \  }}}} |j        |||f||fd	d
¦  «         Œ,t'          |	|¦  «        D ]²\  }}t)          t+          |¦  «        ¦  «        }||v rG |j        |d|f||fdd
¦  «          |j        |ddt1          |dz
  d¦  «        f|j        ddd
¦  «         Œl |j        |d|f||fdd
¦  «          |j        |ddt1          |dz
  d¦  «        f|j        ddd
¦  «         Œ³t'          |
|¦  «        D ]A\  }}t)          t+          |¦  «        ¦  «        }||v rdnd}  |j        ||df||f| d
¦  «         ŒBt5          j        |j        dd…t4          j        f         d
|f¦  «        }! |j        |!dz                       dd¦  «                             t4          j         ¦  «        |j!        ¦  «        }"|D ] \  }} |j        |"d|f|d
z
  |fdd
¦  «         Œ!|	D ]>}t)          t+          |¦  «        ¦  «        }||v rdnd}  |j        |"d|f||f| d
¦  «         Œ? |j        |"d| j	        d›�d|j        ddd
¦  «         t5          j        |j
        t4          j        dd…f         |d
f¦  «        }# |j        |#dz                       dd¦  «                             t4          j         ¦  «        |j!        ¦  «        }$|D ] \  }} |j        |$|df||d
z
  fdd
¦  «         Œ!|
D ]>}t)          t+          |¦  «        ¦  «        }||v rdnd}  |j        |$|df||f| d
¦  «         Œ? |j        |$d| j        d›�d|j        ddd
¦  «         |j        �Ï |j        |j        dz                       dd¦  «                             t4          j         ¦  «        |j!        ¦  «        }% |j"        |%||f|j#        ¬¦  «        }%|D ]+}d„ |D ¦   «         \  }}}} |j        |%||f||fdd
¦  «         Œ, |j        |%d| j$        d›dtK          |¦  «        › �d|j        ddd
¦  «         |%}&�nt5          j&        ||dft4          j         ¬¦  «        }'d„ t'          |	|¦  «        D ¦   «         d „ t'          |
|¦  «        D ¦   «         z   }(tK          |(¦  «        })|)dk    rwt1          d
||)z  ¦  «        }*tO          |(¦  «        D ]T\  }+\  },}-}.|+|*z  }/|/|*z   d
z
  }0t)          |-|d!z
  z  ¦  «        }1|.rd"nd#} |-d$k     rd%}  |j        |'|/||1z
  f|0|f| d¦  «         ŒU |j        |'d&d|j        d'd(d
¦  «         |'}&t5          j(        ||"gd
¬)¦  «        }2t5          j(        |$|&gd
¬)¦  «        }3t5          j(        |2|3gd¬)¦  «        }4|4j        dd…         \  }5}6|5|k    s	|6|dz  k    rotS          ||5z  |dz  |6z  ¦  «        }7 |j"        |4t1          d
t)          |6|7z  ¦  «        ¦  «        t1          d
t)          |5|7z  ¦  «        ¦  «        f|j*        ¬¦  «        }4|4S )*a  
        Visualize V1B results: CCL active intervals, candidates, kept/rejected
        lines, and heatmaps.

        Layout (2x2)
        ------------
        (1,1) image + kept lines (green h, orange v) +
              rejected candidates (red) + bbox rectangles (cyan)
              + CCL interval bands (semi-transparent yellow overlay)
        (1,2) h_heatmap tiled to 2D with CCL interval bands and candidate
              h line positions marked
        (2,1) v_heatmap tiled to 2D with CCL interval bands and candidate
              v line positions marked
        (2,2) db_prob_map heatmap when available; confidence bar chart
              (binary 0/1) otherwise

        Parameters
        ----------
        image_bgr : original BGR image
        pred      : GridPrediction from predict_grid() or predict()
        bboxes    : bbox list for candidate overlay; falls back to DB
                    extraction from pred.db_prob_map when None
        max_dim   : maximum single-panel dimension before downscaling
        r   Nr   )r   éÜ   r5  r¬   r€   g333333ë?c                óF   — g | ]}t          t          |¦  «        ¦  «        ‘ŒS rp   ©r   r   ©rq   Úvs     r*   rs   z3TableGridExtractorV1B.visualize.<locals>.<listcomp>#  s$   € Ð:Ð:Ð:°�c¥%¨¡(¤(™mœmÐ:Ð:Ð:r,   )rÀ   rÀ   r   r   )r   rÀ   r   z1.0é   gìQ¸…ëÑ?)r   r   rÀ   z0.0)rÀ   é€   r   rÀ   )rÀ   rÀ   rÀ   zh_thr=z.2f)é   é   gffffffÖ?zv_thr=r­   c                óF   — g | ]}t          t          |¦  «        ¦  «        ‘ŒS rp   r7  r8  s     r*   rs   z3TableGridExtractorV1B.visualize.<locals>.<listcomp>]  s$   € Ð!>Ð!>Ð!>°A¥#¥e¨A¡h¤h¡-¤-Ð!>Ð!>Ð!>r,   zdb_thr=z  n=r4   r]   c                ó   — g | ]
\  }}||d f‘ŒS )Trp   rå   s      r*   rs   z3TableGridExtractorV1B.visualize.<locals>.<listcomp>h  s"   € ÐAÐAÐA¡4 1 a�!�Q˜�ÐAÐAÐAr,   c                ó   — g | ]
\  }}||d f‘ŒS )Frp   ré   s      r*   rs   z3TableGridExtractorV1B.visualize.<locals>.<listcomp>i  s"   € ÐAÐAÐA¡4 1 a�!�Q˜�ÐAÐAÐAr,   é   )r   éÈ   r   )rB  éd   r   r_   )r   r   é´   z+Score: green=h(1.0)  orange=v(1.0)  red=0.0r‚   )rB  rB  rB  )Úaxis)+r¯   r™   r   r¼   rÍ   rM   r1   rY   r’   r†   r“   r‡   ri   r   rK   rL   ÚcopyÚ	rectangleÚaddWeightedr÷   r   r   ÚlineÚputTextr5   ÚFONT_HERSHEY_SIMPLEXr`   Útiler´   ÚapplyColorMapÚclipr±   rÁ   ÚCOLORMAP_JETr°   rµ   rˆ   r   ra   rS   Úconcatenater6   Ú
INTER_AREA)8r¤   rª   r2  r.   r3  r¯   r/   r0   Ú
vis_bboxesrø   rù   rÉ   rú   rû   rí   rò   Úkept_hÚkept_vÚoverlayÚband_overlayrg   rh   r#   r?   r@   rA   rB   rr   ræ   ÚyprÌ   ÚxpÚcolorÚh_2dÚh_panelÚv_2dÚv_panelÚdb_panelÚbottom_rightÚ	bar_panelÚ	all_linesre   Úbar_wÚidxrf   ÚscoreÚis_hr$   r&   Úbar_h_pxÚtop_rowÚbot_rowÚcomposedÚchÚcwÚscales8                                                           r*   Ú	visualizezTableGridExtractorV1B.visualizeÝ  sP	  € ð> 	ˆ
ˆ
ˆ
à"œ¨¨!¨Ô,‰ˆ�ð ÐÝ˜f™œˆJˆJØÔÐ)Ø×5Ò5°dÔ6FÑGÔGˆJˆJàˆJõ 3Ø˜ ¨Ô(;ñ
ô 
Ñˆ�˜õ /¨t¬~¸tÔ?RÑSÔSˆÝ.¨t¬~¸tÔ?RÑSÔSˆÝ8¸ÀÈdÌnÑ]Ô]‰ˆ�!Ý8¸ÀÈdÌnÑ]Ô]‰ˆ�!å�T”\Ñ"Ô"ˆÝ�T”\Ñ"Ô"ˆð —.’.Ñ"Ô"ˆð —|’|‘~”~ˆØ%ð 	-ð 	-‰JˆE�3ØˆCŒM˜,¨¨E¨
°V¸S°MØ'¨ñ-ô -ð -ð -à%ð 	-ð 	-‰JˆE�3ØˆCŒM˜,¨°¨
°S¸&°MØ'¨ñ-ô -ð -ð -àˆŒ˜ d¨G°T¸1¸gÑFÔFÐFàð 	Ið 	IˆDØ:Ð:°TÐ:Ñ:Ô:‰NˆB��B˜ØˆCŒM˜' B¨ 8¨b°"¨X°}ÀaÑHÔHÐHÐHå˜ Ñ)Ô)ð 		Lð 		L‰DˆAˆqÝ•U˜1‘X”X‘”ˆBØ�Fˆ{ˆ{Ø�”˜ 1 b '¨F°B¨<¸ÀaÑHÔHÐHØ�”˜G U¨Qµ°B¸±F¸A±´Ð,?ØÔ4°d¸KÈñLô Lð Lð Lð �”˜ 1 b '¨F°B¨<¸ÀaÑHÔHÐHØ�”˜G U¨Qµ°B¸±F¸A±´Ð,?ØÔ4°d¸KÈñLô Lð Lð Lõ ˜ Ñ)Ô)ð 	?ð 	?‰DˆAˆqÝ•U˜1‘X”X‘”ˆBØ%&¨& [ [�M�M°kˆEØˆCŒH�W˜r 1˜g¨¨F |°U¸AÑ>Ô>Ð>Ð>õ Œw�t”~ a a a­¬ mÔ4°q¸&°kÑBÔBˆØ#�#Ô#Ø�C‰Z×Ò˜a Ñ%Ô%×,Ò,­R¬XÑ6Ô6¸Ô8Hñ
ô 
ˆð &ð 	.ð 	.‰JˆE�3ØˆCŒM˜' A u :°¸±
¸CÐ/@Ø)¨1ñ.ô .ð .ð .àð 	?ð 	?ˆAÝ•U˜1‘X”X‘”ˆBØ#$¨ ; ;�K�K°KˆEØˆCŒH�W˜q "˜g¨° |°U¸AÑ>Ô>Ð>Ð>ØˆŒ�GÐ? dÔ&9Ð?Ð?Ð?Ø˜SÔ5°t¸_Èañ	Qô 	Qð 	Qõ Œw�t”~¥b¤j°!°!°! mÔ4°v¸q°kÑBÔBˆØ#�#Ô#Ø�C‰Z×Ò˜a Ñ%Ô%×,Ò,­R¬XÑ6Ô6¸Ô8Hñ
ô 
ˆð &ð 	.ð 	.‰JˆE�3ØˆCŒM˜' E¨1 :°°V¸a±ZÐ/@Ø)¨1ñ.ô .ð .ð .àð 	?ð 	?ˆAÝ•U˜1‘X”X‘”ˆBØ#$¨ ; ;�K�K°KˆEØˆCŒH�W˜r 1˜g¨¨F |°U¸AÑ>Ô>Ð>Ð>ØˆŒ�GÐ? dÔ&9Ð?Ð?Ð?Ø˜SÔ5°t¸_Èañ	Qô 	Qð 	Qð ÔÐ'Ø(�sÔ(ØÔ! CÑ'×-Ò-¨a°Ñ5Ô5×<Ò<½R¼XÑFÔFØÔ ñô ˆHð "�s”z (¨V°VÐ,<Ø03Ô0@ðBñ Bô BˆHà"ð Pð P�Ø!>Ð!>¸Ð!>Ñ!>Ô!>‘��B˜˜BØ�”˜h¨¨R¨°2°r°(¸OÈQÑOÔOÐOÐOØˆCŒKØØK˜$Ô0ÐKÐKÐK½#¸j¹/¼/ÐKÐKØ˜Ô1°4¸È!ñô ð ð
 $ˆL‰Låœ &¨&°!Ð!4½B¼HÐEÑEÔEˆIàAÐA­3¨v°xÑ+@Ô+@ÐAÑAÔAØAÐA­3¨v°xÑ+@Ô+@ÐAÑAÔAñBð õ �I‘”ˆAØ�1ŠuˆuÝ˜A˜v¨™{Ñ+Ô+�Ý/8¸Ñ/CÔ/Cð 
-ð 
-Ñ+�CÑ+˜#˜u dØ ™+�CØ ™+¨™/�Cå" 5¨F°R©KÑ#8Ñ9Ô9�HØ+/ÐB˜K˜K°]�EØ˜s’{�{Ø +˜Ø!�C”M )Ø#&¨°Ñ(9Ð":¸SÀ&¸MØ"'¨ñ-ô -ð -ð -ð ˆCŒK˜	Ð#PØ Ô!9¸3ÀÐQRñTô Tð Tà$ˆLõ ”> 7¨WÐ"5ÀÐCÑCÔCˆÝ”> 7¨\Ð":ÀÐCÑCÔCˆÝ”> 7¨WÐ"5À!ÐDÑDÔDˆà”   Ô#‰ˆˆBØ�Š<ˆ<˜2 ¨!¡Ò+Ð+Ý˜7 R™<¨°1©°rÑ)9Ñ:Ô:ˆEØ!�s”zØÝ�Q�˜B ™J™œÑ(Ô(­#¨aµ°R¸%±Z±´Ñ*AÔ*AÐBØ!œnðñ ô ˆHð ˆr,   )r€   r�   r-   r‚   rƒ   r   N)r„   r…   r†   r   r‡   r   r1   r   rˆ   r   r‰   r   rm   r   rŠ   r‹   r   rŒ   )rª   rO   r   r2   )r¼   rO   r   r   )rj   rÎ   rÏ   rÎ   rÐ   r   r   rÎ   )N)rª   rO   r.   r‹   r   r   )NNrÿ   )
rª   rO   r.   r‹   r   r‹   r  r   r   r2   )r  rO   r	  r   r  r   r   r   )Nr1  )
rª   rO   r2  r   r.   r‹   r3  r   r   rO   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r©   r¾   rÍ   Ústaticmethodrá   rþ   r  r  rm  rp   r,   r*   r   r     s-  € € € € € ðð ð& !%Ø #Ø #Ø#&ØØØ!%ð3Að 3Að 3Að 3Að 3Aðr31ð 31ð 31ð 31ðrð ð ð ð: ð4ð 4ð 4ñ „\ð4ðz #ðI
ð I
ð I
ð I
ð I
ð\ #Ø!Ø #ðNð Nð Nð Nð NðhMð Mð Mð Mðn #Øðnð nð nð nð nð nð nr,   r   Ú__main__a!  Run TableGridExtractorV1B on all images in a directory. When a JSON sidecar (<image_stem>.json) exists next to the image, the bboxes stored in it are used directly. When no sidecar is found, bboxes are extracted automatically from the DB probability map output of the model (DB auto mode).)Údescriptionr„   z-Path to the exported GridModelV1 .onnx model.)ÚhelpÚ	image_dirz"Directory containing input images.z--h_on_thresholdg      Ð?z=Heatmap CCL threshold for h active intervals (default: 0.25).)ÚtypeÚdefaultru  z--v_on_thresholdgš™™™™™É?z<Heatmap CCL threshold for v active intervals (default: 0.2).z--grid_margin_pxzGAlignment tolerance for candidate grid extraction in px (default: 5.0).z--db_prob_thresholdr‚   zBDB binarization threshold for auto bbox extraction (default: 0.3).z--db_min_arearƒ   z@Minimum contour area in px for DB bbox extraction (default: 10).z--extensionsÚ*)ÚpngÚjpgÚjpegÚbmpÚtifÚtiffzImage file extensions to scan.)Únargsrx  ru  z	--max_dimix  z=Maximum dimension of the visualization panel (default: 1400).z
--save_dirzJIf set, save visualization images to this directory instead of displaying.)rx  ru  )r„   r†   r‡   r1   rˆ   r‰   T)ÚparentsÚexist_okz
list[Path]Ú	img_pathsz*.zNo images found in: Úsavingz%displaying (press any key to advance)zFound z image(s). Mode: ú.zCannot read: z.jsonr0  z	sidecar (z boxes)zDB autoz	  source=z	  bboxes=z
  h_lines=z
  v_lines=)r.   r3  Ú_v1b_visz  Saved -> zTableGridExtractorV1B - )
r
   r   r   r   r   r   r   r   r   r   )r-   )
r.   r   r/   r   r0   r   r1   r   r   r2   )rN   rO   rP   r   r   rQ   )rZ   r   rU   rQ   rN   rO   r   r[   )
rj   r   rU   rQ   rk   rl   rm   r   r   r   )Vrq  Ú
__future__r   Úpathlibr   Útypingr   Únumpyr`   ÚonnxruntimeÚortÚtable_grid_typesr   r   Úcommon_utilr	   r+   rM   rY   ri   r}   r   rn  ÚargparseÚjsonr¯   ÚArgumentParserÚparserÚadd_argumentr   r   Ú
parse_argsÚargsr„   r†   r‡   r1   rˆ   r‰   Ú	extractorrv  Úsave_dirÚmkdirrƒ  Ú__annotations__Ú
extensionsÚextÚextendr   ÚglobÚupperr   ÚprintÚmoder   Úimg_pathÚimreadr–   Úimg_bgrr�   Úwith_suffixÚ	json_pathÚexistsÚopenÚfÚloadr.   Úbbox_sourcerþ   r2  r¼   rÍ   Ún_boxesrK   rL   rm  r3  ri  ÚstemÚsuffixÚout_pathÚimwriteÚwindow_titleÚimshowÚwaitKeyÚdestroyWindowrp   r,   r*   ú<module>r´     sS  ððð ð ð8 #Ð "Ð "Ð "Ð "Ð "à Ð Ð Ð Ð Ð Ø Ð Ð Ð Ð Ð à Ð Ð Ð Ø Ð Ð Ð à 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ø %Ð %Ð %Ð %Ð %Ð %ð7%ð 7%ð 7%ð 7%ð|  ð	6/ð 6/ð 6/ð 6/ð 6/ðz"ð "ð "ð "ðJ$ð $ð $ð $ðBð ð ð ðL{	ð {	ð {	ð {	ð {	ñ {	ô {	ð {	ðD ˆzÒÑØ€O€O€OØ€K€K€KØ€J€J€Jà$ˆXÔ$ðIðñ ô €Fð ×Ò˜Ð*YÐÑZÔZÐZØ
×Ò˜Ð*NÐÑOÔOÐOØ
×ÒØ °ØLð ñ ô ð ð ×ÒØ °ØKð ñ ô ð ð ×ÒØ °ØVð ñ ô ð ð ×ÒØ E°3ØQð ñ ô ð ð ×ÒØ˜c¨2ØOð ñ ô ð ð ×ÒØ˜cØ<Ð<Ð<Ø-ð ñ ô ð ð
 ×ÒØ˜# tØLð ñ ô ð ð ×ÒØ˜dØYð ñ ô ð ð ×ÒÑÔ€Dà%Ð%Ø”.ØÔ*ØÔ*ØÔ*ØÔ0ØÔ$ðñ ô €Ið ��T”^Ñ$Ô$€IØ'+¤}Ð>���T”]Ñ#Ô#Ð#¸$€HØÐØ�Š˜t¨dˆÑ3Ô3Ð3à€IÐÐÐÑØŒð Eð EˆØ×Ò˜˜ 	§¢¨z°C¨z¨zÑ :Ô :Ñ;Ô;Ñ<Ô<Ð<Ø×Ò˜˜ 	§¢Ð/A°C·I²I±K´KÐ/AÐ/AÑ BÔ BÑCÔCÑDÔDÐDÐDØ��s�s˜9‘~”~Ñ&Ô&€Iàð AØˆÐ0 YÐ0Ð0Ñ1Ô1Ð1Ð1à#ÐPˆxˆxÐ)PˆØˆÐ?�s�s˜9‘~”~Ð?Ð?¸Ð?Ð?Ð?Ñ@Ô@Ð@àð #,ñ #,ˆØ�#”*˜S˜S ™]œ]Ñ+Ô+ˆØˆ?ØˆEÐ1 (¤-Ð1Ð1Ñ2Ô2Ð2Øà×(Ò(¨Ñ1Ô1ˆ	Ø×ÒÑÔð 	$Ø��i Ñ%Ô%ð &¨Ø"˜œ 1™œ�ð&ð &ð &ñ &ô &ð &ð &ð &ð &ð &ð &øøøð &ð &ð &ð &à: c c¨&¡k¤kÐ:Ð:Ð:ˆKˆKàˆFØ#ˆKà×%Ò% g¨vÑ6Ô6ˆà�^¨Ô(8Ð(Dð �#�i×7Ò7¸Ô8HÑIÔIÑJÔJÐJà"(Ð"4�3�3�v‘;”;�;¸!ð 	ð 	ˆØŒ}ð Hð H {ð Hð HØðHð Hà�s˜4œ<Ñ(Ô(ðHð Hà47°C¸¼Ñ4EÔ4EðHð Hñ	
ô 	
ð 	
ð ×&Ò& w°¸VÈTÌ\Ð&ÑZÔZˆàÐØ X¤]Ð"MÐ"M¸H¼OÐ"MÐ"MÑMˆHØˆCŒK˜˜˜H™œ xÑ0Ô0Ð0ØˆEÐ* Ð*Ð*Ñ+Ô+Ð+Ñ+àE°h´mÐEÐEˆLØˆCŒJ�| XÑ.Ô.Ð.ØˆCŒK˜‰NŒNˆNØˆCÔ˜lÑ+Ô+Ð+Ñ+ða ÐðZ#,ð #,s   Ì)MÍM
	ÍM
	