
    |h%                         d dl Z d dlmZ d dlmZmZ d dlZd dlm	Z	 d dl
mZ d dlmZ d dlmZ d dlmZ d d	lmZ d
e j(                  d<    G d d      Z G d d      Zy)    N)Path)AnyList)Image)IMG_FORMATS)build_text_model)LOGGER)check_requirements)select_deviceTRUEKMP_DUPLICATE_LIB_OKc            
           e Zd ZdZdeddfdZdedej                  fdZ	de
dej                  fd	Zdd
Zdde
dededee
   fdZde
dee
   fdZy)VisualAISearcha!  
    A semantic image search system that leverages OpenCLIP for generating high-quality image and text embeddings and
    FAISS for fast similarity-based retrieval.

    This class aligns image and text embeddings in a shared semantic space, enabling users to search large collections
    of images using natural language queries with high accuracy and speed.

    Attributes:
        data (str): Directory containing images.
        device (str): Computation device, e.g., 'cpu' or 'cuda'.
        faiss_index (str): Path to the FAISS index file.
        data_path_npy (str): Path to the numpy file storing image paths.
        data_dir (Path): Path object for the data directory.
        model: Loaded CLIP model.
        index: FAISS index for similarity search.
        image_paths (List[str]): List of image file paths.

    Methods:
        extract_image_feature: Extract CLIP embedding from an image.
        extract_text_feature: Extract CLIP embedding from text.
        load_or_build_index: Load existing FAISS index or build new one.
        search: Perform semantic search for similar images.

    Examples:
        Initialize and search for images
        >>> searcher = VisualAISearch(data="path/to/images", device="cuda")
        >>> results = searcher.search("a cat sitting on a chair", k=10)
    kwargsreturnNc                    t        d       t        d      | _        d| _        d| _        t        |j                  dd            | _        t        |j                  dd            | _	        | j                  j                         sOd	d
lm} t        j                  | j                   d| d       d	dlm}  || ddd       t        d      | _        t#        d| j                        | _        d| _        g | _        | j+                          y)zDInitialize the VisualAISearch class with FAISS index and CLIP model.z	faiss-cpufaisszfaiss.indexz	paths.npydataimagesdevicecpur   )
ASSETS_URLz( not found. Downloading images.zip from z/images.zip)safe_downloadT   )urlunzipretryzclip:ViT-B/32)r   N)r
   
__import__r   faiss_indexdata_path_npyr   getdata_dirr   r   existsultralytics.utilsr   r	   warningultralytics.utils.downloadsr   r   modelindeximage_pathsload_or_build_index)selfr   r   r   s       f/var/www/html/test/engine/venv/lib/python3.12/site-packages/ultralytics/solutions/similarity_search.py__init__zVisualAISearch.__init__1   s    ;'(
((VZZ9:#FJJx$?@}}##%4NNdmm_,TU_T``klmAK8AN NDM%odkkJ

  "    pathc                     | j                   j                  t        j                  |            j	                         j                         S )z7Extract CLIP image embedding from the given image path.)r'   encode_imager   openr   numpy)r+   r/   s     r,   extract_image_featurez$VisualAISearch.extract_image_featureK   s2    zz&&uzz$'78<<>DDFFr.   textc                     | j                   j                  | j                   j                  |g            j                         j	                         S )z6Extract CLIP text embedding from the given text query.)r'   encode_texttokenizer   r3   )r+   r5   s     r,   extract_text_featurez#VisualAISearch.extract_text_featureO   s:    zz%%djj&9&94&&ABFFHNNPPr.   c                    t        | j                        j                         rt        | j                        j                         rdt	        j
                  d       | j                  j                  | j                        | _        t        j                  | j                        | _        yt	        j
                  d       g }| j                  j                         D ]x  }|j                  j                         j!                  d      t"        vr3	 |j%                  | j'                  |             | j                  j%                  |j(                         z |st/        d      t        j0                  |      j3                  d      }| j                  j5                  |       | j                  j7                  |j8                  d	         | _        | j                  j;                  |       | j                  j=                  | j                  | j                         t        j>                  | j                  t        j@                  | j                               t	        j
                  d
tC        | j                         d       y# t*        $ r0}t	        j,                  d|j(                   d|        Y d}~d}~ww xY w)an  
        Load existing FAISS index or build a new one from image features.

        Checks if FAISS index and image paths exist on disk. If found, loads them directly. Otherwise, builds a new
        index by extracting features from all images in the data directory, normalizes the features, and saves both the
        index and image paths for future use.
        zLoading existing FAISS index...Nz#Building FAISS index from images....z	Skipping z: z'No image embeddings could be generated.float32   zIndexed z images.)"r   r   r#   r    r	   infor   
