def mosaic_images(img_list, output):
    if os.path.isfile(output) is True:
        print('warning, %s already exist, skip'%output)
        return True

    args_list=['gdal_merge.py','-init','0','-a_nodata','0','-o',output]
    args_list.extend(img_list)

    if basic.exec_command_args_list_one_file(args_list,output) is False:
        raise IOError('output not exist')
    return True
Beispiel #2
0
def convert_training_examples_from_shp_to_raster(shp_path, raster_path):
    """
    convert training examples which stored in shape file to a raster file,
    so these training examples can be shared by other shape file
    :param shp_path: shape file path
    :param raster_path: raster data path (the output data type is Byte)
    :return:True if successful, False otherwise
    """
    if io_function.is_file_exist(shp_path) is False:
        return False

    # convert class label (string) to class index (integer)
    class_int_field = 'class_int'
    class_label_field = 'class'
    class_int_list = []
    shp_operation_obj = shape_opeation()
    if shp_operation_obj.has_field(shp_path, class_int_field) is False:
        if shp_operation_obj.has_field(shp_path, class_label_field) is False:
            basic.outputlogMessage('%s do not contain training examples' %
                                   shp_path)
        else:
            # convert class label (string) to class index (integer) and create a new field name 'class_int'
            attribute = ['class']
            class_label_list = shp_operation_obj.get_shape_records_value(
                shp_path, attribute)
            classLabel.output_classLabel_to_txt('class_label_index.txt')
            for label in class_label_list:
                class_int_list.append(classLabel.get_class_index(label[0]))
            shp_operation_obj.add_one_field_records_to_shapefile(
                shp_path, class_int_list, class_int_field)

    # check again whether there is 'class_int'
    if shp_operation_obj.has_field(shp_path, class_int_field) is False:
        basic.outputlogMessage(
            "Error: There is not class_int field in the shape file")
        assert False

    # convert training example in shape file to raster
    res = parameters.get_input_image_rescale()
    layername = os.path.splitext(os.path.basename(shp_path))[0]
    args_list = ['gdal_rasterize', '-a', class_int_field, '-ot', 'Byte', \
                 '-tr',str(res),str(res),'-l',layername,shp_path,raster_path]
    result = basic.exec_command_args_list_one_file(args_list, raster_path)
    if os.path.getsize(result) < 1:
        return False
    return True
def remove_polygons_outside_extent(input_shp, extent_shp, output):
    '''
    remove polygons not in the extent
    :param input_shp:
    :param extent_shp:
    :param output:
    :return:
    '''

    # check projection, must be the same
    input_proj4 = map_projection.get_raster_or_vector_srs_info_proj4(input_shp)
    extent_proj4 = map_projection.get_raster_or_vector_srs_info_proj4(extent_shp)
    if input_proj4 != extent_proj4:
        raise ValueError('error, projection insistence between %s and %s'%(input_shp, extent_shp))

    ## -progress: Only works if input layers have the "fast feature count" capability.
    # ogr2ogr - progress - clipsrc ${extent_shp} ${save_shp} ${input_shp}
    arg_list = ['ogr2ogr', '-progress', '-clipsrc', extent_shp, output, input_shp]
    return basic.exec_command_args_list_one_file(arg_list, output)
