Esempio n. 1
0
    def initialize_image(self):
        # Creates a local composite of the original image data for display
        if self.parent.data.im_type == 'wv02_ms':
            self.display_image = utils.create_composite([
                self.parent.data.original_image[4, :, :],
                self.parent.data.original_image[2, :, :],
                self.parent.data.original_image[1, :, :]
            ],
                                                        dtype=np.uint8)

        elif self.parent.data.im_type == 'pan':
            self.display_image = utils.create_composite([
                self.parent.data.original_image,
                self.parent.data.original_image,
                self.parent.data.original_image
            ],
                                                        dtype=np.uint8)

        elif self.parent.data.im_type == 'srgb':
            self.display_image = utils.create_composite([
                self.parent.data.original_image[0, :, :],
                self.parent.data.original_image[1, :, :],
                self.parent.data.original_image[2, :, :]
            ],
                                                        dtype=np.uint8)
        self.disp_xdim, self.disp_ydim = np.shape(self.display_image)[0:2]
Esempio n. 2
0
def save_color_image(image_data, output_name, image_type, block_cols,
                     block_rows):
    """
    Write a rgb color image (as png) of the raw image data to disk.
    """
    holder = []
    # Find the appropriate bands to use for an rgb representation
    if image_type == 'wv02_ms':
        rgb = [5, 3, 2]
    elif image_type == 'srgb':
        rgb = [1, 2, 3]
    else:
        rgb = [1, 1, 1]

    red_band = image_data[rgb[0]]
    green_band = image_data[rgb[1]]
    blue_band = image_data[rgb[2]]

    for i in range(len(red_band)):
        holder.append(
            utils.create_composite([red_band[i], green_band[i], blue_band[i]]))

    colorfullimg = utils.compile_subimages(holder, block_cols, block_rows, 3)
    mimg.imsave(output_name, colorfullimg)
    colorfullimg = None
Esempio n. 3
0
def display_watershed(original_data, watershed_data, block=5):

    # block = 5
    watershed = watershed_data[block]
    original_1 = original_data[6][block]
    original_2 = original_data[4][block]
    original_3 = original_data[1][block]

    # randcolor = colors.ListedColormap(np.random.rand(256,3))
    ws_bound = segmentation.find_boundaries(watershed)
    ws_display = utils.create_composite([original_1, original_2, original_3])
    ws_display[:, :, 0][ws_bound] = 240
    ws_display[:, :, 1][ws_bound] = 80
    ws_display[:, :, 2][ws_bound] = 80

    display_im = utils.create_composite([original_1, original_2, original_3])

    fig, axes = plt.subplots(1, 2, subplot_kw={'xticks': [], 'yticks': []})
    fig.subplots_adjust(hspace=0.3, wspace=0.05)

    # axes[1].imshow(self.sobel_image,interpolation='none',cmap='gray')
    axes[0].imshow(display_im, interpolation='none')
    axes[1].imshow(ws_display, interpolation='none')
    plt.show()
