Package: arctic-charr-matcher
Re-identification of individuals from images using spot constellations; a case study in Arctic charr (Salvelinus alpinus)Ignacy T. Dębicki, Elizabeth A. Mittell, Bjarni K. Kristjánsson, Camille A. Leblanc, Michael B. Morrissey, & Kasim TerzićModified by Walker Herndon to transform the code into a python libraryInstructions for installationYou will need to have python and pip installed to use the library. You can check that these are installed by runningpython --versionandpip --versionin the terminal.Depending on how these were installed on your computer you might have to runpython3 --versionandpip3 --versioninstead.If this command lists version number you are good to go, otherwise install Python and Pip now.Mac and LinuxWith both Python and Pip installed, download the installation scriptinstall.sh. Once it is downloaded, run it in the terminal usingsource ./install.sh path/to/your/project. This will take a minute to finish running.Then to use it in a Jupyter Notebook, simply runjupyter notebook, go to localhost:8888/tree in your browser, and create a new notebook file. You will need to select.venvas your kernel. You can then import and use the library as shown below.WindowsWith both Python and Pip installed, download the installation scriptinstall.ps1. Once it is downloaded, run it in the terminal using.\setup_venv.ps1 C:\path\to\your\project. This will take a minute to finish running.Next run the following:cd C:path\to\your\project.venv\Scripts\Activate.ps1jupyter notebookThen to use it in a Jupyter Notebook, simply runjupyter notebook, go to localhost:8888/tree in your browser, and create a new notebook file. You will need to select.venvas your kernel. You can then import and use the library as shown below.Working with virual environmentsUsing virtual environments when working with Python is good practice as it keeps your dependencies separated between different programs. The installation scripts above will automatically create a virtual environment with everything needed for the matcher installed within it. The virtual environment will be created at the path you provide.Comprehensive documentation of Python virtual environments, or “venv” can be foundhere, but the basics are also provided below. You don't need to worry about this when first installing the matcher as the process is done for you, but when you continue working on the project in the future this information will be useful.To create a new virtual environment runpython -m venv /path/to/venvwhere the path can be anywhere you’d like to store the virtual environment. Virtual environment directories are often named something like.venv(the dot at the start makes the folder hidden by default), but you can name it whatever you’d like.To use the venv, first activate it by runningsource <venv>/bin/activatewhere<venv>is the path to the venv given in step 1. This command assumes the shell you are using is bash or ash (bash is the default on Mac and Linux so if that doesn’t mean anything to you, you are almost definitely using bash). If you aren’t using bash or zsh the equivalent command for your shell can be found in the documentation linked above.Now that the venv is activated, when you install a library usingpip install <library>it will be installed within the venv instead of globally. This is why virtual environments are good to keep your dependencies organized.To deactivate the virtual environment again, just rundeactivate.If you have previously run the installation script and want to use the matcher again, just go to the terminal, runcd path/to/your/projectand activate the environment as shown above. Then, just runjupyter notebook.UsageStart by importing some classes from the libraryfromarctic_charr_matcher.MatcherimportMatcherfromarctic_charr_matcherimportDBUtilfromarctic_charr_matcher.algorithmsimportAlgorithmNext, initialize the matchermatcher=Matcher(imgRoot="path/to/images",maskModelWeights="path/to/mask_model.hdf5",spotUnetWeights="path/to/spot_model.hdf5")INCLUDE SOMETHING ABOUT THOSE OTHER PARAMETERS TOOYou'll need to supply the images to work with and the trained models.Creating Image ListDBUtilis used to generate the list of images to be used by the matcher. There are a few options for how to generate the image list which are outlined below. All of these functions return a list ofFishobjects, each of which are associated with one of the fish images. The list ofFishobjects is what the matcher takes in.From sorted imagesIf your images are organized you can provide a date range for the images that should be passed to the matcher. Here's what the file structure for the images needs to look like:└── images/
	├── 2012_June/
	│ ├── Cave1/
	│ │ ├── IMG_001.JPG
	│ │ ├── IMG_002.JPG
	│ │ └── ...
	│ ├── Cave2/
	│ ├── Cave3/
	│ └── ...
	├── 2012_Aug/
	├── 2013_June/
	├── 2013_Aug/
	└── ...Here is an example of usingDBUtil.get_fishto get the list of images:matchingImages=DBUtil.get_fish(21,rootDirs=["path/to/images","path/to/results"],years=range(2015,2018))Here we are loading in the images to match our query image against. There are a few parameters to consider:Cave number:I've picked 21 but it can be any cave you want to run the matcher on.rootDirs:should be the path to the base image directory, and the path to a results directory whichyou will need to create in your project folder if it isn't already there. This directory will hold the image mask and spot files which is what the matcher performs matching on. This should be in the same directory as you are running your script from.years:the range of years you want to include inmatchingImages(first value is inclusive, second is exclusive, so this example is[2015, 2016, 2017])Other parameters:months:defaults to["June", "Aug"]but if your months are different you can provide your own list of months here.firstMonth:defaults to 0, this value is the first index of the months list to use. By default this means it will start with June from the first year in the range provided. Change to 1 to start with Aug instead, or to another number to start with another month in your custom month list.lastMonth:defaults to 1, this is the last index of the months list to use. By default this means it will end on Aug of the last year in the range provided. Change to 0 to end with June instead, or to another number to end with another month in your custom month list.verbose:defaults to False, set to True to print more information when running.From unsorted imagesIf your images are not sorted, or you want to use all images in the directory for matching, you can useDBUtil.get_unsorted_fishinstead.matchingImages=DBUtil.get_unsorted_fish(rootDirs=["path/to/images","path/to/results"])rootDirsis the same as inDBUtil.get_fish.Other parameters:excludeDirs:can be used to provide a list of subdirectories to skip over.verbose:defaults to False, set to True to print more information when running.From specific image pathsIf you want only a select few images, you can provide a list of the paths to those images instead and useDBUtil.get_fish_from_pathsqueryImages=DBUtil.get_fish_from_paths(["path/to/IMG_1234.JPG","path/to/IMG_2468.JPG"],rootDirs=["path/to/images","path/to/results"])Here, we useDBUtil.get_fish_from_pathsto select two images for our query. We also need to provide the root image directories again for the image generation to work properly. This function also has theverboseoption to provide more information when running.MatchingFinally, we can run the matcher:matches=matcher.matching(query_images=queryImages,matching_imgs=matchingImages,rankingLimit=5)Here I have passed in the two query images acquired fromDBUtil.get_fish_from_paths. They are matched against the list of images acquired from eitherDBUtil.get_fishorDBUtil.get_unsorted_fish. We also setrankingLimitto 5 here to limit the results to the best 5 images.This command can take quite a while to run. It will go through every image provided and generate the mask and spot files if they haven't already been created, then attempt to match then with the query image(s). Creating the mask and spot files takes some time and the matching takes some time itself. Subsequent runs will be considerably faster as the mask and spot files are saved, and the matching data is cached.Other parameters:algorithm:this defaults to Algorithm.CUSTOM_GROTH. To use the Astroalign matcher pass in Algorithm.Astroalign instead.verbose:this defaults to False, set to True for more information when running. Usingverbose=Trueis recommended when running the matcher so you can follow the progress at it runs and ensure it is running smoothly. Without this set it may seem like nothing is happening for a while.The results frommatcher.matchingwill be in the form of a list of results for each query. Each result is a dictionary with three elements:"file_name":The unique ID (UUID) of the fish file."ranking":The ranking of the results. In this example with rankingLimit set to 5 this will a value from 1 to 5."score":The 'score' given by the matching algorithm for the image. The higher the score, the more similar the image is to the query. Note that scores from the Groth matcher and Astroalign cannot be compared.To get theFishobject from the UUID of a fish listed in the results useDBUtil.get_fish_from_uuidfishResult=DBUtil.get_fish_from_uuid("image-uuid-here",matchingImages)The first parameter is the UUID of the fish, and the second is the list of Fish objects to search through. This function will return a singleFishobject. The image path can then be attained fromfishResult.image_path.You can also display the image in Jupyter Notebook using IPython.display. This can be installed through pip by runningpip install ipython.fromIPython.displayimportImageImage(fishResult.image_path)This can also be used to display the mask and spot images by doingImage(fishResult.mask_path)orImage(fishResult.spot_path)