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 test_save_function_saves_image_in_a_default_destination(self): self.pm.get_args = Mock( return_value=Mock(output=None, log=None, config="test_config")) default_path = self.pm.get_out_file_path() self.assertFalse(isfile(default_path)) self.pm.save_focused_image(Image(np.zeros((3, 3), dtype=np.uint8))) self.assertTrue(isfile(default_path))
def resize(self, new_size): image = Image.resize(self, new_size) # Because the image must be an integer number of pixels, we must correct the # factor to calculate the pixel size properly. corrected_factor = new_size[0] / self.width() pixel_size = self._pixel_size / corrected_factor return self.from_image(image, pixel_size)
def perform_match(self, parser_manager): """ Perform image alignment and crystal matching returning a results object. :param . :return: ServiceResult object. """ log = logging.getLogger(".".join([__name__, self.__class__.__name__])) log.addFilter(logconfig.ThreadContextFilter()) extra = self._config_align.all_to_json() extra.update(self._config_crystal.all_to_json()) log = logging.LoggerAdapter(log, extra) log.info("Matching Started") log.debug(extra) input_poi = parser_manager.parse_selected_points_from_args() beamline_image = parser_manager.get_focused_image() parser_manager.save_focused_image(beamline_image) focused_image_path = parser_manager.get_focused_image_path() formulatrix_image_path = parser_manager.get_formulatrix_image_path() job_id = parser_manager.get_job_id() # Create the images image1 = Image.from_file(formulatrix_image_path) image2 = beamline_image # Create results object service_result = ServiceResult(job_id, formulatrix_image_path, focused_image_path) # Perform alignment try: aligned_images, scaled_poi = self._perform_alignment( image1, image2, input_poi) service_result.set_image_alignment_results(aligned_images) # Perform Crystal Matching - only proceed if we have a valid alignment if aligned_images.alignment_status_code( ) == ALIGNED_IMAGE_STATUS_OK: match_results = self._perform_matching(aligned_images, scaled_poi, parser_manager) service_result.append_crystal_matching_results(match_results) except Exception as e: if sys.version_info[0] < 3: log.error("ERROR: " + e.message) else: log.error("ERROR: " + str(e)) service_result.set_err_state(e) return service_result
def get_focused_image(self): focusing_path = abspath(self.get_args().beamline_stack_path) if "." not in focusing_path: files = self._sort_files_according_to_names(focusing_path) # Run focusstack stacker = FocusStack(files, self.get_args().config) focused_image = stacker.composite() self.images_to_stack = stacker.get_fft_images_to_stack() else: focused_image = Image(cv2.imread(focusing_path)) return focused_image
def _create_background_image(self): """ Create the background image, which consists of the two images side-by-side with a colored backdrop. This must be recreated if the image size, padding, or background color changes. """ self._calculate_image_positions() w, h = self._calculate_background_image_size() image = Image.blank(w, h) image.paste(self._image1, self._image1_position) image.paste(self._image2, self._image2_position) image, factor = self._rescale_to_max_size(image) self._background_image = image self._scale_factor = factor
def composite(self): log = logging.getLogger(".".join([__name__, self.__class__.__name__])) log.addFilter(logconfig.ThreadContextFilter()) extra = self._config.all_to_json() log = logging.LoggerAdapter(log, extra) log.info("Focusstack Started, first image, " + self._image_file_list[0].name) log.debug(extra) start_t = time.time() t1 = time.time() man = ImageFFTManager(self._image_file_list) man.read_ftt_images() sd = SharpnessDetector(man.get_fft_images(), self._config) images = sd.images_to_stack() self.fft_images = sd.get_fft_images_to_stack() t2 = time.time() - t1 #add extra field to the log extra = {'FTT_time': t2} log = logging.LoggerAdapter(log, extra) log.info("FFT calculation finished") log.debug(extra) images = np.array(images, dtype=images[0].dtype) #TODO:Implement alignment algo #aligned_images, gray_images = self.align(images) #stacked_image = pyramid(aligned_images, self._config).get_pyramid_fusion() stacked_image = PyramidManager(images, self._config).get_pyramid_fusion() stacked_image = cv2.convertScaleAbs(stacked_image) backtorgb = cv2.cvtColor(stacked_image, cv2.COLOR_GRAY2RGB) calculation_time = time.time() - start_t extra = {'stack_time': calculation_time} log = logging.LoggerAdapter(log, extra) log.info("Stacking Finished") log.debug(extra) return Image(backtorgb)
def __init__(self, img, pixel_size): Image.__init__(self, img) # The real size represented by a single pixel in the image self._pixel_size = pixel_size
def freq_range(self, coarseness_range, scale_factor): image = Image.freq_range(self, coarseness_range, scale_factor) return self.from_image(image, self._pixel_size)
def to_alpha(self): image = Image.to_alpha(self) return self.from_image(image, self._pixel_size)
def to_color(self): image = Image.to_color(self) return self.from_image(image, self._pixel_size)
def rotate(self, angle, center): image = Image.rotate(self, angle, center) return self.from_image(image, self._pixel_size)
def from_file(filename, pixel_size=0): image = Image.from_file(filename) return SizedImage(image, pixel_size)
def draw_keypoints(image, keypoints): """ Draw the list of keypoints to the specified image and display it as a popup window. """ marked_image = cv2.drawKeypoints(image.raw(), keypoints, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) return Image(marked_image)
def inverse_transform_image(self, image, output_size): warped = cv2.warpPerspective(image.raw(), self._homography_inverse, output_size) warped = Image(warped) return warped
def inverse_transform_image(self, image, output_size): offset = - self._translation warped = Image.blank(output_size[0], output_size[1], image.channels) warped.paste(image, offset) return warped
def crop(self, rect): image = Image.crop(self, rect) return self.from_image(image, self._pixel_size)
def crop_region_from_image(self): region = Rectangle.from_center(self.point, self.region_size, self.region_size) img = Image(self.img).crop(region) return img.raw()