Esempio n. 4
0
def watershed_transformation(image_data, sobel_threshold,
                             amplification_factor):
    '''
    Runs a watershed transform on the main dataset
        1. Create a gradient image using the sobel algorithm
        2. Adjust the gradient image based on given threshold and amplification.
        3. Find the local minimum gradient values and place a marker
        4. Construct watersheds on top of the gradient image starting at the 
            markers.
        5. Recombine neighboring image segments using a region adjacency graph.
    '''
    # If this block has no data, return a placeholder watershed.
    if np.amax(image_data[0]) <= 1:
        return np.zeros(np.shape(image_data))

    # Create a gradient image using a sobel filter
    sobel_image = filters.sobel(image_data[2])

    # Adjust the sobel image based on the given threshold and amp factor.
    upper_threshold = np.amax(sobel_image) / amplification_factor
    if upper_threshold < 0.20:
        upper_threshold = 0.20
    sobel_image = exposure.rescale_intensity(sobel_image,
                                             in_range=(0, upper_threshold),
                                             out_range=(0, 1))

    # Prevent the watersheds from 'leaking' along the sides of the image
    sobel_image[:, 0] = 1
    sobel_image[:, -1] = 1
    sobel_image[0, :] = 1
    sobel_image[-1, :] = 1

    # Set all values in the sobel image that are lower than the
    #   given threshold to zero.
    sobel_image[sobel_image <= sobel_threshold] = 0

    #sobel_copy = np.copy(sobel_image)

    # Find local minimum values in the sobel image by inverting
    #   sobel_image and finding the local maximum values
    inv_sobel = 1 - sobel_image
    local_min = feature.peak_local_max(inv_sobel,
                                       min_distance=2,
                                       indices=False,
                                       num_peaks_per_label=1)
    markers = ndimage.label(local_min)[0]

    # Build a watershed from the markers on top of the edge image
    im_watersheds = morphology.watershed(sobel_image, markers)
    im_watersheds = np.array(im_watersheds, dtype='uint16')
    # Clear gradient image data
    sobel_image = None

    # Find the locations that contain no spectral data
    empty_pixels = np.zeros(np.shape(image_data[0]), dtype='bool')
    empty_pixels[image_data[2] == 0] = True
    # Set all values outside of the image area (empty pixels, usually caused by
    #   orthorectification) to one value, at the end of the watershed list.
    im_watersheds[empty_pixels] = np.amax(im_watersheds) + 1

    # Recombine segments that are adjacent and similar to each other.
    #   Created a region adjacency graph. Create_composite() takes a single list
    #   of bands
    color_im = utils.create_composite(
        [image_data[0], image_data[1], image_data[2]])

    # Clear image data
    image_data = None
    # Create the region adjacency graph based on the color image
    try:
        im_graph = graph.rag_mean_color(color_im, im_watersheds)
    except KeyError:
        pass
    else:
        # Clear color image data
        color_im = None
        # Combine segments that are adjacent and whose pixel intensity
        #   difference is less than 10.
        im_watersheds = graph.cut_threshold(im_watersheds, im_graph, 5.0)

    return im_watersheds