def zonal_stats_one_polygon(idx, polygon, image_tiles, img_tile_polygons, stats, nodata=None,range=None,
                            band = 1,all_touched=True):

    overlap_index = vector_gpd.get_poly_index_within_extent(img_tile_polygons, polygon)
    image_list = [image_tiles[item] for item in overlap_index]

    if len(image_list) == 1:
        out_image, out_tran,nodata = raster_io.read_raster_in_polygons_mask(image_list[0], polygon, nodata=nodata,
                                                                     all_touched=all_touched,bands=band)
    elif len(image_list) > 1:
        # for the case it overlap more than one raster, need to produce a mosaic
        tmp_saved_files = []
        for k_img, image_path in enumerate(image_list):

            # print(image_path)
            tmp_save_path = os.path.splitext(os.path.basename(image_path))[0] + '_subset_poly%d'%idx +'.tif'
            _, _,nodata = raster_io.read_raster_in_polygons_mask(image_path, polygon,all_touched=all_touched,nodata=nodata,
                                                          bands=band, save_path=tmp_save_path)
            tmp_saved_files.append(tmp_save_path)

        # mosaic files in tmp_saved_files
        save_path = 'raster_for_poly%d.tif'%idx
        mosaic_args_list = ['gdal_merge.py', '-o', save_path,'-n',str(nodata),'-a_nodata',str(nodata)]
        mosaic_args_list.extend(tmp_saved_files)
        if basic.exec_command_args_list_one_file(mosaic_args_list,save_path) is False:
            raise IOError('error, obtain a mosaic (%s) failed'%save_path)

        # read the raster
        out_image, out_nodata = raster_io.read_raster_one_band_np(save_path,band=band)
        # remove temporal raster
        tmp_saved_files.append(save_path)
        for item in tmp_saved_files:
            io_function.delete_file_or_dir(item)

    else:
        basic.outputlogMessage('warning, cannot find raster for %d (start=0) polygon'%idx)
        return None

    # do calculation
    return array_stats(out_image, stats, nodata,range=range)
 def get_polygon_shape_info(self, input_shp, out_box, bupdate=False):
     """
     get Oriented minimum bounding box for a polygon shapefile,
     and update the shape information based on oriented minimum bounding box to
     the input shape file
     :param input_shp: input polygon shape file
     :param out_box: output Oriented minimum bounding box shape file
     :param bupdate: indicate whether update the original input shapefile
     :return:True is successful, False Otherwise
     """
     if io_function.is_file_exist(input_shp) is False:
         return False
     args_list = ['qgis_function.py', input_shp, out_box]
     if basic.exec_command_args_list_one_file(args_list, out_box) is False:
         basic.outputlogMessage(
             'get polygon shape information of %s failed' % input_shp)
         return False
     else:
         basic.outputlogMessage(
             'get polygon shape information of %s completed, output file is %s'
             % (input_shp, out_box))
         return True
Beispiel #6
0
def get_sub_image(idx,selected_polygon, image_tile_list, image_tile_bounds, save_path, dstnodata, brectangle ):
    '''
    get a mask image based on a selected polygon, it may cross two image tiles
    :param selected_polygon: selected polygons
    :param image_tile_list: image list
    :param image_tile_bounds: the boxes of images in the list
    :param save_path: save path
    :param brectangle: if brectangle is True, crop the raster using bounds, else, use the polygon
    :return: True is successful, False otherwise
    '''

    # find the images which the center polygon overlap (one or two images)
    img_index = get_overlap_image_index([selected_polygon], image_tile_bounds)
    if len(img_index) < 1:
        basic.outputlogMessage(
            'Warning, %dth polygon do not overlap any image tile, please check ' #and its buffer area
            '(1) the shape file and raster have the same projection'
            'and (2) this polygon is in the extent of images' % idx)
        return False

    image_list = [image_tile_list[item] for item in img_index]

    # check it cross two or more images
    if len(image_list) == 1:
        # for the case that the polygon only overlap one raster
        with rasterio.open(image_list[0]) as src:
            polygon_json = mapping(selected_polygon)

            # not necessary
            # overlap_win = rasterio.features.geometry_window(src, [polygon_json], pad_x=0, pad_y=0, north_up=True, rotated=False,
            #                               pixel_precision=3)

            if brectangle:
                # polygon_box = selected_polygon.bounds
                polygon_json = mapping(selected_polygon.envelope) #shapely.geometry.Polygon([polygon_box])

            # crop image and saved to disk
            out_image, out_transform = mask(src, [polygon_json], nodata=dstnodata, all_touched=True, crop=True)

            # test: save it to disk
            out_meta = src.meta.copy()
            out_meta.update({"driver": "GTiff",
                             "height": out_image.shape[1],
                             "width": out_image.shape[2],
                             "transform": out_transform})  # note that, the saved image have a small offset compared to the original ones (~0.5 pixel)
            with rasterio.open(save_path, "w", **out_meta) as dest:
                dest.write(out_image)
        pass
    else:
        # for the case it overlap more than one raster, need to produce a mosaic
        tmp_saved_files = []

        for k_img,image_path in enumerate(image_list):
            with rasterio.open(image_path) as src:
                polygon_json = mapping(selected_polygon)
                if brectangle:
                    # polygon_box = selected_polygon.bounds
                    polygon_json = mapping(selected_polygon.envelope)  # shapely.geometry.Polygon([polygon_box])

                # crop image and saved to disk
                out_image, out_transform = mask(src, [polygon_json], nodata=dstnodata, all_touched=True, crop=True)

                tmp_saved = os.path.splitext(save_path)[0] +'_%d'%k_img + os.path.splitext(save_path)[1]
                # test: save it to disk
                out_meta = src.meta.copy()
                out_meta.update({"driver": "GTiff",
                                 "height": out_image.shape[1],
                                 "width": out_image.shape[2],
                                 "transform": out_transform})  # note that, the saved image have a small offset compared to the original ones (~0.5 pixel)
                with rasterio.open(tmp_saved, "w", **out_meta) as dest:
                    dest.write(out_image)
                tmp_saved_files.append(tmp_saved)

        # mosaic files in tmp_saved_files
        mosaic_args_list = ['gdal_merge.py', '-o', save_path,'-n',str(dstnodata),'-a_nodata',str(dstnodata)]
        mosaic_args_list.extend(tmp_saved_files)
        if basic.exec_command_args_list_one_file(mosaic_args_list,save_path) is False:
            raise IOError('error, obtain a mosaic (%s) failed'%save_path)

        # # for test
        # if idx==13:
        #     raise ValueError('for test')

        # remove the tmp files
        for tmp_file in tmp_saved_files:
            io_function.delete_file_or_dir(tmp_file)

    # if it will output a very large image (10000 by 10000 pixels), then raise a error

    return True
