Esempio n. 1
0
def main():
    print __doc__

    parser = argparse.ArgumentParser(description='Test image segmentation')
    parser.add_argument('image', metavar='FILE', help='Input image')
    parser.add_argument('--max-size', metavar='N', type=float, help="Scale the input image down if its perimeter exceeds N. Default is no scaling.")
    args = parser.parse_args()

    img = cv2.imread(args.image)
    if img == None or img.size == 0:
        sys.stderr.write("Failed to read %s\n" % args.image)
        return -1

    sys.stderr.write("Processing %s...\n" % args.image)

    # Scale the image down if its perimeter exceeds the maximum (if set).
    img = common.scale_max_perimeter(img, args.max_size)

    # Linear enhancement
    enhanced1 = ft.naik_murthy_linear(img)

    # Nonlinear enhancement using S-type function
    enhanced2a = ft.naik_murthy_nonlinear(enhanced1, ft.s_type_enhancement, 0, 3, 0.5, 2)
    enhanced2b = ft.naik_murthy_nonlinear(enhanced1, ft.s_type_enhancement, 0, 3, 1.5, 2)

    # Enhancement using histogram equalization
    sums = bgr_to_sums(img) # Range 0..(255*3-1)
    sums = cv2.normalize(sums, None, 0, 255, cv2.NORM_MINMAX) # Range 0..255
    sums = cv2.equalizeHist(np.uint8(sums))
    sums = cv2.normalize(np.float32(sums), None, 0, 3, cv2.NORM_MINMAX) # Range 0..3
    enhanced3 = ft.naik_murthy_nonlinear(img, sums, fmap=True)

    # Display the image in a window.
    cv2.namedWindow('image')
    cv2.imshow('image', img)

    while True:
        k = cv2.waitKey(0) & 0xFF

        if k == ord('0'):
            cv2.imshow('image', img)
        elif k == ord('1'):
            cv2.imshow('image', enhanced1)
        elif k == ord('2'):
            cv2.imshow('image', enhanced2a)
        elif k == ord('w'):
            cv2.imshow('image', enhanced2b)
        elif k == ord('3'):
            cv2.imshow('image', enhanced3)
        elif k == 27:
            break

    cv2.destroyAllWindows()
    return 0