read_indexr(   nploadr)   r"   iterdirsuffixlowerlstripr   appendr4   name	Exceptionr%   RuntimeErrorvstackastypenormalize_L2IndexFlatIPshapeaddwrite_indexsavearraylen)r+   vectorsfilees       r,   r*   z"VisualAISearch.load_or_build_indexS   s      !((*tD4F4F/G/N/N/PKK9:..t/?/?@DJ!wwt'9'9:D 	9: MM))+ 		=D{{  "))#.kA=t99$?@  ''		2		= HII))G$++I6

(ZZ++GMM!,<=


w

tzz4+;+;<
""BHHT-=-=$>?hs4#3#345X>?  =499+Rs;<<=s   AJ	J>%J99J>queryksimilarity_threshc           	      $   | j                  |      j                  d      }| j                  j                  |       | j                  j                  ||      \  }}t        |d         D cg c]1  \  }}|d   |   |k\  s| j                  |   t        |d   |         f3 }	}}|	j                  d d       t        j                  d       |	D ]!  \  }
}t        j                  d|
 d|d	       # |	D cg c]  }|d   	 c}S c c}}w c c}w )
au  
        Return top-k semantically similar images to the given query.

        Args:
            query (str): Natural language text query to search for.
            k (int, optional): Maximum number of results to return.
            similarity_thresh (float, optional): Minimum similarity threshold for filtering results.

        Returns:
            (List[str]): List of image filenames ranked by similarity score.

        Examples:
            Search for images matching a query
            >>> searcher = VisualAISearch(data="images")
            >>> results = searcher.search("red car", k=5, similarity_thresh=0.2)
        r<   r   c                     | d   S )Nr=    )xs    r,   <lambda>z'VisualAISearch.search.<locals>.<lambda>   s
    1Q4 r.   T)keyreversez
Ranked Results:z  - z | Similarity: z.4f)r9   rK   r   rL   r(   search	enumerater)   floatsortr	   r>   )r+   rW   rX   rY   	text_featDr(   idxiresultsrG   scorers                r,   ra   zVisualAISearch.search   s   " --e4;;IF	

	*::$$Y25BKERSHBU
8>QYZ[\Y]^aYbfwYwTa %!S	"23
 
 	6'(" 	AKD%KK$tfOE#;?@	A &&!&&
 's   ,D "D8Dc                 $    | j                  |      S )z.Direct call interface for the search function.)ra   )r+   rW   s     r,   __call__zVisualAISearch.__call__   s    {{5!!r.   )r   N)   g?)__name__
__module____qualname____doc__r   r-   r   r@   ndarrayr4   strr9   r*   intrc   r   ra   rm   r\   r.   r,   r   r      s    :# # #4G$ G2:: GQ Q Q+@Z'C 'C ' 'QUVYQZ '@"c "d3i "r.   r   c                   D    e Zd ZdZd
dededdfdZdefdZddeddfd	Zy)	SearchAppa  
    A Flask-based web interface for semantic image search with natural language queries.

    This class provides a clean, responsive frontend that enables users to input natural language queries and
    instantly view the most relevant images retrieved from the indexed database.

    Attributes:
        render_template: Flask template rendering function.
        request: Flask request object.
        searcher (VisualAISearch): Instance of the VisualAISearch class.
        app (Flask): Flask application instance.

    Methods:
        index: Process user queries and display search results.
        run: Start the Flask web application.

    Examples:
        Start a search application
        >>> app = SearchApp(data="path/to/images", device="cuda")
        >>> app.run(debug=True)
    Nr   r   r   c                    t        d       ddlm}m}m} || _        || _        t        ||      | _         |t        dt        |      j                         d      | _
        | j                  j                  d| j                  d	d
g       y)a  
        Initialize the SearchApp with VisualAISearch backend.

        Args:
            data (str, optional): Path to directory containing images to index and search.
            device (str, optional): Device to run inference on (e.g. 'cpu', 'cuda').
        zflask>=3.0.1r   )Flaskrender_templaterequest)r   r   	templatesz/images)template_folderstatic_folderstatic_url_path/GETPOST)	view_funcmethodsN)r
   flaskry   rz   r{   r   searcherro   r   resolveappadd_url_ruler(   )r+   r   r   ry   rz   r{   s         r,   r-   zSearchApp.__init__   sw     	>*99.&D@'t*,,.%	
 	cTZZ%Qr.   c                     g }| j                   j                  dk(  rE| j                   j                  j                  dd      j	                         }| j                  |      }| j                  d|      S )zCProcess user query and display search results in the web interface.r   rW    zsimilarity-search.html)ri   )r{   methodformr!   stripr   rz   )r+   ri   rW   s      r,   r(   zSearchApp.index   sc    <<&(LL%%))'26<<>EmmE*G##$<g#NNr.   debugc                 <    | j                   j                  |       y)z'Start the Flask web application server.)r   N)r   run)r+   r   s     r,   r   zSearchApp.run   s    5!r.   )r   N)F)	ro   rp   rq   rr   rt   r-   r(   boolr   r\   r.   r,   rw   rw      sF    ,RS RS RD R,Os O" "$ "r.   rw   )ospathlibr   typingr   r   r3   r@   PILr   ultralytics.data.utilsr   ultralytics.nn.text_modelr   r$   r	   ultralytics.utils.checksr
   ultralytics.utils.torch_utilsr   environr   rw   r\   r.   r,   <module>r      sK    
     . 6 $ 7 7%+

! "O" O"d7" 7"r.   