
    .h                    Z    d dl mZ d dlmZ d dlZd dlmZmZm	Z	 d dl
mZ  G d de      Zy)    )annotations)AnyN)BaseSolutionSolutionAnnotatorSolutionResults)colorsc                  N     e Zd ZdZd fdZ	 	 	 	 	 	 	 	 	 	 ddZd ZddZ xZS )	RegionCountera  
    A class for real-time counting of objects within user-defined regions in a video stream.

    This class inherits from `BaseSolution` and provides functionality to define polygonal regions in a video frame,
    track objects, and count those objects that pass through each defined region. Useful for applications requiring
    counting in specified areas, such as monitoring zones or segmented sections.

    Attributes:
        region_template (dict): Template for creating new counting regions with default attributes including name,
            polygon coordinates, and display colors.
        counting_regions (list): List storing all defined regions, where each entry is based on `region_template`
            and includes specific region settings like name, coordinates, and color.
        region_counts (dict): Dictionary storing the count of objects for each named region.

    Methods:
        add_region: Add a new counting region with specified attributes.
        process: Process video frames to count objects in each region.
        initialize_regions: Initialize zones to count the objects in each one. Zones could be multiple as well.

    Examples:
        Initialize a RegionCounter and add a counting region
        >>> counter = RegionCounter()
        >>> counter.add_region("Zone1", [(100, 100), (200, 100), (200, 200), (100, 200)], (255, 0, 0), (255, 255, 255))
        >>> results = counter.process(frame)
        >>> print(f"Total tracks: {results.total_tracks}")
    c                z    t        |   di | dddddd| _        i | _        g | _        | j                          y)zSInitialize the RegionCounter for real-time object counting in user-defined regions.zDefault RegionNr      r   r   )r   r   r   )namepolygoncountsregion_color
text_color )super__init__region_templateregion_countscounting_regionsinitialize_regions)selfkwargs	__class__s     b/var/www/html/ai-service/venv/lib/python3.12/site-packages/ultralytics/solutions/region_counter.pyr   zRegionCounter.__init__)   sJ    "6"$+# 
   "!    c                    | j                   j                         }|j                  || j                  |      ||d       | j                  j                  |       |S )aM  
        Add a new region to the counting list based on the provided template with specific attributes.

        Args:
            name (str): Name assigned to the new region.
            polygon_points (list[tuple]): List of (x, y) coordinates defining the region's polygon.
            region_color (tuple[int, int, int]): BGR color for region visualization.
            text_color (tuple[int, int, int]): BGR color for the text within the region.

        Returns:
            (dict[str, any]): Returns a dictionary including the region information i.e. name, region_color etc.
        )r   r   r   r   )r   copyupdatePolygonr   append)r   r   polygon_pointsr   r   regions         r   
add_regionzRegionCounter.add_region7   sY    & %%**,<<7 ,(		
 	$$V,r   c           	     \   | j                   | j                          t        | j                   t              sd| j                   i| _         t	        | j                   j                               D ]=  \  }\  }}| j                  ||t        |d      d      }| j                  |d         |d<   ? y)zInitialize regions only once.Nz	Region#01Tr   r   prepared_polygon)	r%   initialize_region
isinstancedict	enumerateitemsr&   r   prep)r   ir   ptsr%   s        r   r   z RegionCounter.initialize_regionsV   s    ;;""$$++t,&4DK'(9(9(;< 	FNA{c__T3q$QF)-6)3D)EF%&	Fr   c           
        | j                  |       t        || j                        }t        | j                  | j
                  | j                  | j                        D ]  \  }}}}|j                  || j                  |||      t        |d             | j                  |d   |d   z   dz  |d   |d   z   dz  f      }| j                  D ]9  }|d   j                  |      s|d	xx   dz  cc<   |d	   | j                  |d
   <   ;  | j                  D ]  }|d   }	t        t!        t"        t%        j&                  |	j(                  j*                  t$        j,                                    }
t/        |	j0                  j2                        t/        |	j0                  j4                        fgdz  \  \  }}\  }}|j7                  |
|d   | j                  dz         |j9                  ||||gt;        |d	         |d   |d   | j                  dz  d       d|d	<    |j=                         }| j?                  |       tA        |tC        | j                        | j                        S )a  
        Process the input frame to detect and count objects within each defined region.

        Args:
            im0 (np.ndarray): Input image frame where objects and regions are annotated.

        Returns:
            (SolutionResults): Contains processed image `plot_im`, 'total_tracks' (int, total number of tracked objects),
                and 'region_counts' (dict, counts of objects per region).
        )
line_widthT)labelcolorr            r(   r   r   r   )dtyper   r      rect)r3   r4   	txt_colormarginshape)plot_imtotal_tracksr   )"extract_tracksr   r2   zipboxesclss	track_idsconfs	box_labeladjust_box_labelr   Pointr   containsr   listmaptuplenparrayexteriorcoordsint32intcentroidxydraw_regionadaptive_labelstrresultdisplay_outputr   len)r   im0	annotatorboxclstrack_idconfcenterr%   polyr0   x1y1x2y2r>   s                   r   processzRegionCounter.process`   sK    	C %cdooF	(+DJJ		4>>SWS]S](^ 	J$Ch4+@+@dH+U]cdlnr]stZZ#a&3q6/Q!6Q#a&A8M NOF// J,-66v>8$)$9?9ID&&vf~6J	J ++ 	!F)$Ds5"((4==+?+?rxx"PQRC#&t}}#7T]]__9M"N!ORS!SHRhr2!!#vn'=tQR?RS$$RR &*+^, .* %   !F8	! ""$G$wS=P`d`r`rssr   )r   r   returnNone)
r   rX   r$   zlist[tuple]r   tuple[int, int, int]r   rk   ri   zdict[str, Any])r\   z
np.ndarrayri   r   )	__name__
__module____qualname____doc__r   r&   r   rh   __classcell__)r   s   @r   r
   r
      sN    6" $ +	
 ) 
>F(tr   r
   )
__future__r   typingr   numpyrM   ultralytics.solutions.solutionsr   r   r   ultralytics.utils.plottingr   r
   r   r   r   <module>rv      s)    #   \ \ -{tL {tr   