def find_grid_positions(match_scores, match_locations, well_size, num_positions): """Find the positions of one axis of a grid, given a set of scores for possible wells and the positions on that axis where those scores were found.""" # match scores and locations are the positions (along just the x or y axis) # of possible wells. If there are 12 rows of wells along that given axis, # then these locations should group into 12 clusters, plus some background # false positives. These false positives likely have lower scores, though. # So: construct a 1-d array that has the well scores at each position. # Then, smooth the array, so that clusters of points will merge together, # and find the highest local maxima of the smoothed array. match_locations = match_locations.round().astype(int) min_loc, max_loc = match_locations.min(), match_locations.max() accumulator = numpy.zeros((max_loc - min_loc + 1), dtype=match_scores.dtype) match_locations -= min_loc for score, loc in zip(match_scores, match_locations): accumulator[loc] += score # NB: above is NOT the same as accumulator[match_locations] += match_scores # because if there are duplicate locations in match_locations, they'll only get # counted once in this formulation, but the for-loop makes sure each gets # accumulated properly. smoothed = ndimage.gaussian_filter1d(accumulator, well_size/5, mode='constant') positions, scores = maxima.find_local_maxima(smoothed, min_distance=well_size/3) positions = positions[:,0] best = scores.argsort()[-num_positions:] return numpy.sort(positions[best]) + min_loc
def find_potential_well_centroids(image, well_mask, well_size): small_image, zoom_factor = downsample_image(image) small_mask = zoom(well_mask, 1/zoom_factor, order=1, output=numpy.float32) small_mask = small_mask > 0.5 small_well_size = well_size / zoom_factor peaks = match_template.match_template(small_image, small_mask, pad_input=True, mode='edge') min_distance = 0.9*small_well_size centroids, match_scores = maxima.find_local_maxima(peaks, min_distance) good_matches = match_scores > 0.05 * match_scores.max() x, y = centroids.T # excludes centroids near the edges radius = small_well_size/2 good_centroids = ((x > radius) & (x < peaks.shape[0] - radius) & (y > radius) & (y < peaks.shape[1] - radius)) centroid_mask = good_matches & good_centroids return match_scores[centroid_mask], centroids[centroid_mask] * zoom_factor