
    jO              
       Z   d dl Zd dlmZ d dlmZ d dlmZ g dZdedede	e
e
e
e
f         fd	Z G d
 d          Zdej        dej        dej        fdZdej        dej        dej        fdZddej        dedee         fdZ G d d          Z G d d          Z G d d          ZdS )    N)anyascii)linear_sum_assignmentPolygon)	TextMatchbox_ioupolygon_iounmsLocalizationConfusion	OCRMetricDetectionMetricword1word2returnc                 6   | |k    }|                                  |                                 k    }t          |           t          |          k    }t          |                                            t          |                                           k    }||||fS )aW  Performs string comparison with multiple levels of tolerance

    Args:
        word1: a string
        word2: another string

    Returns:
        a tuple with booleans specifying respectively whether the raw strings, their lower-case counterparts, their
            anyascii counterparts and their lower-case anyascii counterparts match
    )lowerr   )r   r   	raw_matchcaseless_matchanyascii_matchunicase_matchs         V/var/www/html/Carbon-Document/venv/lib/python3.11/site-packages/doctr/utils/metrics.pystring_matchr      s|     I[[]]ekkmm3Ne__7N UOO))++x/D/D/F/FFMnnmCC    c                   j    e Zd ZdZd
dZdee         dee         ddfdZdeee	f         fdZ
d
d	ZdS )r   a;  Implements text match metric (word-level accuracy) for recognition task.

    The raw aggregated metric is computed as follows:

    .. math::
        \forall X, Y \in \mathcal{W}^N,
        TextMatch(X, Y) = \frac{1}{N} \sum\limits_{i=1}^N f_{Y_i}(X_i)

    with the indicator function :math:`f_{a}` defined as:

    .. math::
        \forall a, x \in \mathcal{W},
        f_a(x) = \left\{
            \begin{array}{ll}
                1 & \mbox{if } x = a \\
                0 & \mbox{otherwise.}
            \end{array}
        \right.

    where :math:`\mathcal{W}` is the set of all possible character sequences,
    :math:`N` is a strictly positive integer.

    >>> from doctr.utils import TextMatch
    >>> metric = TextMatch()
    >>> metric.update(['Hello', 'world'], ['hello', 'world'])
    >>> metric.summary()
    r   Nc                 .    |                                   d S N)resetselfs    r   __init__zTextMatch.__init__I   s    

r   gtpredc                    t          |          t          |          k    rt          d          t          ||          D ]\  }}t          ||          \  }}}}| xj        t          |          z  c_        | xj        t          |          z  c_        | xj        t          |          z  c_        | xj        t          |          z  c_        | xj	        t          |          z  c_	        dS )zUpdate the state of the metric with new predictions

        Args:
            gt: list of groung-truth character sequences
            pred: list of predicted character sequences
        z<prediction size does not match with ground-truth labels sizeN)
lenAssertionErrorzipr   rawintcaselessr   unicasetotal)	r   r!   r"   gt_word	pred_word_raw	_caseless	_anyascii_unicases	            r   updatezTextMatch.updateL   s     r77c$ii !_```"%b$-- 	* 	*GY3?3S3S0D)YHHD		!HHMMS^^+MMMMS^^+MMLLCMM)LLL

c"gg



r   c                     | j         dk    rt          d          t          | j        | j         z  | j        | j         z  | j        | j         z  | j        | j         z            S )zComputes the aggregated metrics

        Returns:
            a dictionary with the exact match score for the raw data, its lower-case counterpart, its anyascii
            counterpart and its lower-case anyascii counterpart
        r   z8you need to update the metric before getting the summaryr'   r)   r   r*   )r+   r%   dictr'   r)   r   r*   r   s    r   summaryzTextMatch.summaryc   se     :?? ![\\\4:%]TZ/]TZ/L4:-	
 
 
 	
r   c                 L    d| _         d| _        d| _        d| _        d| _        d S )Nr   )r'   r)   r   r*   r+   r   s    r   r   zTextMatch.resett   s)    