Beispiel #7
0
def main(options, args):

    # get multi-temporal shapefile list
    para_file = options.para_file
    b_remove = parameters.get_bool_parameters_None_if_absence(
        para_file, 'b_remove_polygons_using_multitemporal_results')
    # exit
    if b_remove is None or b_remove is False:
        basic.outputlogMessage(
            'Warning, b_remove_polygons_using_multitemporal_results not set or is NO'
        )
        return True

    shp_dir = args[0]
    file_pattern = args[1]
    polyon_shps_list = io_function.get_file_list_by_pattern(
        shp_dir, file_pattern)
    if len(polyon_shps_list) < 2:
        raise ValueError(
            'Error, less than two shapefiles, cannot conduct multi-polygon anlysis'
        )

    # make polyon_shps_list in order: I0 to In
    polyon_shps_list.sort(
        key=lambda x: int(re.findall('I\d+', os.path.basename(x))[0][1:]))

    # print(polyon_shps_list)
    # sys.exit()

    # check projection of the shape file, should be the same
    new_shp_proj4 = map_projection.get_raster_or_vector_srs_info_proj4(
        polyon_shps_list[0])
    for idx in range(len(polyon_shps_list) - 1):
        shp_proj4 = map_projection.get_raster_or_vector_srs_info_proj4(
            polyon_shps_list[idx + 1])
        if shp_proj4 != new_shp_proj4:
            raise ValueError('error, projection insistence between %s and %s' %
                             (new_shp_proj4, shp_proj4))

    import remove_nonActive_thawSlumps
    import polygons_change_analyze

    # polygon change analysis
    polygons_change_analyze.cal_multi_temporal_iou_and_occurrence(
        polyon_shps_list, para_file)

    # remove non active polygons
    remove_nonActive_thawSlumps.remove_non_active_thaw_slumps(
        polyon_shps_list, para_file)

    # back up files and conduct evaluation
    for idx, shp_path in enumerate(polyon_shps_list):

        # evaluation files
        shp_rmTimeiou = io_function.get_name_by_adding_tail(
            shp_path, 'rmTimeiou')
        basic.outputlogMessage('(%d/%d) evaluation of %s' %
                               (idx, len(polyon_shps_list), shp_rmTimeiou))

        # evaluation
        args_list = [
            os.path.join(deeplabRS, 'evaluation_result.py'), '-p', para_file,
            shp_rmTimeiou
        ]
        if basic.exec_command_args_list_one_file(
                args_list, 'evaluation_report.txt') is False:
            return False

        I_idx_str = re.findall('I\d+', os.path.basename(shp_rmTimeiou))

        old_eva_report = io_function.get_file_list_by_pattern(
            shp_dir, I_idx_str[0] + '*eva_report*' + '.txt')
        old_eva_report = [
            item for item in old_eva_report if 'rmTimeiou' not in item
        ]

        old_eva_report_name = old_eva_report[0]

        eva_report_name = io_function.get_name_by_adding_tail(
            old_eva_report_name, 'rmTimeiou')
        # io_function.move_file_to_dst(old_eva_report,backup_eva_report)
        # io_function.move_file_to_dst('evaluation_report.txt', old_eva_report)
        io_function.move_file_to_dst('evaluation_report.txt',
                                     eva_report_name,
                                     overwrite=True)

        # back up the shape files (no_need)

    basic.outputlogMessage(
        'Finish removing polygons using multi-temporal mapping results')