#@ ImagePlus (Label="Template image") template #@ ImagePlus (Label="Target image") image #@ Boolean (Label="Flip template vertically") flipv #@ Boolean (Label="Flip template horizontally") fliph #@ String (Label="Additional rotation angles separated by ," ,required=False) angles #@ String (Label="Matching method",choices={"Normalised Square Difference","Normalised cross-correlation","Normalised 0-mean cross-correlation"}, value="0-mean normalised cross-correlation") method #@ int (Label="Expected number of templates", min=1) n_hit #@ String (visibility="MESSAGE", value="The parameters below are used only if the template is flipped/rotated and/or more than 1 template are expected in the image") doc #@ Float (Label="Score Threshold (0-1)", min=0, max=1, value=0.5, stepSize=0.1) score_threshold #@ Float (Label="Min height for maxima detection relative to neighbourhood (0-1, decrease to get more hits)", min=0, max=1, value=0.1, stepSize=0.1) tolerance #@ Float (Label="Maximal overlap between Bounding boxes (0-1)",min=0, max=1, value=0.4, stepSize=0.1) max_overlap #@ String (visibility="MESSAGE", value="Output") out #@ Boolean (Label="Display image with found ROI") show_roi #@ Boolean (Label="Show result table") show_table ''' previous parameter removed : Boolean (Label="Display correlation map(s)") show_map # Complicated, showing several correlation map with each variation of the template Requires ImageJ 1.52i to have the possibilityy to fill the background while rotating for 16-bit images FIJI macro to do template matching input : - template : ImagePlus for the template - image : ImagePlus for the target image ie this macro search for one template (with eventual flipped/rotated version)into one target image. The 2 images should be already open in Fiji. First of all, additionnal versions of the template are generated (flip+rotation) For the resulting list of templates the search is carried out and results in a list of correlation maps Minima/maxima in the correlation map are detected, followed by Non-Maxima Supression in case of multiple correlation map/templates The multifile input is not yet macro recordable. An alternative is to use a folder input and to process the content of the folder (but not as flexible) TO DO : - order of the column in result table - use steerable tempalte matching see steerable detector BIG Lausanne NB : - Delete the previous ROI for every new Run otherwise 1st ROI is used to limit the search - Method limited to normalised method to have correlation map in range 0-1 : easier to apply a treshold. Otherwise normalising relative to maxima of each correlation map is not good since this result in having the global maxima to always be one, eventhough its correlation value was not one. Another possibility would be to have an absolute threshold (realtive to the correlation score) and a relative threshold (relative to the maxima of this particular map) ''' from ij import IJ ## Import HomeMade modules from ROIdetection.NonMaximaSupression_Py2 import NMS #from ROIdetection.SearchRoi import getSearchRoi from ROIdetection.MatchTemplate_Module import getHit_Template, CornerToCenter # Convert method string to the opencv corresponding index Dico_Method = {"Square difference":0,"Normalised Square Difference":1,"Cross-Correlation":2,"Normalised cross-correlation":3,"0-mean cross-correlation":4,"Normalised 0-mean cross-correlation":5} Method = Dico_Method[method] ## BODY ## # Initialise variable TemplateProc = template.getProcessor() ImageProc = image.getProcessor() ImageName = image.getTitle() # Do the processing Hits_BeforeNMS = getHit_Template(TemplateProc, ImageProc, flipv, fliph, angles, Method, n_hit, score_threshold, tolerance) ### NMS inter template print "\n-- Hits before NMS --\n", for hit in Hits_BeforeNMS : print hit # NMS if more than one hit if len(Hits_BeforeNMS)==1: Hits_AfterNMS = Hits_BeforeNMS elif Method in [0,1]: Hits_AfterNMS = NMS(Hits_BeforeNMS, N=n_hit, maxOverlap=max_overlap, sortDescending=False) # only difference is the sorting else: Hits_AfterNMS = NMS(Hits_BeforeNMS, N=n_hit, maxOverlap=max_overlap, sortDescending=True) print "\n-- Hits after NMS --\n" for hit in Hits_AfterNMS : print hit ### Initialise outputs ### if show_table: from ij.measure import ResultsTable from utils import AddToTable Table = ResultsTable().getResultsTable() # allows to append to an existing table if show_roi: from ij.plugin.frame import RoiManager from ij.gui import Roi RM = RoiManager() rm = RM.getInstance() # Loop over final hits to generate ROI for hit in Hits_AfterNMS: if show_roi: roi = Roi(*hit['BBox']) roi.setName(hit['TemplateName']) rm.addRoi(roi) #image.setRoi(roi) if show_table: Xcorner, Ycorner = hit['BBox'][0], hit['BBox'][1] Xcenter, Ycenter = CornerToCenter(Xcorner, Ycorner, hit['BBox'][2], hit['BBox'][3]) Dico = {'Image':ImageName, 'Template':hit['TemplateName'] ,'Xcorner':Xcorner, 'Ycorner':Ycorner, 'Xcenter':Xcenter, 'Ycenter':Ycenter, 'Score':hit['Score']} AddToTable(Table, Dico, Order=("Image", "Template", "Score", "Xcorner", "Ycorner", "Xcenter", "Ycenter")) # Display result table if show_table: Table.show("Results") if show_roi: # Show All ROI + Associate ROI to slices rm.runCommand("Associate", "true") rm.runCommand("Show All with labels") # Bring image to the front IJ.selectWindow(ImageName)