r   r   N)__name__
__module____qualname____doc__r    liststrr2   r5   floatr6   r    r   r   r   r   ,   s         8   I 3i 
	   .
c5j) 
 
 
 
"     r   r   boxes_1boxes_2c                    t          j        | j        d         |j        d         ft           j                  }| j        d         dk    r|j        d         dk    rt          j        | dd          \  }}}}t          j        |dd          \  }}}	}
t          j        ||j                  }t          j        ||j                  }t          j        ||	j                  }t          j        ||
j                  }t          j        ||z
  dt           j	                  t          j        ||z
  dt           j	                  z  }||z
  ||z
  z  |	|z
  |
|z
  z  j        z   |z
  }||z  }|S )a  Computes the IoU between two sets of bounding boxes

    Args:
        boxes_1: bounding boxes of shape (N, 4) in format (xmin, ymin, xmax, ymax)
        boxes_2: bounding boxes of shape (M, 4) in format (xmin, ymin, xmax, ymax)

    Returns:
        the IoU matrix of shape (N, M)
    r   dtype      axis)
npzerosshapefloat32splitmaximumTminimumclipinf)rA   rB   iou_matl1t1r1b1l2t2r2b2lefttoprightbotintersectionunions                    r   r   r   |   sG    (GM!$4gmA6F#GrzZZZG}Q!a 01 4 4'11555BB'11555BBz"bd##jRT""
2rt$$jRT""wut|Q77"'#)QPRPV:W:WWbR"W%"r'b2g)>(AALP&Nr   polys_1polys_2c                    | j         dk    s|j         dk    rt          d          t          j        | j        d         |j        d         ft          j                  }d | D             }d |D             }t          |          D ]P\  }}t          |          D ];\  }}|                    |          j        }	|j        |j        z   |	z
  }
|	|
z  |||f<   <Q|S )a  Computes the IoU between two sets of rotated bounding boxes

    Args:
        polys_1: rotated bounding boxes of shape (N, 4, 2)
        polys_2: rotated bounding boxes of shape (M, 4, 2)
        mask_shape: spatial shape of the intermediate masks
        use_broadcasting: if set to True, leverage broadcasting speedup by consuming more memory

    Returns:
        the IoU matrix of shape (N, M)
       z'expects boxes to be in format (N, 4, 2)r   rD   c                 ,    g | ]}t          |          S r@   r   .0polys     r   
<listcomp>zpolygon_iou.<locals>.<listcomp>       999wt}}999r   c                 ,    g | ]}t          |          S r@   r   rh   s     r   rk   zpolygon_iou.<locals>.<listcomp>   rl   r   )	ndimr%   rJ   rK   rL   rM   	enumeratera   area)rc   rd   rT   shapely_polys_1shapely_polys_2ipoly1jpoly2intersection_area
union_areas              r   r	   r	      s     |qGLA--FGGGha('-*:;2:NNNG99999O99999Oo.. ; ;5!/22 	; 	;HAu % 2 25 9 9 >ej03DDJ-
:GAqDMM	;
 Nr         ?boxesthreshc                 ~   | dddf         }| dddf         }| dddf         }| dddf         }| dddf         }||z
  ||z
  z  }|                                 ddd         }g }	|j        dk    rJ|d         }