Esempio n. 5
0
def mode_one(segment_list, label_vector, feature_matrix, input_directory, im_type, tds_filename):
    ## Build a list of the images in the input directory
    # for each image in the directory, image list contains the "..._segmented.h5" file if it exists,
    #   and the raw image file if it does not.

    # If there is an existing segment list, note the required image to continue the
    # training set
    if segment_list:
        required_images = get_required_images(segment_list[len(label_vector):])
    else:
        required_images = []

    # Add the images in the provided folder to the image list
    seg_list = list(utils.get_image_paths(input_directory, keyword='segmented.h5', strict=False))

    for ext in utils.valid_extensions:
        raw_list = utils.get_image_paths(input_directory, keyword=ext)
        for raw_im in raw_list:
            if os.path.splitext(raw_im)[0] + "_segmented.h5" not in seg_list:
                seg_list.append(raw_im)

    # Save only the unique entries
    image_list = list(set(seg_list))
    utils.remove_hidden(image_list)

    # Make sure we have all of the required images
    for image in required_images:
        if image in image_list:
            print "Missing required image: {}".format(image)
            quit()

    # **************************************** #
    # For expanding icebridge training set 9.18.18
    target_images = ["2016_07_19_01052.JPG",
                     "2017_07_25_01613.JPG",
                     "2017_07_25_01772.JPG",
                     "2017_07_25_01783.JPG",
                     "2017_07_25_06767.JPG"]
    # **************************************** #

    # As long as there were files in the input directory, loop indefinitely
    # This loop breaks when the training GUI is closed.
    while image_list:

        # Cycle through each image in the list
        for next_image in image_list:

            # If we are out of predetermined segments to classify, start picking
            # images from those in the directory provided
            if len(segment_list) == len(label_vector):
                image_name = os.path.split(next_image)[1]
                # if image_name not in target_images:
                #     print("Skipping {}".format(image_name))
                #     continue
            # Otherwise find the image name from the next unlabeled segment
            else:
                image_name = segment_list[len(label_vector)][0]
                # Convert the image name into the segmented name. This file must
                #   exist to work from an existing tds. That is, we cant resegment the
                #   image, because it will give different results and segment ids will not match.
                image_name = os.path.splitext(image_name)[0] + "_segmented.h5"

            # image_root, image_ext = os.path.splitext(image_name)
            print("Working on image: {}".format(image_name))

            # If the image is already segmented
            if image_name.split('_')[-1] == 'segmented.h5':
                segmented_name = image_name
            # Otherwise image_name should point to a raw image
            else:
                print("Creating segments on provided image...")
                # Preprocess next_image data
                image_data, meta_data = prepare_image(input_directory, image_name, im_type,
                                                      output_path=input_directory, verbose=True)
                # Create image segments
                segmented_name = os.path.splitext(image_name)[0] + '_segmented.h5'
                seg_path = os.path.join(input_directory, segmented_name)
                segment_image(image_data, image_type=im_type, write_results=True,
                              dst_file=seg_path, verbose=True)
                # Convert this entry in image_list to the "..._segmented.h5" name
                image_list.append(segmented_name)
                image_list.remove(next_image)

            h5_file = os.path.join(input_directory, segmented_name)
            # from segment import load_from_disk
            original_image = []
            original_image_dict, im_type = load_from_disk(h5_file, False)
            for sub_image in range(len(original_image_dict[1])):
                # Create a list of image blocks based on the number of bands
                # in the input image.
                # Need to verify this for pan images (ncw 9.17.18):
                if im_type == 'pan':
                    original_image.append(original_image_dict[1])
                if im_type == 'wv02_ms':
                    original_image.append(
                        utils.create_composite([original_image_dict[i][sub_image] for i in range(1,9)],
                                               dtype=c_int)
                    )
                if im_type == 'srgb':
                    original_image.append(
                        utils.create_composite([original_image_dict[i][sub_image] for i in range(1,4)],
                                               dtype=c_int)
                    )

            with h5py.File(h5_file, 'r') as f:
                im_date = f.attrs.get("Image Date")
                watershed_image = f['watershed'][:]

            # Convert the segmented image to c_int datatype. This is needed for the
            # Cython methods that calculate attribute of segments.
            watershed_image = np.ndarray.astype(watershed_image, c_int)

            #### Initializing the GUI
            tW = TrainingWindow(original_image, watershed_image, segment_list,
                                image_name, label_vector, feature_matrix, im_type, im_date,
                                1, tds_filename)
Esempio n. 6
0
                    image_list.remove(next_image)

                h5_file = os.path.join(input_path, segmented_name)
                # from segment import load_from_disk
                original_image = []
                original_image_dict, im_type = load_from_disk(h5_file, False)
                for sub_image in range(len(original_image_dict[1])):
                    # Create a list of image blocks based on the number of bands
                    # in the input image.
                    if im_type == 'wv02_ms':
                        original_image.append(
                            utils.create_composite([
                                original_image_dict[1][sub_image],
                                original_image_dict[2][sub_image],
                                original_image_dict[3][sub_image],
                                original_image_dict[4][sub_image],
                                original_image_dict[5][sub_image],
                                original_image_dict[6][sub_image],
                                original_image_dict[7][sub_image],
                                original_image_dict[8][sub_image]
                            ]))
                    if im_type == 'srgb':
                        original_image.append(
                            utils.create_composite([
                                original_image_dict[1][sub_image],
                                original_image_dict[2][sub_image],
                                original_image_dict[3][sub_image]
                            ]))
                # original_image = utils.create_composite([original_image[1],
                #                                         original_image[2],
                #                                         original_image[3]])
