Package: deep-search-engine
DeepSearchDeepSearch is a sophisticated AI-powered search engine designed to enhance image searching. It utilizes deep learning algorithms to efficiently search a vast collection of images and find the most similar matches.The DeepSearch engine is built on top of theAnnoylibrary, which is a fast, memory-efficient, and easy-to-use library for approximate nearest-neighbor search.The engine uses pre-trained models fromKerasto extract features from images and then store them in an Annoy index. The index is then used to find the most similar images to a given query image.Table of ContentsFeaturesPrerequisitesInstallation from PyPIInstallation from GitHub RepositoryUsageImporting the DeepSearch classInitializing the DeepSearch classBuilding the indexSaving the indexSearching for similar imagesFull Implementation ExampleCLI UsageSupported ModelsSupported MetricsImpact of Image Quantity on Processing TimeContributingFeaturesFast: DeepSearch is built on top of the Annoy library, which is a fast, memory-efficient, and easy-to-use library for approximate nearest neighbor search.Easy to use: DeepSearch is designed to be easy to use and integrate into your existing applications.High Accuracy: DeepSearch uses a pre-trained model from Keras to extract features from images and then store them in an Annoy index. The index is then used to find the most similar images to a given query image.PrerequisitesPython 3.10.6+ is required to install DeepSearch. You can download the latest version of Python fromhere.You also need to install TensorFlow at least 2.10.1 which can be downloaded fromhere.Installation from PyPIYou can install DeepSearch from the PyPI package repository foundhereTo install DeepSearch, run the following command:pipinstalldeep-search-engineInstallation from GitHub RepositoryYou can also install DeepSearch from the GitHub repository foundhereby cloning the repository and installing the requirements.It is recommended to install DeepSearch in a virtual environment. You can usevirtualenvorvenvto create a virtual environment.To create a virtual environment usingvenv, run the following command:python-mvenvenvTo activate the virtual environment, run the following command:# Windowssourceenv/Scripts/activate# Linuxsourceenv/bin/activateYou will need to install the requirements before you can use DeepSearch. To install the requirements, run the following command:pipinstall-rrequirements.txtWith everything installed, you can now start utilizing DeepSearch.UsageThere are two options for using DeepSearch in your application. You can either use the DeepSearch class and its methods in your code or you can use the DeepSearch CLI.Importing the DeepSearch classFirst, you need to import the DeepSearch class from the DeepSearch module as follows:fromDeepSearchimportDeepSearchInitializing the DeepSearch classThen, you need to create an instance of the DeepSearch class. You can optionally pass the model name, and the number of trees to the constructor, metric, and verbose parameters. The default values are as follows:deepSearch=DeepSearch(model_name='VGG16',n_trees=100,metric='angular',verbose=True)Themodel_nameparameter specifies the name of the model to use for extracting features from images. More information about the supported models can be foundhere.Then_treesparameter specifies the number of trees to use in the Annoy index. The default value is100. More trees will give you better accuracy but will also increase memory usage and search time.Themetricparameter specifies the distance metric to use in the Annoy index. More information about the supported metrics can be foundhere.Theverboseparameter specifies whether to print the progress of the indexing process. The default value isFalse.Building the indexNow, you can build the index and representations by calling thebuild()method. This method requires the path to thedatasetdirectory which contains the images to index as a string.deepSearch.build('dataset')This function will go through all the images in thedatasetdirectory and extract features from them. It will use those features to build the Annoy index and store the indexes and representations in the same directory.You can optionally passmetric,n_treesandmodel_nameparameters to thebuild()method. The default values are the same as the ones you passed to the constructor.This can be useful if you want to try different values for the parameters without creating a new instance of the DeepSearch class.Saving the indexThebuild()method will save the index and representations in the same directory as the images. If you use different values for the parameters, thebuild()method will save the index and representations as a separate file.For example, if you use theVGG16model with theangularmetric and100trees, the index and representations will be saved in theVGG16_angular_100_annoy_index.annandVGG16_angular_100_representations.pklfiles respectively.The saving format is as follows:# Annoy index filef'{model_name}_{metric}_{n_trees}_annoy_index.ann'# Representations filef'{model_name}_{metric}_{n_trees}_representations.pkl'Thepicklemodule is used to save the representations.Searching for similar imagesFinally, you can search for similar images by calling theget_similar_images()method. This method will extract features from the query image and then use them to find the most similar images in the index. You have to specify the path to the query image as a string.You can optionally pass the number of similar images to return as an integer. The default value is 10. You can specify the optional parameterwith_distancesas True to return the distances of similar images as well. The default value of this parameter isFalse.similar_images=deepSearch.get_similar_images('query.jpg',num_results=20,with_distance=True)print(similar_images)The output of theget_similar_images()method is a python list of dictionaries. Each dictionary contains the image index from the index file, the path to the similar image and the distance between the query image and the similar image. The list is sorted by the distance in ascending order (the first image is the most similar).[{'index':0,'path':'images/0.jpg','distance':0.0},{'index':1,'path':'images/1.jpg','distance':0.6206140518188477},{'index':2,'path':'images/2.jpg','distance':0.7063581943511963},...]Full Implementation ExampleThe following example shows how to use DeepSearch in your code. It will index all the images in thedatasetdirectory and then find the most similar images to the query image.fromDeepSearchimportDeepSearch# Initialize the DeepSearch classdeepSearch=DeepSearch(model_name='VGG16',n_trees=100,metric='angular',verbose=True)# Build the index and representationsdeepSearch.build('dataset')# Search for similar imagessimilar_images=deepSearch.get_similar_images('lookup/query.jpg',num_results=20,with_distance=True)# Print the similar imagesprint(similar_images)The full implementation of the example can be found in the DeepSearchDemo.py file.To run the demo, you need to copy the images you want to index to the dataset directory, copy the query image to the lookup directory, and then run the DeepSearchDemo.py file as follows:pythonDeepSearchDemo.pyCLI UsageAnother option for using DeepSearch is to use the DeepSearch CLI. The DeepSearch CLI allows you to use DeepSearch from the command line without writing any code.Before using the DeepSearch CLI, you need to install the DeepSearch package using the following command:pipinstalldeep-search-engineRunning the DeepSearch CLI will build the index and search for similar images. Similar images will then be saved (copied) in a directory which can be specified using the--outputoption or will be saved in theoutputby default. The output directory will be created if it doesn't exist.There are several options you can pass to the DeepSearch CLI. The options are as follows:--folder: The path to the folder containing the images to index. This option is required.--output: The path to the output directory where similar images will be saved. The default value isoutput.--image: The path to the query image. This option is required.--num-results: The number of similar images to return. The default value is 10.--metric: The distance metric to use in the Annoy index. The default value isangular.--n-trees: The number of trees to use in the Annoy index. The default value is 100.--model: The name of the model to use for extracting features from images. The default value isVGG16.--verbose: Whether to print the progress of the indexing process. The default value isFalse.To run the DeepSearch CLI, you need to run the DeepSearchCLI.py file as follows:# Example with required options onlydeep-search-engine--folderdataset--imagelookup/query.jpg# Example with several optionsdeep-search-engine--folderdataset--imagelookup/query.jpg--outputoutput--num_results20--metriceuclidean--n_trees20--modelResNet50--verboseTrueSupported ModelsThe following models are supported:VGG16(default)ResNet50InceptionV3XceptionThe default value isVGG16. You can get a list of available models by calling the staticget_available_models()method of the DeepSearch class as follows:# Get a list of available modelsmodels=DeepSearch.get_available_models()print(models)# ['VGG16', 'ResNet50', 'InceptionV3', 'Xception']The models are case-sensitive and must be specified exactly as shown above.You can easily add support for other models from theKerasApplications library by adding a new model class to themodelsdictionary in theModelLoaderclass.Supported MetricsThe following metrics are supported:angular(default) - The cosine similarity metric.euclidean- The Euclidean distance metric.manhattan- The Manhattan distance metric.hamming- The Hamming distance metric.dot- The dot product metric.The default value isangularwhich is the cosine distance.You can get a list of available metrics by calling the staticget_available_metrics()method of the DeepSearch class as follows:# Get a list of available metricsmetrics=DeepSearch.get_available_metrics()print(metrics)# ['angular', 'euclidean', 'manhattan', 'hamming', 'dot']The metrics are case-sensitive and must be specified exactly as shown above.Impact of Image Quantity on Processing TimeWhen processing a large number of images, it may take longer for the algorithm to generate representations. This is due to the increased computational demands of processing more data (more memory and CPU usage).Once the representations are generated, the search process is very fast. The search process is limited by the number of trees in the Annoy index. The more trees you use, the more accurate the search results will be, but the longer it will take to search.When you run the algorithm for the first time, it will generate the representations and save them to a file. The next time you run the algorithm, it will load the representations from the file instead of generating them again. This will significantly reduce the processing time.For example, I have run the algorithm on a dataset of 100,000 images and the generation of the representations took approximately 12 minutes. Each subsequent run took a couple of seconds which depends on the size of the dataset and the number of trees in the Annoy index.One of the great features is that you can add more images to the dataset and run the algorithm again. The algorithm will only generate representations for the new images and will load the representations for the existing images from the file. This will significantly reduce the processing time.When the image is deleted from the dataset, the algorithm will remove the representation for the image from the file. This will avoid any issues when searching for similar images.Any of these operations will force the algorithm to remove the Annoy index file and generate it again. This will ensure that the Annoy index file is up to date. However, this is a relatively fast operation depending on the size of the dataset and the number of trees in the Annoy index. For the previous example of 100,000 images, the generation of the annoy index file took approximately 3 seconds.You can force the algorithm to remove the representation's file and Annoy index file by passing the--clearoption to the DeepSearch CLI as follows:deep-search-engine--folderdataset--imagelookup/query.jpg--clearTrueOr you can call therebuild()method of the DeepSearch class if you are using the DeepSearch API as follows:# Rebuild the indexdeep_search.rebuild()ContributingIf you would like to contribute to this project, please feel free to submit a pull request. If you have any questions, please feel free to open an issue.