|	                    |
           t          j        ||
         ||dd                            }t          j        ||
         ||dd                            }t          j        ||
         ||dd                            }t          j        ||
         ||dd                            }t          j        d||z
            }t          j        d||z
            }||z  }|||
         ||dd                  z   |z
  z  }t          j        ||k              d         }||dz            }|j        dk    J|	S )	a(  Perform non-max suppression, borrowed from <https://github.com/rbgirshick/fast-rcnn>`_.

    Args:
        boxes: np array of straight boxes: (*, 5), (xmin, ymin, xmax, ymax, score)
        thresh: iou threshold to perform box suppression.

    Returns:
        A list of box indexes to keep
    Nr   rG      rf   rF           )argsortsizeappendrJ   rO   rQ   where)rz   r{   x1y1x2y2scoresareasorderkeeprs   xx1yy1xx2yy2whinterovrindss                       r   r
   r
      s    
qqq!tB	qqq!tB	qqq!tB	qqq!tB111a4[F"Wb!ENNTTrT"ED
*q..!HAjA59..jA59..jA59..jA59..JsC#I&&JsC#I&&AuQx%abb	"22U:;xv&&q)dQh *q.. Kr   c                       e Zd ZdZ	 	 ddededdfdZd	ej        d
ej        ddfdZ	de
edz  edz  edz  f         fdZddZdS )r   a   Implements common confusion metrics and mean IoU for localization evaluation.

    The aggregated metrics are computed as follows:

    .. math::
        \forall Y \in \mathcal{B}^N, \forall X \in \mathcal{B}^M, \\
        Recall(X, Y) = \frac{1}{N} \sum\limits_{i=1}^N g_{X}(Y_i) \\
        Precision(X, Y) = \frac{1}{M} \sum\limits_{i=1}^M g_{X}(Y_i) \\
        meanIoU(X, Y) = \frac{1}{M} \sum\limits_{i=1}^M \max\limits_{j \in [1, N]}  IoU(X_i, Y_j)

    with the function :math:`IoU(x, y)` being the Intersection over Union between bounding boxes :math:`x` and
    :math:`y`, and the function :math:`g_{X}` defined as:

    .. math::
        \forall y \in \mathcal{B},
        g_X(y) = \left\{
            \begin{array}{ll}
                1 & \mbox{if } y\mbox{ has been assigned to any }(X_i)_i\mbox{ with an }IoU \geq 0.5 \\
                0 & \mbox{otherwise.}
            \end{array}
        \right.

    where :math:`\mathcal{B}` is the set of possible bounding boxes,
    :math:`N` (number of ground truths) and :math:`M` (number of predictions) are strictly positive integers.

    >>> import numpy as np
    >>> from doctr.utils import LocalizationConfusion
    >>> metric = LocalizationConfusion(iou_thresh=0.5)
    >>> metric.update(np.asarray([[0, 0, 100, 100]]), np.asarray([[0, 0, 70, 70], [110, 95, 200, 150]]))
    >>> metric.summary()

    Args:
        iou_thresh: minimum IoU to consider a pair of prediction and ground truth as a match
        use_polygons: if set to True, predictions and targets will be expected to have rotated format
    ry   F
iou_threshuse_polygonsr   Nc                 J    || _         || _        |                                  d S r   r   r   r   r   r   r   s      r   r    zLocalizationConfusion.__init__   $    
 %(

r   gtspredsc                    |j         d         dk    r| j        rt          ||          }nt          ||          }| xj        t          |                    d                                                    z  c_        t          |           \  }}| xj	        t          |||f         | j        k                                              z  c_	        | xj        |j         d         z  c_        | xj        |j         d         z  c_        dS )a  Updates the metric

        Args:
            gts: a set of relative bounding boxes either of shape (N, 4) or (N, 5) if they are rotated ones
            preds: a set of relative bounding boxes either of shape (M, 4) or (M, 5) if they are rotated ones
        r   rH   N)rL   r   r	   r   tot_iour?   maxsumr   matchesr(   r   num_gts	num_preds)r   r   r   rT   
