示例#1
0
def compute_color2d_superpixels_features(image,
                                         dict_features,
                                         sp_size=30,
                                         sp_regul=0.2):
    """ segment image into superpixels and estimate features per superpixel

    :param ndarray image: input RGB image
    :param dict(list(str)) dict_features: list of features to be extracted
    :param int sp_size: initial size of a superpixel(meaning edge length)
    :param float sp_regul: regularisation in range(0;1) where "0" gives elastic
           and "1" nearly square segments
    :return list(list(int)), [[floats]]: superpixels and related of features
    """
    assert sp_regul > 0., 'slic. regularisation must be positive'
    logging.debug('run Superpixel clustering.')
    slic = segment_slic_img2d(image,
                              sp_size=sp_size,
                              relative_compact=sp_regul)
    # plt.figure(), plt.imshow(slic)

    logging.debug('extract slic/superpixels features.')
    features, _ = compute_selected_features_img2d(image, slic, dict_features)
    logging.debug('list of features RAW: %r', features.shape)
    features[np.isnan(features)] = 0

    # if fts_norm:
    #     logging.debug('norm all features.')
    #     features, _ = seg_fts.norm_features(features)
    #     logging.debug('list of features NORM: %s', repr(features.shape))
    return slic, features
示例#2
0
def load_image_annot_compute_features_labels(idx_row,
                                             params,
                                             show_debug_imgs=SHOW_DEBUG_IMAGES
                                             ):
    """ load image and annotation, and compute superpixel features and labels

    :param (int, {...}) idx_row: row from table with paths
    :param {str: ...} params: segmentation parameters
    :param bool show_debug_imgs: whether show debug images
    :return (...):
    """
    def _path_out_img(params, dir_name, name):
        return os.path.join(params['path_exp'], dir_name, name + '.png')

    idx, row = idx_row
    idx_name = get_idx_name(idx, row['path_image'])
    img = load_image(row['path_image'], params['img_type'])
    annot = load_image(row['path_annot'], '2d_segm')
    logging.debug('.. processing: %s', idx_name)
    assert img.shape[:2] == annot.shape[:2], \
        'individual size of image %s and seg_pipe %s for "%s" - "%s"' % \
        (repr(img.shape), repr(annot.shape), row['path_image'], row['path_annot'])
    if show_debug_imgs:
        plt.imsave(_path_out_img(params, FOLDER_IMAGE, idx_name),
                   img,
                   cmap=plt.cm.gray)
        plt.imsave(_path_out_img(params, FOLDER_ANNOT, idx_name), annot)

    # duplicate gray band to be as rgb
    # if img.ndim == 2:
    #     img = np.rollaxis(np.tile(img, (3, 1, 1)), 0, 3)
    slic = seg_spx.segment_slic_img2d(img,
                                      sp_size=params['slic_size'],
                                      rltv_compact=params['slic_regul'])
    img = tl_data.convert_img_color_from_rgb(img,
                                             params.get('clr_space', 'rgb'))
    logging.debug('computed SLIC with %i labels', slic.max())
    if show_debug_imgs:
        img_rgb = use_rgb_image(img)
        img_slic = segmentation.mark_boundaries(img_rgb,
                                                slic,
                                                color=(1, 0, 0),
                                                mode='subpixel')
        plt.imsave(_path_out_img(params, FOLDER_SLIC, idx_name),
                   np.clip(img_slic, 0, 1))
    slic_label_hist = seg_label.histogram_regions_labels_norm(slic, annot)
    labels = np.argmax(slic_label_hist, axis=1)
    slic_annot = labels[slic]
    if show_debug_imgs:
        plt.imsave(_path_out_img(params, FOLDER_SLIC_ANNOT, idx_name),
                   np.clip(slic_annot, 0, slic_annot.max()))

    features, feature_names = seg_fts.compute_selected_features_img2d(
        img, slic, params['features'])
    return idx_name, img, annot, slic, features, labels, \
           slic_label_hist, feature_names
