def __init__(self, match, feature1, feature2, detector): self._match = match self._feature1 = feature1 self._feature2 = feature2 self._detector = detector self._offset1 = Point(0, 0) self._offset2 = Point(0, 0) self._point2_projected = None self._included_in_transformation = True
def _calculate_image_positions(self): """ Determine the positions of images 1 and 2 in the background image. """ pad = self._padding w1, h1 = self._image1.size() w2, h2 = self._image2.size() self._image1_position = Point(pad, pad) self._image2_position = Point(2 * pad + w1, pad) if h2 > h1: self._image1_position += Point(0, pad + 0.5 * (h2 - h1)) elif h2 > h1: self._image2_position += Point(0, pad + 0.5 * (h1 - h2))
def __init__(self, image1, image2): self._image1 = image1 self._image2 = image2 self._image1_position = Point(0, 0) self._image2_position = Point(0, 0) self._scale_factor = 1 self._background_image = None self._image_size = self.DEFAULT_IMAGE_SIZE self._padding = self.DEFAULT_PADDING self._back_color = self.DEFAULT_BACK_COLOR self._create_background_image()
def create_overlay_image(image1, image2, offset, rect_color=Color.black()): """ For the two images, A and B, where the position of B is offset from that of A, overlay image B onto image A at the appropriate position. The overlaid area will ve a blending of the two images. A rectangle will be drawn around the area. """ # Make a copy of A, the background image background = image1.copy() # Get overlapping regions of images overlap_a, overlap_b = Overlayer.get_overlap_regions( image1, image2, offset) if overlap_a is None or overlap_b is None: return background # Blend the two overlapping regions perc_a, perc_b = 0.5, 0.5 blended = cv2.addWeighted(overlap_a.raw(), perc_a, overlap_b.raw(), perc_b, 0) background.paste(Image(blended), Point(max(offset.x, 0), max(offset.y, 0))) background = background.to_channels(3) # Define the rectangle that will be pasted to the background image w, h = image2.size() rect = Rectangle.from_corner(offset, w, h) background.draw_rectangle(rect, color=rect_color) return background
def _default_alignment(self): """ Default alignment result with 0 offset. """ translation = Point() description = "DISABLED!" return AlignedImages(self._image1, self._image2, self._resolution, self._scale_factor, translation, self._align_config, description)
def pixel_offset(self): """ The translation (offset) in pixels - nearest whole number. """ if self._pixel_offset is None: self._pixel_offset = Point(int(round(self._translation.x, 0)), int(round(self._translation.y, 0))) return self._pixel_offset
def parse_selected_points_from_args(self): """Parse the selected points list provided by the command line for validity and returns a list of Point objects. :param args: Command line arguments provided by argument parser - must contain 'selected_points' :return: List of Selected Points. """ log = logging.getLogger(".".join([__name__])) log.addFilter(logconfig.ThreadContextFilter()) selected_points = [] if self.get_args().selected_points: point_expected_format = re.compile("[0-9]+,[0-9]+") sel_points = self.get_args().selected_points for point_string in self.get_args().selected_points: point_string = point_string.strip('()') match_results = point_expected_format.match(point_string) # Check the regex matches the entire string # DEV NOTE: can use re.full_match in Python v3 if match_results is not None and match_results.span( )[1] == len(point_string): x, y = map(int, point_string.strip('()').split(',')) selected_points.append(Point(x, y)) else: log.warning( "Selected point with invalid format will be ignored - '" + point_string + "'") return selected_points
def real_offset(self): """ The transform in real units (um) with no rounding. """ if self._real_offset is None: x, y = self._translation.x, self._translation.y pixel_size = self._resolution self._real_offset = Point(x * pixel_size, y * pixel_size) return self._real_offset
def real_center(self): """ The position of the center of image B (in image A coordinates) - in pixels. """ if self._real_center is None: width, height = self.image2.size() x, y = self._translation.x + width / 2, self._translation.y + height / 2 self._real_center = Point(x, y) return self._real_center
def draw_text(self, text, point, color=Color.black(), centered=False, scale=1.5, thickness=3): """ Draw the specified text on the image (in place) """ position = point if centered: size = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, fontScale=scale, thickness=thickness)[0] position = point + Point(-size[0]/2, +size[1]/2) position = position.intify().tuple() cv2.putText(self._img, text, position, cv2.FONT_HERSHEY_SIMPLEX, scale, color.bgra(), thickness)
def _calculate_median_translation(self, matches): matches, mask = self._pre_filter(matches) deltas = [m.point2() - m.point1() for m in matches] x = -np.median([d.x for d in deltas]) y = -np.median([d.y for d in deltas]) point = Point(x, y) transform = Translation(point) return transform, mask
def test_find_z_level_for_point_very_close_to_image_edge(self): img = MagicMock(get_image=Mock(return_value=np.ones((30, 30), dtype=np.float64)), get_image_number=Mock(return_value=1), get_image_name=Mock(return_value='test1') ) fft_images = [img] poi = Point(1, 1) region_size = 10 number = PointFFTManager(fft_images, poi, region_size).find_z_level_for_point() self.assertEqual(number, 1)
def make_search_region(self, centre_point): """ Define a rectangle on image B in which to search for the matching crystal. Its narrow and tall as the crystal is likely to move downwards under the effect of gravity. """ search_width, search_height = self._search_size_pixels() vertical_shift = self._search_vertical_shift top_left = centre_point - Point(search_width / 2, search_height * (1 - vertical_shift)) rect = Rectangle.from_corner(top_left, search_width, search_height) rect = rect.intersection(self._aligned_images.image2.bounds()) return rect
def test_find_z_level_for_point_returns_number_of_img_with_higier_fft(self): img =MagicMock(get_image=Mock(return_value=np.ones((30,30),dtype=np.float64)), get_image_number=Mock(return_value=10), get_image_name=Mock(return_value='test1') ) img1 = MagicMock(get_image=Mock(return_value=np.zeros((30,30),dtype=np.float64)), get_image_number=Mock(return_value=0), get_image_name=Mock(return_value='test2') ) fft_images = [img, img1] poi = Point(15,15) region_size = 10 number = PointFFTManager(fft_images, poi, region_size).find_z_level_for_point() self.assertEqual(number, 10)
def draw_cross(self, point, color=Color.black(), size=5, thickness=1): """ Draw an X on the image (in place). """ self.draw_line(point - Point(size, size), point + Point(size, size), color, thickness) self.draw_line(point + Point(size, -size), point + Point(-size, size), color, thickness)
def _np_array_to_points(np_array): points = [] for p in np_array: points.append(Point(p[0][0], p[0][1])) return points
def test_crop_region_from_image_cuts_square_region_of_given_size(self): image = np.zeros((10, 10), dtype=np.float64) pointfft = PointFFT(Point(5, 5), image, 2) region = pointfft.crop_region_from_image() self.assertEqual(region.size, 4)
def bounds(self): """ Return a rectangle that bounds the image (0,0,w,h). """ return Rectangle(Point(), Point(self.width(), self.height()))
def point(self): """ The image coordinates of the feature. """ return Point(self._keypoint.pt[0], self._keypoint.pt[1])