gt_indicespred_indicess         r   r2   zLocalizationConfusion.update	  s     ;q>A  .%c511!#u--LLE'++1+"5"5"9"9";";<<<LL (=gX'F'F$JLLC\)A!Bdo!U Z Z \ \]]]LL 		!$%+a.(r   c                     | j         dk    r| j        | j         z  nd}| j        dk    r| j        | j        z  nd}| j        dk    rt          | j        | j        z  d          nd}|||fS )z|Computes the aggregated metrics

        Returns:
            a tuple with the recall, precision and meanIoU scores
        r   Nr}   )r   r   r   roundr   r   recall	precisionmean_ious       r   r6   zLocalizationConfusion.summary   s~     15q0@0@,,d 6:^a5G5GDL4>11T	 ?Cnq>P>P56:::VZy(**r   c                 >    d| _         d| _        d| _        d| _        d S Nr   r   )r   r   r   r   r   s    r   r   zLocalizationConfusion.reset1  s"    r   ry   Fr8   r9   r:   r;   r<   r?   boolr    rJ   ndarrayr2   tupler6   r   r@   r   r   r   r      s        " "L  "   
	   )"* )RZ )D ) ) ) ).+ut|UT\54<GH + + + +"     r   r   c            
           e Zd ZdZ	 	 ddededdfdZd	ej        d
ej        de	e
         de	e
         ddf