示例#3
0
def compute_color2d_superpixels_features(image,
                                         clr_space='rgb',
                                         sp_size=30,
                                         sp_regul=0.2,
                                         dict_features=FTS_SET_SIMPLE,
                                         fts_norm=True):
    """ segment image into superpixels and estimate features per superpixel

    :param ndarray image: input RGB image
    :param str clr_space: chose the color space
    :param int sp_size: initial size of a superpixel(meaning edge lenght)
    :param float sp_regul: regularisation in range(0;1) where "0" gives elastic
           and "1" nearly square segments
    :param {str: [str]} dict_features: list of features to be extracted
    :param bool fts_norm: weather nomalise features
    :return [[int]], [[floats]]: superpixels and related of features
    """
    assert sp_regul > 0., 'slic. regularisation must be positive'
    logging.debug('run Superpixel clustering.')
    slic = seg_sp.segment_slic_img2d(image,
                                     sp_size=sp_size,
                                     rltv_compact=sp_regul)
    # plt.figure(), plt.imshow(slic)

    logging.debug('extract slic/superpixels features.')
    image = convert_img_color_space(image, clr_space)
    features, _ = seg_fts.compute_selected_features_img2d(
        image, slic, dict_features)
    logging.debug('list of features RAW: %s', repr(features.shape))
    features[np.isnan(features)] = 0

    if fts_norm:
        logging.debug('norm all features.')
        features, _ = seg_fts.norm_features(features)
        logging.debug('list of features NORM: %s', repr(features.shape))
    return slic, features
示例#4
0
def compute_edge_weights(segments,
                         image=None,
                         features=None,
                         proba=None,
                         edge_type=''):
    """
    pp 32, http://www.coe.utah.edu/~cs7640/readings/graph_cuts_intro.pdf
    exp(- norm value diff) * (geom dist vertex)**-1

    :param ndarry segments: superpixels
    :param ndarry image: input image
    :param ndarry features: features for each segment (superpixel)
    :param ndarry proba: probability of each superpixel and class
    :param str edge_type: contains edge type, if 'model', after '_' you can
        specify the metric, eg. 'model_l2'
    :return [[int, int]], [float]:

    >>> segments = np.array([[0] * 3 + [1] * 5 + [2] * 4,
    ...                      [4] * 4 + [5] * 5 + [6] * 3])
    >>> np.random.seed(0)
    >>> img = np.random.random(segments.shape + (3,)) * 255
    >>> features = np.random.random((segments.max() + 1, 15)) * 10
    >>> proba = np.random.random((segments.max() + 1, 2))
    >>> edges, weights = compute_edge_weights(segments)
    >>> edges.tolist()
    [[0, 1], [1, 2], [0, 4], [1, 4], [1, 5], [2, 5], [4, 5], [2, 6], [5, 6]]
    >>> np.round(weights, 2).tolist()
    [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
    >>> edges, weights = compute_edge_weights(segments, image=img,
    ...                                        edge_type='spatial')
    >>> np.round(weights, 3).tolist()
    [0.776, 0.69, 2.776, 0.853, 2.194, 0.853, 0.69, 2.776, 0.776]
    >>> edges, weights = compute_edge_weights(segments, image=img,
    ...                                        edge_type='color')
    >>> np.round(weights, 3).tolist()
    [0.06, 0.002, 0.001, 0.001, 0.001, 0.009, 0.001, 0.019, 0.044]
    >>> edges, weights = compute_edge_weights(segments, features=features,
    ...                                        edge_type='features')
    >>> np.round(weights, 3).tolist()
    [0.031, 0.005, 0.051, 0.032, 0.096, 0.013, 0.018, 0.033, 0.013]
    >>> edges, weights = compute_edge_weights(segments, proba=proba,
    ...                                        edge_type='model')
    >>> np.round(weights, 3).tolist()
    [0.001, 0.028, 1.122, 0.038, 0.117, 0.688, 0.487, 1.152, 0.282]
    """
    logging.debug('extraction segment connectivity...')
    _, edges = get_vertexes_edges(segments)
    # convert variables
    edges = np.array(edges, dtype=np.int32)
    logging.debug('graph edges %r', edges.shape)

    if edge_type.startswith('model'):
        assert proba is not None, '"proba" is required'
        metric = edge_type.split('_')[-1] if '_' in edge_type else 'lT'
        edge_weights = compute_edge_model(edges, proba, metric)
    elif edge_type == 'color':
        assert image is not None, '"image" is required'
        image_float = np.array(image, dtype=float)
        if np.max(image) > 1:
            image_float /= 255.
        color, _ = compute_selected_features_img2d(image_float, segments,
                                                   {'color': ['mean']})
        vertex_1 = color[edges[:, 0]]
        vertex_2 = color[edges[:, 1]]
        dist = metrics.pairwise.paired_manhattan_distances(vertex_1, vertex_2)
        weights = dist.astype(float) / (2 * np.std(dist)**2)
        edge_weights = np.exp(-weights)
    elif edge_type == 'features':
        assert features is not None, '"features" is required'
        features_norm = preprocessing.StandardScaler().fit_transform(features)
        vertex_1 = features_norm[edges[:, 0]]
        vertex_2 = features_norm[edges[:, 1]]
        dist = metrics.pairwise.paired_euclidean_distances(vertex_1, vertex_2)
        weights = dist.astype(float) / (2 * np.std(dist)**2)
        edge_weights = np.exp(-weights)
    else:
        edge_weights = np.ones(len(edges))

    edge_weights = np.array(edge_weights, dtype=float)
    if edge_type in ['model', 'features', 'color', 'spatial']:
        centres = superpixel_centers(segments)
        spatial = compute_spatial_dist(centres, edges, relative=True)
        edge_weights /= spatial

    # set the threshold for min edge weight
    min_weight = 1. / MIN_MAX_EDGE_WEIGHT
    max_weight = MIN_MAX_EDGE_WEIGHT
    edge_weights[edge_weights < min_weight] = min_weight
    edge_weights[edge_weights > max_weight] = max_weight
    return edges, edge_weights