Esempio n. 2
0
    def _preprocess(self):
        if self.img == None:
            raise ValueError("No image loaded")

        if 'preprocess' not in self.params:
            return

        # Scale the image down if its perimeter exceeds the maximum (if set).
        perim = sum(self.img.shape[:2])
        max_perim = getattr(self.params.preprocess, 'maximum_perimeter', None)
        if max_perim and perim > max_perim:
            logging.info("Scaling down...")
            rf = float(max_perim) / perim
            self.img = cv2.resize(self.img, None, fx=rf, fy=rf)

        # Perform color enhancement.
        color_enhancement = getattr(self.params.preprocess, 'color_enhancement', None)
        if color_enhancement:
            for method, args in vars(color_enhancement).iteritems():
                if method == 'naik_murthy_linear':
                    logging.info("Color enhancement...")
                    self.img = ft.naik_murthy_linear(self.img)
                else:
                    raise ValueError("Unknown color enhancement method '%s'" % method)

        # Perform segmentation.
        segmentation = getattr(self.params.preprocess, 'segmentation', None)
        if segmentation:
            logging.info("Segmenting...")
            iterations = getattr(segmentation, 'iterations', 5)
            margin = getattr(segmentation, 'margin', 1)
            output_folder = getattr(segmentation, 'output_folder', None)

            # Create a binary mask for the largest contour.
            self.mask = common.grabcut(self.img, iterations, None, margin)
            self.bin_mask = np.where((self.mask==cv2.GC_FGD) + (self.mask==cv2.GC_PR_FGD), 255, 0).astype('uint8')
            contour = ft.get_largest_contour(self.bin_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
            if contour == None:
                raise ValueError("No contour found for binary image")
            self.bin_mask = np.zeros(self.img.shape[:2], dtype=np.uint8)
            cv2.drawContours(self.bin_mask, [contour], 0, 255, -1)

            # Save the masked image to the output folder.
            if output_folder and os.path.isdir(output_folder):
                img_masked = cv2.bitwise_and(self.img, self.img, mask=self.bin_mask)
                fname = os.path.basename(self.path)
                out_path = os.path.join(output_folder, fname)
                cv2.imwrite(out_path, img_masked)
Esempio n. 3
0
    def __preprocess(self):
        """Perform preprocessing steps as specified in the configurations.

        Preprocessing steps may be:

        * Resizing
        * Color correction
        * Segmentation

        This method is executed by :meth:`make`.
        """
        if self.img is None:
            raise RuntimeError("No image is loaded")
        if 'preprocess' not in self.config:
            return

        # Scale the image down if its perimeter (width+height) exceeds the
        # maximum. If a ROI is set, use the perimeter of the ROI instead, or
        # else we might end up with a very small ROI.
        if self.roi:
            perim = sum(self.roi[2:4])
        else:
            perim = sum(self.img.shape[:2])

        rf = 1.0
        max_perim = getattr(self.config.preprocess, 'maximum_perimeter', None)
        if max_perim and perim > max_perim:
            logging.info("Scaling down...")
            rf = float(max_perim) / perim
            self.img = cv2.resize(self.img, None, fx=rf, fy=rf)

        # Account for the resizing factor if a ROI is set.
        if self.roi:
            self.roi = [int(x*rf) for x in self.roi]
            self.roi = tuple(self.roi)

        # Perform color enhancement.
        color_enhancement = getattr(self.config.preprocess,
            'color_enhancement', None)
        if color_enhancement:
            for method, args in vars(color_enhancement).iteritems():
                if method == 'naik_murthy_linear':
                    logging.info("Color enhancement...")
                    self.img = ft.naik_murthy_linear(self.img)
                else:
                    raise ConfigurationError("Unknown color enhancement "\
                        "method '%s'" % method)

        # Perform segmentation.
        try:
            segmentation = self.config.preprocess.segmentation.grabcut
        except:
            segmentation = {}

        if segmentation:
            logging.info("Segmenting...")
            iters = getattr(segmentation, 'iters', 5)
            margin = getattr(segmentation, 'margin', 1)
            output_folder = getattr(segmentation, 'output_folder', None)

            # Get the main contour.
            self.mask = self.__grabcut(self.img, iters, self.roi, margin)
            self.bin_mask = np.where((self.mask==cv2.GC_FGD) + \
                (self.mask==cv2.GC_PR_FGD), 255, 0).astype('uint8')
            contour = ft.get_largest_contour(self.bin_mask, cv2.RETR_EXTERNAL,
                cv2.CHAIN_APPROX_SIMPLE)
            if contour is None:
                raise ValueError("No contour found for binary image")

            # Create a binary mask of the main contour.
            self.bin_mask = np.zeros(self.img.shape[:2], dtype=np.uint8)
            cv2.drawContours(self.bin_mask, [contour], 0, 255, -1)

            # Save the masked image to the output folder.
            if output_folder:
                img_masked = cv2.bitwise_and(self.img, self.img,
                    mask=self.bin_mask)

                out_path = os.path.join(output_folder, self.path)
                out_dir = os.path.dirname(out_path)
                if not os.path.isdir(out_dir):
                    os.makedirs(out_dir)

                cv2.imwrite(out_path, img_masked)
Esempio n. 4
0
    def __preprocess(self):
        """Perform preprocessing steps as specified in the configurations.

        Preprocessing steps may be:

        * Resizing
        * Color correction
        * Segmentation or cropping

        This method is executed by :meth:`make`.
        """
        if self.img is None:
            raise RuntimeError("No image is loaded")
        if 'preprocess' not in self.config:
            return

        # Scale the image down if its perimeter (width+height) exceeds the
        # maximum. If a ROI is set, use the perimeter of the ROI instead, or
        # else we might end up with a very small ROI.
        if self.roi:
            perim = sum(self.roi[2:4])
        else:
            perim = sum(self.img.shape[:2])

        rf = 1.0
        max_perim = getattr(self.config.preprocess, 'maximum_perimeter', None)
        if max_perim and perim > max_perim:
            logging.info("Scaling down...")
            rf = float(max_perim) / perim
            self.img = cv2.resize(self.img, None, fx=rf, fy=rf)

        # Account for the resizing factor if a ROI is set.
        if self.roi:
            self.roi = [int(x * rf) for x in self.roi]
            self.roi = tuple(self.roi)

        # Perform color enhancement.
        color_enhancement = getattr(self.config.preprocess,
                                    'color_enhancement', None)
        if color_enhancement:
            for method, args in vars(color_enhancement).iteritems():
                if method == 'naik_murthy_linear':
                    logging.info("Color enhancement...")
                    self.img = ft.naik_murthy_linear(self.img)
                else:
                    raise ConfigurationError("Unknown color enhancement "\
                        "method '%s'" % method)

        # Perform segmentation.
        try:
            segmentation = self.config.preprocess.segmentation.grabcut
        except:
            segmentation = {}

        if segmentation:
            logging.info("Segmenting...")
            iters = getattr(segmentation, 'iters', 5)
            margin = getattr(segmentation, 'margin', 1)
            output_folder = getattr(segmentation, 'output_folder', None)

            # Get the main contour.
            self.mask = self.__grabcut(self.img, iters, self.roi, margin)
            self.bin_mask = np.where((self.mask==cv2.GC_FGD) + \
                (self.mask==cv2.GC_PR_FGD), 255, 0).astype('uint8')
            contour = ft.get_largest_contour(self.bin_mask, cv2.RETR_EXTERNAL,
                                             cv2.CHAIN_APPROX_SIMPLE)
            if contour is None:
                raise ValueError("No contour found for binary image")

            # Create a binary mask of the main contour.
            self.bin_mask = np.zeros(self.img.shape[:2], dtype=np.uint8)
            cv2.drawContours(self.bin_mask, [contour], 0, 255, -1)

            # Save the masked image to the output folder.
            if output_folder:
                img_masked = cv2.bitwise_and(self.img,
                                             self.img,
                                             mask=self.bin_mask)

                out_path = os.path.join(output_folder, self.path)
                out_dir = os.path.dirname(out_path)
                if not os.path.isdir(out_dir):
                    os.makedirs(out_dir)

                cv2.imwrite(out_path, img_masked)
        else:
            # Crop image in stead of segmenting.
            try:
                crop = self.config.preprocess.crop
            except:
                crop = {}

            if crop:
                logging.info("Cropping image...")
                roi_pix = getattr(crop, 'roi_pix', None)
                roi_frac = getattr(crop, 'roi_frac', None)
                if roi_pix:
                    # roi_pix is like (x, y, w, h) in pixel units.
                    if len(roi_pix) != 4:
                        raise ValueError(
                            "roi_pix must be a list of four integers.")
                    for x in roi_pix:
                        if not (isinstance(x, int) and x >= 0):
                            raise ValueError(
                                "roi_pix must be a (x, y, w, h) tuple "
                                "of integers.")
                    self.roi = roi_pix
                elif roi_frac:
                    # roi_frac is like (x1, x2, y1, y2) in fractions
                    # of total img size.
                    if len(roi_frac) != 4:
                        raise ValueError(
                            "roi_frac must be a list of four floats.")
                    for x in roi_frac:
                        if not 0 <= x <= 1:
                            raise ValueError(
                                "roi_frac must be a (x1, x2, y1, y2) tuple, "
                                "where the values are floats between 0 and 1.")
                    if not (roi_frac[0] < roi_frac[1]
                            and roi_frac[2] < roi_frac[3]):
                        raise ValueError(
                            "roi_frac must be a (x1, x2, y1, y2) tuple, "
                            "where x1 < x2 and y1 < y2.")
                    # Make ROI like (x, y, w, h).
                    self.roi = (int(self.img.shape[1] * roi_frac[0]),
                                int(self.img.shape[0] * roi_frac[2]),
                                int(self.img.shape[1] * roi_frac[1]) -
                                int(self.img.shape[1] * roi_frac[0]),
                                int(self.img.shape[0] * roi_frac[3]) -
                                int(self.img.shape[0] * roi_frac[2]))
                else:
                    logging.warning("No ROI for cropping found. Proceed "
                                    "without cropping.")
                    self.roi = (0, 0, self.img.shape[1], self.img.shape[0])

                # Crop image to given ROI.
                self.img = self.img[self.roi[1]:self.roi[1] + self.roi[3],
                                    self.roi[0]:self.roi[0] + self.roi[2]]
Esempio n. 5
0
    def __preprocess(self):
        """Perform preprocessing steps as specified in the configurations.

        Preprocessing steps may be:

        * Resizing
        * Color correction
        * Segmentation or cropping

        This method is executed by :meth:`make`.
        """
        if self.img is None:
            raise RuntimeError("No image is loaded")
        if 'preprocess' not in self.config:
            return

        # Scale the image down if its perimeter (width+height) exceeds the
        # maximum. If a ROI is set, use the perimeter of the ROI instead, or
        # else we might end up with a very small ROI.
        if self.roi:
            perim = sum(self.roi[2:4])
        else:
            perim = sum(self.img.shape[:2])

        rf = 1.0
        max_perim = getattr(self.config.preprocess, 'maximum_perimeter', None)
        if max_perim and perim > max_perim:
            logging.info("Scaling down...")
            rf = float(max_perim) / perim
            self.img = cv2.resize(self.img, None, fx=rf, fy=rf)

        # Account for the resizing factor if a ROI is set.
        if self.roi:
            self.roi = [int(x*rf) for x in self.roi]
            self.roi = tuple(self.roi)

        # Perform color enhancement.
        color_enhancement = getattr(self.config.preprocess,
            'color_enhancement', None)
        if color_enhancement:
            for method, args in vars(color_enhancement).iteritems():
                if method == 'naik_murthy_linear':
                    logging.info("Color enhancement...")
                    self.img = ft.naik_murthy_linear(self.img)
                else:
                    raise ConfigurationError("Unknown color enhancement "\
                        "method '%s'" % method)

        # Perform segmentation.
        try:
            segmentation = self.config.preprocess.segmentation.grabcut
        except:
            segmentation = {}

        if segmentation:
            logging.info("Segmenting...")
            iters = getattr(segmentation, 'iters', 5)
            margin = getattr(segmentation, 'margin', 1)
            output_folder = getattr(segmentation, 'output_folder', None)

            # Get the main contour.
            self.mask = self.__grabcut(self.img, iters, self.roi, margin)
            self.bin_mask = np.where((self.mask==cv2.GC_FGD) + \
                (self.mask==cv2.GC_PR_FGD), 255, 0).astype('uint8')
            contour = ft.get_largest_contour(self.bin_mask, cv2.RETR_EXTERNAL,
                cv2.CHAIN_APPROX_SIMPLE)
            if contour is None:
                raise ValueError("No contour found for binary image")

            # Create a binary mask of the main contour.
            self.bin_mask = np.zeros(self.img.shape[:2], dtype=np.uint8)
            cv2.drawContours(self.bin_mask, [contour], 0, 255, -1)

            # Save the masked image to the output folder.
            if output_folder:
                img_masked = cv2.bitwise_and(self.img, self.img,
                    mask=self.bin_mask)

                out_path = os.path.join(output_folder, self.path)
                out_dir = os.path.dirname(out_path)
                if not os.path.isdir(out_dir):
                    os.makedirs(out_dir)

                cv2.imwrite(out_path, img_masked)
        else:
            # Crop image in stead of segmenting.
            try:
                crop = self.config.preprocess.crop
            except:
                crop = {}

            if crop:
                logging.info("Cropping image...")
                roi_pix = getattr(crop, 'roi_pix', None)
                roi_frac = getattr(crop, 'roi_frac', None)
                if roi_pix:
                    # roi_pix is like (x, y, w, h) in pixel units.
                    if len(roi_pix) != 4:
                        raise ValueError(
                            "roi_pix must be a list of four integers.")
                    for x in roi_pix:
                        if not (isinstance(x, int) and x >= 0):
                            raise ValueError(
                                "roi_pix must be a (x, y, w, h) tuple "
                                "of integers.")
                    self.roi = roi_pix
                elif roi_frac:
                    # roi_frac is like (x1, x2, y1, y2) in fractions
                    # of total img size.
                    if len(roi_frac) != 4:
                        raise ValueError(
                            "roi_frac must be a list of four floats.")
                    for x in roi_frac:
                        if not 0 <= x <= 1:
                            raise ValueError(
                                "roi_frac must be a (x1, x2, y1, y2) tuple, "
                                "where the values are floats between 0 and 1.")
                    if not (roi_frac[0] < roi_frac[1] and
                            roi_frac[2] < roi_frac[3]):
                        raise ValueError(
                            "roi_frac must be a (x1, x2, y1, y2) tuple, "
                            "where x1 < x2 and y1 < y2.")
                    # Make ROI like (x, y, w, h).
                    self.roi = (int(self.img.shape[1] * roi_frac[0]),
                                int(self.img.shape[0] * roi_frac[2]),
                                int(self.img.shape[1] * roi_frac[1]) -
                                int(self.img.shape[1] * roi_frac[0]),
                                int(self.img.shape[0] * roi_frac[3]) -
                                int(self.img.shape[0] * roi_frac[2]))
                else:
                    logging.warning("No ROI for cropping found. Proceed "
                                    "without cropping.")
                    self.roi = (0, 0, self.img.shape[1], self.img.shape[0])

                # Crop image to given ROI.
                self.img = self.img[self.roi[1]: self.roi[1] + self.roi[3],
                                    self.roi[0]: self.roi[0] + self.roi[2]]