dZdeee
edz  f         ee
edz  f         edz  f         fdZddZdS )r   a\  Implements an end-to-end OCR metric.

    The aggregated metrics are computed as follows:

    .. math::
        \forall (B, L) \in \mathcal{B}^N \times \mathcal{L}^N,
        \forall (\hat{B}, \hat{L}) \in \mathcal{B}^M \times \mathcal{L}^M, \\
        Recall(B, \hat{B}, L, \hat{L}) = \frac{1}{N} \sum\limits_{i=1}^N h_{B,L}(\hat{B}_i, \hat{L}_i) \\
        Precision(B, \hat{B}, L, \hat{L}) = \frac{1}{M} \sum\limits_{i=1}^M h_{B,L}(\hat{B}_i, \hat{L}_i) \\
        meanIoU(B, \hat{B}) = \frac{1}{M} \sum\limits_{i=1}^M \max\limits_{j \in [1, N]}  IoU(\hat{B}_i, B_j)

    with the function :math:`IoU(x, y)` being the Intersection over Union between bounding boxes :math:`x` and
    :math:`y`, and the function :math:`h_{B, L}` defined as:

    .. math::
        \forall (b, l) \in \mathcal{B} \times \mathcal{L},
        h_{B,L}(b, l) = \left\{
            \begin{array}{ll}
                1 & \mbox{if } b\mbox{ has been assigned to a given }B_j\mbox{ with an } \\
                & IoU \geq 0.5 \mbox{ and that for this assignment, } l = L_j\\
                0 & \mbox{otherwise.}
            \end{array}
        \right.

    where :math:`\mathcal{B}` is the set of possible bounding boxes,
    :math:`\mathcal{L}` is the set of possible character sequences,
    :math:`N` (number of ground truths) and :math:`M` (number of predictions) are strictly positive integers.

    >>> import numpy as np
    >>> from doctr.utils import OCRMetric
    >>> metric = OCRMetric(iou_thresh=0.5)
    >>> metric.update(np.asarray([[0, 0, 100, 100]]), np.asarray([[0, 0, 70, 70], [110, 95, 200, 150]]),
    >>>               ['hello'], ['hello', 'world'])
    >>> metric.summary()

    Args:
        iou_thresh: minimum IoU to consider a pair of prediction and ground truth as a match
        use_polygons: if set to True, predictions and targets will be expected to have rotated format
    ry   Fr   r   r   Nc                 J    || _         || _        |                                  d S r   r   r   s      r   r    zOCRMetric.__init__a  r   r   gt_boxes
pred_boxes	gt_labelspred_labelsc                    |j         d         t          |          k    s|j         d         t          |          k    rt          d          |j         d         dk    rH| j        rt	          ||          }nt          ||          }| xj        t          |                    d          	                                          z  c_        t          |           \  }}|||f         | j        k    }t          ||         ||                   D ]\  }	}
t          ||	         ||
                   \  }}}}| xj        t          |          z  c_        | xj        t          |          z  c_        | xj        t          |          z  c_        | xj        t          |          z  c_        | xj        |j         d         z  c_        | xj        |j         d         z  c_        dS )ar  Updates the metric

        Args:
            gt_boxes: a set of relative bounding boxes either of shape (N, 4) or (N, 5) if they are rotated ones
            pred_boxes: a set of relative bounding boxes either of shape (M, 4) or (M, 5) if they are rotated ones
            gt_labels: a list of N string labels
            pred_labels: a list of M string labels
        r   athere should be the same number of boxes and string both for the ground truth and the predictionsrH   N)rL   r$   r%   r   r	   r   r   r?   r   r   r   r   r&   r   raw_matchesr(   caseless_matchesanyascii_matchesunicase_matchesr   r   )r   r   r   r   r   rT   r   r   is_keptgt_idxpred_idxr.   r/   r0   r1   s                  r   r2   zOCRMetric.updatej  s    >!I..*2B12E[IYIY2Y2Y s  
 A""  8%h
;;!(J77LLE'++1+"5"5"9"9";";<<<LL (=gX'F'F$Jj,674?JG$'
7(;\'=R$S$S 6 6 7CIfDUWbckWl7m7m4iH  CII-  %%Y7%%%%Y7%%$$H5$$$q))**1--r   c                 L   t          | j        dk    r| j        | j        z  nd| j        dk    r| j        | j        z  nd| j        dk    r| j        | j        z  nd| j        dk    r| j        | j        z  nd          }t          | j        dk    r| j        | j        z  nd| j        dk    r| j        | j        z  nd| j        dk    r| j        | j        z  nd| j        dk    r| j        | j        z  nd          }| j        dk    rt          | j        | j        z  d          nd}|||fS )zComputes the aggregated metrics

        Returns:
            a tuple with the recall & precision for each string comparison and the mean IoU
        r   Nr4   r}   )	r5   r   r   r   r   r   r   r   r   r   s       r   r6   zOCRMetric.summary  s`    37<!3C3C 4<//=A\A=M=MT*T\99SW=A\A=M=MT*T\99SW;?<!;K;KD(4<77QU	
 
 
 59^a5G5G 4>11T?C~PQ?Q?QT*T^;;W[?C~PQ?Q?QT*T^;;W[=A^a=O=OD(4>99UY	
 
 
	 ?Cnq>P>P56:::VZy(**r   c                 h    d| _         d| _        d| _        d| _        d| _        d| _        d| _        d S r   )r   r   r   r   r   r   r   r   s    r   r   zOCRMetric.reset  s=     ! ! r   r   r8   )r9   r:   r;   r<   r?   r   r    rJ   r   r=   r>   r2   r   r5   r6   r   r@   r   r   r   r   8  s       & &T  "   
	   ).*). J). 9	).
 #Y). 
). ). ). ).V+tC$56S%$,=N8OQVY]Q]]^ + + + +6! ! ! ! ! !r   r   c            
           e Zd ZdZ	 	 ddededdfdZd	ej        d
ej        dej        dej        ddf
dZ	de
edz  edz  edz  f         fdZddZdS )r   a  Implements an object detection metric.

    The aggregated metrics are computed as follows:

    .. math::
        \forall (B, C) \in \mathcal{B}^N \times \mathcal{C}^N,
        \forall (\hat{B}, \hat{C}) \in \mathcal{B}^M \times \mathcal{C}^M, \\
        Recall(B, \hat{B}, C, \hat{C}) = \frac{1}{N} \sum\limits_{i=1}^N h_{B,C}(\hat{B}_i, \hat{C}_i) \\
        Precision(B, \hat{B}, C, \hat{C}) = \frac{1}{M} \sum\limits_{i=1}^M h_{B,C}(\hat{B}_i, \hat{C}_i) \\
        meanIoU(B, \hat{B}) = \frac{1}{M} \sum\limits_{i=1}^M \max\limits_{j \in [1, N]}  IoU(\hat{B}_i, B_j)

    with the function :math:`IoU(x, y)` being the Intersection over Union between bounding boxes :math:`x` and
    :math:`y`, and the function :math:`h_{B, C}` defined as:

    .. math::
        \forall (b, c) \in \mathcal{B} \times \mathcal{C},
        h_{B,C}(b, c) = \left\{
            \begin{array}{ll}
                1 & \mbox{if } b\mbox{ has been assigned to a given }B_j\mbox{ with an } \\
                & IoU \geq 0.5 \mbox{ and that for this assignment, } c = C_j\\
                0 & \mbox{otherwise.}
            \end{array}
        \right.

    where :math:`\mathcal{B}` is the set of possible bounding boxes,
    :math:`\mathcal{C}` is the set of possible class indices,
    :math:`N` (number of ground truths) and :math:`M` (number of predictions) are strictly positive integers.

    >>> import numpy as np
    >>> from doctr.utils import DetectionMetric
    >>> metric = DetectionMetric(iou_thresh=0.5)
    >>> metric.update(np.asarray([[0, 0, 100, 100]]), np.asarray([[0, 0, 70, 70], [110, 95, 200, 150]]),
    >>>               np.zeros(1, dtype=np.int64), np.array([0, 1], dtype=np.int64))
    >>> metric.summary()

    Args:
        iou_thresh: minimum IoU to consider a pair of prediction and ground truth as a match
        use_polygons: if set to True, predictions and targets will be expected to have rotated format
    ry   Fr   r   r   Nc                 J    || _         || _        |                                  d S r   r   r   s      r   r    zDetectionMetric.__init__  r   r   r   r   r   r   c                    |j         d         |j         d         k    s|j         d         |j         d         k    rt          d          |j         d         dk    r| j        rt          ||          }nt	          ||          }| xj        t          |                    d                                                    z  c_        t          |           \  }}|||f         | j
        k    }| xj        t          |||                  |||                  k                                              z  c_        | xj        |j         d         z  c_        | xj        |j         d         z  c_        dS )a  Updates the metric

        Args:
            gt_boxes: a set of relative bounding boxes either of shape (N, 4) or (N, 5) if they are rotated ones
            pred_boxes: a set of relative bounding boxes either of shape (M, 4) or (M, 5) if they are rotated ones
            gt_labels: an array of class indices of shape (N,)
            pred_labels: an array of class indices of shape (M,)
        r   r   rH   N)rL   r%   r   r	   r   r   r?   r   r   r   r   num_matchesr(   r   r   )	r   r   r   r   r   rT   r   r   r   s	            r   r2   zDetectionMetric.update  sa    >!	 222j6Fq6I[M^_`Ma6a6a s  
 A""  8%h
;;!(J77LLE'++1+"5"5"9"9";";<<<LL (=gX'F'F$Jj,674?JGYz'/B%C{S_`gShGi%i$n$n$p$p q qqq))**1--r   c                     | j         dk    r| j        | j         z  nd}| j        dk    r| j        | j        z  nd}| j        dk    rt          | j        | j        z  d          nd}|||fS )zComputes the aggregated metrics

        Returns:
            a tuple with the recall & precision for each class prediction and the mean IoU
        r   Nr}   )r   r   r   r   r   r   s       r   r6   zDetectionMetric.summary  s     59L14D4D!DL00$ :>!9K9KD$t~55QU	 ?Cnq>P>P56:::VZy(**r   c                 >    d| _         d| _        d| _        d| _        d S r   )r   r   r   r   r   s    r   r   zDetectionMetric.reset#  s%    r   r   r8   r   r@   r   r   r   r     s        & &T  "   
	   $.*$. J$. :	$.
 Z$. 
$. $. $. $.L+ut|UT\54<GH + + + +"     r   r   )ry   )numpyrJ   r   scipy.optimizer   shapely.geometryr   __all__r>   r   r   r   r   r   r   r	   r?   r=   r(   r
   r   r   r   r@   r   r   <module>r      s             0 0 0 0 0 0 $ $ $ $ $ $  D DC DE$dD2H,I D D D D*M M M M M M M M`RZ "*     8 bj RZ    :# #rz #5 #49 # # # #LZ Z Z Z Z Z Z Zz! ! ! ! ! ! ! !Dm m m m m m m m m mr   