def segment_image(imgs_idx_path, params, classif, path_out, path_visu=None,
                  show_debug_imgs=SHOW_DEBUG_IMAGES):
    """ perform image segmentation on input image with given paramters
    and trained classifier, and save results

    :param (int, str) imgs_idx_path:
    :param {str: ...} params: segmentation parameters
    :param obj classif: trained classifier
    :param str path_out: path for output
    :param str path_visu: the existing patch means export also visualisation
    :return (str, ndarray, ndarray):
    """
    idx, path_img = parse_imgs_idx_path(imgs_idx_path)
    logging.debug('segmenting image: "%s"', path_img)
    idx_name = get_idx_name(idx, path_img)
    img = load_image(path_img, params['img_type'])
    slic = seg_spx.segment_slic_img2d(img, sp_size=params['slic_size'],
                                            rltv_compact=params['slic_regul'])
    img = seg_pipe.convert_img_color_space(img, params.get('clr_space', 'rgb'))
    features, _ = seg_fts.compute_selected_features_img2d(img, slic,
                                                          params['features'])
    labels = classif.predict(features)
    segm = labels[slic]
    path_img = os.path.join(path_out, idx_name + '.png')
    logging.debug('export segmentation: %s', path_img)
    img_seg = Image.fromarray(segm.astype(np.uint8))
    img_seg.convert('L').save(path_img)
    # io.imsave(path_img, segm)

    # plt.imsave(os.path.join(path_out, idx_name + '_rgb.png'), seg_pipe)
    if path_visu is not None and os.path.isdir(path_visu):
        export_draw_image_segm_contour(img, segm, path_visu, idx_name)

    try:  # in case some classiefier do not support predict_proba
        proba = classif.predict_proba(features)
        segm_soft = proba[slic]
        path_npz = os.path.join(path_out, idx_name + '.npz')
        np.savez_compressed(path_npz, segm_soft)
    except Exception:
        logging.warning('classif: %s not support predict_proba(.)',
                        repr(classif))
        proba = None
        segm_soft = None

    # if probabilities was not estimated of GC regul. is zero
    if proba is not None and params['gc_regul'] > 0:
        gc_regul = params['gc_regul']
        if params['gc_use_trans']:
            label_penalty = seg_gc.compute_pairwise_cost_from_transitions(
                                                params['label_transitions'])
            gc_regul = (gc_regul * label_penalty)
        labels_gc = seg_gc.segment_graph_cut_general(slic, proba, img, features,
                                     gc_regul, edge_type=params['gc_edge_type'])
        # labels_gc = seg_gc.segment_graph_cut_simple(slic, proba, gc_regul)
        segm_gc = labels_gc[slic]
        # relabel according classif classes
        segm_gc = classif.classes_[segm_gc]

        path_img = os.path.join(path_out, idx_name + '_gc.png')
        logging.debug('export segmentation: %s', path_img)
        img_seg_gc = Image.fromarray(segm_gc.astype(np.uint8))
        img_seg_gc.convert('L').save(path_img)
        # io.imsave(path_img, segm_gc)

        if path_visu is not None and os.path.isdir(path_visu):
            export_draw_image_segm_contour(img, segm_gc, path_visu,
                                           idx_name, '_gc')

            if show_debug_imgs:
                labels_map = np.argmax(proba, axis=1)
                plt.imsave(os.path.join(path_visu, idx_name + '_map.png'),
                           labels_map[slic])
                if not segm_soft is None:
                    for lb in range(segm_soft.shape[2]):
                        uc_name = idx_name + '_gc_unary-lb%i.png' % lb
                        plt.imsave(os.path.join(path_visu, uc_name),
                                   segm_soft[:, :, lb], vmin=0., vmax=1.,
                                   cmap=plt.cm.Greens)
    else:
        segm_gc = np.zeros(segm.shape)
    # gc.collect(), time.sleep(1)
    return idx_name, segm, segm_gc