Esempio n. 7
0
def display_image(raw, watershed, classified, type):

    # Save a color
    empty_color = [.1, .1, .1]  #Almost black
    snow_color = [.9, .9, .9]  #Almost white
    pond_color = [.31, .431, .647]  #Blue
    gray_color = [.65, .65, .65]  #Gray
    water_color = [0., 0., 0.]  #Black
    shadow_color = [.100, .545, .0]  #Orange

    custom_colormap = [
        empty_color, snow_color, gray_color, pond_color, water_color,
        shadow_color
    ]
    custom_colormap = colors.ListedColormap(custom_colormap)

    #Making sure there is atleast one of every pixel so the colors map properly (only changes
    # display image, not saved data)
    classified[0][0] = 0
    classified[1][0] = 1
    classified[2][0] = 2
    classified[3][0] = 3
    classified[4][0] = 4
    classified[5][0] = 5

    # Figure that show 3 images: raw, segmented, and classified
    if type == 1:
        # Creating the watershed display image with borders highlighted
        ws_bound = segmentation.find_boundaries(watershed)
        ws_display = utils.create_composite([raw, raw, raw])
        ws_display[:, :, 0][ws_bound] = 255
        ws_display[:, :, 1][ws_bound] = 255
        ws_display[:, :, 2][ws_bound] = 22

        fig, axes = plt.subplots(1, 3, subplot_kw={'xticks': [], 'yticks': []})
        fig.subplots_adjust(left=0.05,
                            right=0.99,
                            bottom=0.05,
                            top=0.90,
                            wspace=0.02,
                            hspace=0.2)

        tnrfont = {'fontname': 'Times New Roman'}

        axes[0].imshow(raw, cmap='gray', interpolation='None')
        axes[0].set_title("Raw Image", **tnrfont)
        axes[1].imshow(ws_display, interpolation='None')
        axes[1].set_title("Image Segments", **tnrfont)
        axes[2].imshow(classified, cmap=custom_colormap, interpolation='None')
        axes[2].set_title("Classification Output", **tnrfont)

    # Figure that shows 2 images: raw and classified.
    if type == 2:
        fig, axes = plt.subplots(1, 2, subplot_kw={'xticks': [], 'yticks': []})
        fig.subplots_adjust(hspace=0.3, wspace=0.05)
        axes[0].imshow(raw, interpolation='None')
        axes[0].set_title("Raw Image")
        axes[1].imshow(classified, cmap=custom_colormap, interpolation='None')
        axes[1].set_title("Classification Output")

    plt.show()
Esempio n. 8
0
def classify_image(input_image, watershed_data, training_dataset, meta_data,
            threads=1, quality_control=False, verbose=False):
    '''
    Run a random forest classification. 
    Input: 
        input_image: preprocessed image data (preprocess.py)
        watershed_image: Image objects created with the segmentation
            algorithm. (segment.py)
        training_dataset: Tuple of training data in the form:
            (label_vector, attribute_matrix)
        meta_data: [im_type, im_date]
    Returns:
        Raster of classified data. 
    '''

    #### Prepare Data and Variables
    num_blocks = len(input_image[1])
    num_bands = len(input_image.keys())
    image_type = meta_data[0]
    image_date = meta_data[1]

    ## Restructure the input data.
    # We are creating a single list where each element of the list is one
    #   block (old: subimage) of the image and is a stack of all bands.  
    image_data = []    # [block:row:column:band]
    for blk in range(num_blocks):
        image_data.append(utils.create_composite(
                [input_image[b][blk] for b in range(1,num_bands+1)]))
    input_image = None

    ## Parse training_dataset input
    label_vector = training_dataset[0]
    training_feature_matrix = training_dataset[1]

    # Method for assessing the quality of the training dataset.
    # quality_control = True
    # if quality_control == True:
    #     debug_tools.test_training(label_vector, training_feature_matrix)
    #     aa = raw_input("Continue? ")
    #     if aa == 'n':
    #         quit()

    #### Construct the random forest decision tree using the training data set
    rfc = RandomForestClassifier(n_estimators=100)
    rfc.fit(training_feature_matrix, label_vector)

    #### Classify each image block
    # Define multiprocessing-safe queues containing data to process
    clsf_block_queue = Queue()
    num_blocks = len(watershed_data)
    im_block_queue = construct_block_queue(image_data, watershed_data, num_blocks)

    # Define the number of threads to create
    NUMBER_OF_PROCESSES = threads
    block_procs = [Process(target=process_block_helper,
                           args=(im_block_queue, clsf_block_queue, image_type, 
                                 image_date, rfc))
                   for _ in range(NUMBER_OF_PROCESSES)]

    # Start the worker processes. 
    for proc in block_procs:
        # Add a stop command to the end of the queue for each of the 
        #   processes started. This will signal for the process to stop. 
        im_block_queue.put('STOP')
        # Start the process
        proc.start()

    # Display a progress bar
    if verbose:
        try:
            from tqdm import tqdm
        except ImportError:
            print "Install tqdm to display progress bar."
            verbose = False
        else:
            pbar = tqdm(total=num_blocks, unit='block')

    # Each process adds the classification results to clsf_block_queue, when it 
    #   finishes a row. Adds 'None' when there are not more rows left 
    #   in the queue. 
    # This loop continues as long as all of the processes have not finished
    #   (i.e. fewer than NUMBER_OF_PROCESSES have returned None). When a row is 
    #   added to the queue, the tqdm progress bar updates.

    # Initialize the output dataset as an empty list of length = input dataset
    #   This needs to be initialized since blocks will be added non-sequentially
    clsf_block_list = [None for _ in range(num_blocks)]
    finished_threads = 0
    while finished_threads < NUMBER_OF_PROCESSES:
        if not clsf_block_queue.empty():
            val = clsf_block_queue.get()
            if val == None:
                finished_threads += 1
            else:
                block_num = val[0]
                segmnt_data = val[1]
                clsf_block_list[block_num] = segmnt_data
                if verbose: pbar.update()

    # Close the progress bar
    if verbose: 
        pbar.close()
        print "Finished Processing. Closing threads..."

    # Join all of the processes back together
    for proc in block_procs:
        proc.join()

    return clsf_block_list
