示例#1
0
    def setUp(self):

        # Test images cropped around the droplet region
        self.empty_img = open_grey_scale_image('tests/test_images/empty_droplets.JPG')[250:2350, 0:4288]
        self.some_crystals_img = open_grey_scale_image('tests/test_images/some_crystals.JPG')[250:2350, 0:4288]
        self.all_crystals_img = open_grey_scale_image('tests/test_images/all_crystals.JPG')[250:2350, 0:4288]

        # Target number of droplets
        self.num_droplets = 149
        self.delta = self.num_droplets // 0.7 # 15% variation in segmentation results is allowed
示例#2
0
def segment_cells_to_file2p5(image_filename, save_overlay=False):

    if os.path.isdir(image_filename):
        img_list = [
            os.path.join(image_filename, f) for f in os.listdir(image_filename)
            if f.endswith('.jpg')
        ]
    elif os.path.isfile(image_filename):
        img_list = [image_filename]

    for image_file in tqdm(img_list):
        # Open image
        image = open_grey_scale_image(image_file)

        # Segment image
        (labeled, num_regions) = segment2p5(image)

        # Save the overlay image if requested
        if save_overlay:
            image_overlay = label2rgb(labeled, bg_label=0)
            filename = image_file.split('.')[0] + '_segmented.jpg'
            with warnings.catch_warnings():
                warnings.simplefilter("ignore")
                io.imsave(filename, image_overlay)

        # Extract individual cells
        cell_images, _, area_list2p5 = extract_indiv_cells2p5(image, labeled)

        # Output folder has the same name as the image by default
        out_directory = image_file.split('.')[0]

        if not os.path.exists(out_directory):
            os.mkdir(out_directory)

        logging.info("Saving segmented cells to %s", out_directory)

        # Save all the images in the output directory
        for (i, img) in enumerate(cell_images):
            name2p5 = os.path.join(
                out_directory,
                os.path.basename(image_file).split('.')[0] + '_cell_' +
                str(i) + '.jpg')
            with warnings.catch_warnings():
                warnings.simplefilter("ignore")
                io.imsave(name2p5, img, check_contrast=False)

        cellarea2p5 = {
            name2p5[j]: area_list2p5[j]
            for j in range(len(name2p5))
        }

        with open(
                os.path.join(
                    out_directory,
                    os.path.basename(image_file).split('.')[0] + '.pkl'),
                'wb') as f:
            f.write(pickle.dumps(cellarea2p5))
示例#3
0
def process_image(image_path, model, save_overlay=False):
    '''
    Process a single image to obtain the number of detached and attached cells

    Parameters
    ----------
    imgage_path: string
        Path to the image to process
    model: tensorflow model
        Instance of a tensorflow model trained to discriminate round and flat cells
    save_overlay: bool, optional
        Save an image with green / red overlays for detached / attached cells to `image_path / overlay`

    Returns
    -------
    (date_take: datetime, num_cells: int, num_attached: int, num_detached: int)
        Date from the EXIF data, number of cells, number of attached cells, number of detached cells
    '''

    # Open image
    #date_taken = get_date_taken(image_path)
    image = open_grey_scale_image(image_path)

    # Segment image
    (labeled, _) = segment(image)

    # Extract individual droplets
    cell_images, regProps = extract_indiv_cells(image, labeled)

    # Predict labels from model
    if cell_images and len(cell_images) > 0:
        X = np.asarray(cell_images)
        Y = model.predict_classes(X).flatten().tolist()

        num_cells = len(Y)
        num_attached = Y.count(0)
        num_detached = num_cells - num_attached

    else:
        logging.warning("No cells found in image %s", image_path)
        num_cells = 0
        num_attached = 0
        num_detached = 0

    # Save overlay if applicable
    if save_overlay:
        path = os.path.join(os.path.dirname(image_path), 'overlay',
                            os.path.basename(image_path))
        save_overlay_image(path, image, regProps, Y)

    return (num_cells, num_attached, num_detached)
示例#4
0
def process_image_folder(directory,
                         show_plot=False,
                         save_overlay=False,
                         show_segmentation=False):

    # List images in directory
    supported_extensions = [
        'jpg',
        'png',
        'gif',
        'jpeg ',
        'eps',
        'bmp',
        'tiff',
        'bmp',
        'icns',
        'ico',
        'spi',
    ]
    image_list = [
        os.path.join(directory, image_path)
        for image_path in os.listdir(directory)
        if os.path.splitext(image_path)[1][1:].lower() in supported_extensions
    ]

    # Define the model path
    model_name = "cnn-simple-model.json"

    # If show segmentation flag is asserted, display the segmentation of an image
    if show_segmentation:
        idx_80 = int(len(image_list) * 0.8)
        image_80 = open_grey_scale_image(image_list[idx_80])
        logging.info("Segmentation check requested. Segmenting image %s",
                     image_list[idx_80])
        labeled, _ = segment(image_80)

        from skimage.color import label2rgb
        overlay_image = label2rgb(labeled, image=image_80, bg_label=1)

        import matplotlib
        matplotlib.use('Qt4Agg', force=True)
        import matplotlib.pyplot as plt
        fig = plt.figure()
        fig.set_tight_layout(True)
        plt.ion()
        plt.imshow(overlay_image)
        plt.show(block=False)
        plt.pause(0.1)

        result = input("Continue? (y/n)\n")

        while result != 'y':
            if result == 'n':
                plt.close()
                logging.warning(
                    "Segmentation rejected. Stopping the application")
                return
            else:
                result = input("Please press 'y' for yes or 'n' for no\n")

        plt.close()

    # Compute the number of batches necessary
    num_images = len(image_list)
    logging.info("Number of images: %d", num_images)
    num_cpu = os.cpu_count()

    if num_images < num_cpu:
        logging.info("Processing on a single thread.")
        flat_data = process_image_batch(image_list, model_name, 0,
                                        logging.root.level, save_overlay)
    else:
        logging.info("Processing in parallel")
        batch_size = max([1, num_images // (num_cpu - 1)])
        logging.info("Batch size: %d", batch_size)
        num_batches = int(math.ceil(num_images // batch_size))
        logging.info("Number of batches: %d", num_batches)

        # Process all images from directory in parallel
        data = Parallel(n_jobs=-2)(delayed(process_image_batch)(
            image_list[i * batch_size:min([(i + 1) * batch_size, num_images])],
            model_name, i, logging.root.level, save_overlay)
                                   for i in range(num_batches))

        flat_data = [item for sublist in data for item in sublist]

    # Make a dataframe from the data and save it to disk
    df = pd.DataFrame(sorted(flat_data, key=lambda x: x[0]),
                      columns=[
                          "DateTime", "Num cells", "Num attached",
                          "Num detached", "Image Name"
                      ])
    df['RelTime'] = (df['DateTime'] - df['DateTime'][0]).dt.total_seconds()
    df.to_csv(os.path.join(directory, "cellData.csv"))
    logging.info("Saved data to disk.")

    # Plot the data for imediate visualization
    if show_plot:
        plot_cell_data(df, directory)
 def test_open_asserts_error_if_file_not_found(self):
     with self.assertRaises(OSError):
         open_grey_scale_image('some/nonexistent/path.JPG')
 def setUp(self):
     self.empty_img = open_grey_scale_image(
         'tests/test_images/empty_droplets.JPG')
 def test_open_non_image_raises_error(self):
     with self.assertRaises(OSError):
         open_grey_scale_image('LICENSE')