def process_image(args, path): global bin_mask, intersects, rotation, img, img_src, center img = cv2.imread(path) if img == None or img.size == 0: logging.info("Failed to read %s" % path) return logging.info("Processing %s..." % path) # Scale the image down if its perimeter exceeds the maximum (if set). img = common.scale_max_perimeter(img, args.max_size) img_src = img.copy() # Perform segmentation logging.info("- Segmenting...") mask = common.grabcut(img, args.iters, None, args.margin) bin_mask = np.where((mask == cv2.GC_FGD) + (mask == cv2.GC_PR_FGD), 255, 0).astype('uint8') # Obtain contours (all points) from the mask. contour = ft.get_largest_contour(bin_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # Fit an ellipse on the contour to get the rotation angle. box = cv2.fitEllipse(contour) rotation = int(box[2]) # Get the shape360 feature. logging.info("- Obtaining shape...") intersects, center = ft.shape_360(contour, rotation) logging.info("- Done") draw_axis()
def process_image(args, path): global intersects, rotation, img, img_src, center img = cv2.imread(path) if img == None or img.size == 0: logging.info("Failed to read %s" % path) return logging.info("Processing %s..." % path) # Scale the image down if its perimeter exceeds the maximum (if set). img = common.scale_max_perimeter(img, args.max_size) img_src = img.copy() # Perform segmentation logging.info("- Segmenting...") mask = common.grabcut(img, args.iters, None, args.margin) bin_mask = np.where((mask == cv2.GC_FGD) + (mask == cv2.GC_PR_FGD), 255, 0).astype("uint8") # Obtain contours (all points) from the mask. contour = ft.get_largest_contour(bin_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # Fit an ellipse on the contour to get the rotation angle. box = cv2.fitEllipse(contour) rotation = int(box[2]) # Get the shape360 feature. logging.info("- Obtaining shape...") intersects, center = ft.shape_360(contour, rotation) logging.info("- Done") draw_axis()
def __get_shape_360(self, args, bin_mask): """Executes :meth:`features.shape_360`.""" if self.bin_mask == None: raise ValueError("Binary mask cannot be None") rotation = getattr(args, 'rotation', 0) step = getattr(args, 'step', 1) t = getattr(args, 't', 8) output_functions = getattr(args, 'output_functions', {'mean_sd': True}) # Get the largest contour from the binary mask. contour = ft.get_largest_contour(bin_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) if contour == None: raise ValueError("No contour found for binary image") # Set the rotation. if rotation == 'FIT_ELLIPSE': box = cv2.fitEllipse(contour) rotation = int(box[2]) if not 0 <= rotation <= 179: raise ValueError("Rotation must be in the range 0 to 179, "\ "found %s" % rotation) # Extract shape feature. intersects, center = ft.shape_360(contour, rotation, step, t) # Create a masked image. if 'color_histograms' in output_functions: img_masked = cv2.bitwise_and(self.img, self.img, mask=bin_mask) # Run the output function for each angle. means = [] sds = [] histograms = [] for angle in range(0, 360, step): for f_name, f_args in vars(output_functions).iteritems(): # Mean distance + standard deviation. if f_name == 'mean_sd': distances = [] for p in intersects[angle]: d = ft.point_dist(center, p) distances.append(d) if len(distances) == 0: mean = 0 sd = 0 else: mean = np.mean(distances, dtype=np.float32) if len(distances) > 1: sd = np.std(distances, ddof=1, dtype=np.float32) else: sd = 0 means.append(mean) sds.append(sd) # Color histograms. if f_name == 'color_histograms': # Get a line from the center to the outer intersection point. line = None if intersects[angle]: line = ft.extreme_points([center] + intersects[angle]) # Create a mask for the line, where the line is foreground. line_mask = np.zeros(self.img.shape[:2], dtype=np.uint8) if line is not None: cv2.line(line_mask, tuple(line[0]), tuple(line[1]), 255, 1) # Create histogram from masked + line masked image. hists = self.__get_color_histograms(img_masked, f_args, line_mask) histograms.append(hists) means = means.astype(float) sds = sds.astype(float) # Normalize the features if a scaler is set. if self.scaler and 'mean_sd' in output_functions: means = self.scaler.fit_transform(means) sds = self.scaler.fit_transform(sds) # Group the means+sds together. means_sds = np.array(zip(means, sds)).flatten() return np.append(means_sds, histograms)
def __get_shape_360(self, args, bin_mask): """Executes :meth:`features.shape_360`.""" if self.bin_mask == None: raise ValueError("Binary mask cannot be None") rotation = getattr(args, 'rotation', 0) step = getattr(args, 'step', 1) t = getattr(args, 't', 8) output_functions = getattr(args, 'output_functions', {'mean_sd': True}) # Get the largest contour from the binary mask. contour = ft.get_largest_contour(bin_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) if contour == None: raise ValueError("No contour found for binary image") # Set the rotation. if rotation == 'FIT_ELLIPSE': box = cv2.fitEllipse(contour) rotation = int(box[2]) if not 0 <= rotation <= 179: raise ValueError("Rotation must be in the range 0 to 179, "\ "found %s" % rotation) # Extract shape feature. intersects, center = ft.shape_360(contour, rotation, step, t) # Create a masked image. if 'color_histograms' in output_functions: img_masked = cv2.bitwise_and(self.img, self.img, mask=bin_mask) # Run the output function for each angle. means = [] sds = [] histograms = [] for angle in range(0, 360, step): for f_name, f_args in vars(output_functions).iteritems(): # Mean distance + standard deviation. if f_name == 'mean_sd': distances = [] for p in intersects[angle]: d = ft.point_dist(center, p) distances.append(d) if len(distances) == 0: mean = 0 sd = 0 else: mean = np.mean(distances, dtype=np.float32) if len(distances) > 1: sd = np.std(distances, ddof=1, dtype=np.float32) else: sd = 0 means.append(mean) sds.append(sd) # Color histograms. if f_name == 'color_histograms': # Get a line from the center to the outer intersection point. line = None if intersects[angle]: line = ft.extreme_points([center] + intersects[angle]) # Create a mask for the line, where the line is foreground. line_mask = np.zeros(self.img.shape[:2], dtype=np.uint8) if line is not None: cv2.line(line_mask, tuple(line[0]), tuple(line[1]), 255, 1) # Create histogram from masked + line masked image. hists = self.__get_color_histograms( img_masked, f_args, line_mask) histograms.append(hists) means = means.astype(float) sds = sds.astype(float) # Normalize the features if a scaler is set. if self.scaler and 'mean_sd' in output_functions: means = self.scaler.fit_transform(means) sds = self.scaler.fit_transform(sds) # Group the means+sds together. means_sds = np.array(zip(means, sds)).flatten() return np.append(means_sds, histograms)