Esempio n. 9
0
def classify_image(input_image,
                   watershed_data,
                   training_dataset,
                   meta_data,
                   threads=2,
                   quality_control=False,
                   debug_flag=False,
                   verbose=False):
    '''
    Run a random forest classification. 
    Input: 
        input_image: preprocessed image data (preprocess.py)
        watershed_image: Image objects created with the segmentation 
            algorithm. (segment.py)
        training_dataset: Tuple of training data in the form:
            (label_vector, attribute_matrix)
        meta_data: [im_type, im_date]
    Returns:
        Raster of classified data. 
    '''

    #### Prepare Data and Variables
    num_blocks = len(input_image[1])
    num_bands = len(input_image.keys())
    image_type = meta_data[0]
    image_date = meta_data[1]

    ## Restructure the input data.
    # We are creating a single list where each element of the list is one
    #   block (old: subimage) of the image and is a stack of all bands.
    image_data = []  # [block:row:column:band]
    for blk in range(num_blocks):
        image_data.append(
            utils.create_composite(
                [input_image[b][blk] for b in range(1, num_bands + 1)]))
    input_image = None

    # watershed_image = input_file['watershed'][:]
    # watershed_dimensions = input_file['dimensions'][:]
    # num_x_subimages = dimensions[0]
    # num_y_subimages = dimensions[1]

    ## Parse training_dataset input
    label_vector = training_dataset[0]
    training_feature_matrix = training_dataset[1]

    # im_type = input_file.attrs.get('Image Type')
    # im_date = input_file.attrs.get('Image Date')

    #Method for assessing the quality of the training dataset.
    if quality_control == True:
        test_training(label_vector, training_feature_matrix)
        aa = raw_input("Continue? ")
        if aa == 'n':
            quit()

    # # If there is no information in this image file, save a dummy classified image and exit
    # # This can often happen depending on the original image dimensions and the amount it was split
    # if np.sum(band_1) == 0:
    #     classified_image_path = os.path.join(output_filepath, output_filename + '_classified_image.png')
    #     outfile = h5py.File(os.path.join(output_filepath, output_filename + '_classified.h5'),'w')

    #     if im_type == 'wv02_ms':
    #             empty_bands = np.zeros(np.shape(band_1)[0],np.shape(band_1)[1],8)
    #                     empty_image = utils.compile_subimages(empty_bands, num_x_subimages, num_y_subimages, 8)
    #             elif im_type == 'srgb':
    #                     empty_bands = np.zeros(np.shape(band_1)[0],np.shape(band_1)[1],3)
    #                     empty_image = utils.compile_subimages(empty_bands, num_x_subimages, num_y_subimages, 3)
    #             elif im_type == 'pan':
    #                     empty_image = np.zeros(np.shape(band_1))

    #     outfile.create_dataset('classified', data=empty_image,compression='gzip',compression_opts=9)
    #     outfile.create_dataset('original', data=empty_image,compression='gzip',compression_opts=9)
    #     outfile.close()
    #     # return a 1x5 array with values of one for the pixel counts
    #     return output_filename, np.ones(5)

    #### Construct the random forest decision tree using the training data set
    rfc = RandomForestClassifier()
    rfc.fit(training_feature_matrix, label_vector)

    #### Classify each image block
    # Define multiprocessing-safe queues containing data to process
    clsf_block_queue = Queue()
    num_blocks = len(watershed_data)
    im_block_queue = construct_block_queue(image_data, watershed_data,
                                           num_blocks)

    # Define the number of threads to create
    NUMBER_OF_PROCESSES = threads
    block_procs = [
        Process(target=process_block_helper,
                args=(im_block_queue, clsf_block_queue, image_type, image_date,
                      rfc)) for _ in range(NUMBER_OF_PROCESSES)
    ]

    # Start the worker processes.
    for proc in block_procs:
        # Add a stop command to the end of the queue for each of the
        #   processes started. This will signal for the process to stop.
        im_block_queue.put('STOP')
        # Start the process
        proc.start()

    # Display a progress bar
    if verbose:
        try:
            from tqdm import tqdm
        except ImportError:
            print "Install tqdm to display progress bar."
            verbose = False
        else:
            pbar = tqdm(total=num_blocks, unit='block')

    # Each process adds the classification results to clsf_block_queue, when it
    #   finishes a row. Adds 'None' when there are not more rows left
    #   in the queue.
    # This loop continues as long as all of the processes have not finished
    #   (i.e. fewer than NUMBER_OF_PROCESSES have returned None). When a row is
    #   added to the queue, the tqdm progress bar updates.

    # Initialize the output dataset as an empty list of length = input dataset
    #   This needs to be initialized since blocks will be added non-sequentially
    clsf_block_list = [None for _ in range(num_blocks)]
    finished_threads = 0
    while finished_threads < NUMBER_OF_PROCESSES:
        if not clsf_block_queue.empty():
            val = clsf_block_queue.get()
            if val == None:
                finished_threads += 1
            else:
                block_num = val[0]
                segmnt_data = val[1]
                clsf_block_list[block_num] = segmnt_data
                if verbose: pbar.update()

    # Close the progress bar
    if verbose:
        pbar.close()
        print "Finished Processing. Closing threads..."

    # Join all of the processes back together
    for proc in block_procs:
        proc.join()

    return clsf_block_list

    # Lite version: Save only the classified output, and do not save the original image data
    compiled_classified = utils.compile_subimages(classified_image,
                                                  num_x_subimages,
                                                  num_y_subimages, 1)

    if verbose: print "Saving..."

    with h5py.File(
            os.path.join(output_filepath, output_filename + '_classified.h5'),
            'w') as outfile:
        outfile.create_dataset('classified',
                               data=compiled_classified,
                               compression='gzip',
                               compression_opts=9)

    #### Count the number of pixels that were in each classification category.
    sum_snow, sum_gray_ice, sum_melt_ponds, sum_open_water, sum_shadow = utils.count_features(
        compiled_classified)
    pixel_counts = [
        sum_snow, sum_gray_ice, sum_melt_ponds, sum_open_water, sum_shadow
    ]

    # Clear the image datasets from memory
    compiled_classified = None
    input_image = None
    watershed_image = None

    cur_image = None
    cur_ws = None
    entropy_image = None

    if verbose: print "Done."

    return output_filename, pixel_counts