fast slic 算法

原图:

效果图:

from fast_slic import Slic
from fast_slic.avx2 import SlicAvx2
from skimage import segmentation, color
import matplotlib.pyplot as plt
import imutils
import cv2
image = cv2.imread("fish.jpg")
image = imutils.resize(image, width=300)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

slic = SlicAvx2(num_components=12, compactness=10, subsample_stride=1)
n_clusters = len(slic.slic_model.clusters)     # The cluster information of superpixels.

# use pre-defined centroids
centers_w = [20, 70, 120, 170, 220, 270] * 2
centers_h = [40] * 6 + [80] * 6
new_clusters = slic.slic_model.clusters.copy()
print(len(new_clusters))
for k in range(0, len(new_clusters)):
    cluster = new_clusters[k]
    cluster['yx'] = (centers_h[k], centers_w[k])
    cluster['number'] = k
slic.slic_model.clusters = new_clusters # The cluster information of superpixels.
# print('after center assignment', slic.slic_model.clusters)

# iterate only once
slic_result = slic.iterate(image, 1) # Cluster Map

# plot results
fig, ax_arr = plt.subplots(1, 2)
ax1, ax2 = ax_arr.ravel()

# show centers in image
for cluster in new_clusters:
    label = cluster['number']
    center = cluster['yx']
    #cv2.circle(image, (int(center[1]), int(center[0])), 3, [255, 0, 255], -1)
    #cv2.putText(image, str(label), (int(center[1]), int(center[0])), cv2.FONT_HERSHEY_PLAIN, 2, [255, 0, 255], 2)
ax1.imshow(segmentation.mark_boundaries(image, slic_result))

ax2.imshow(slic_result)
plt.show()

another sample:

这回是需要一个mask来指定哪些区域不画裂纹

fastslic虽然很快,但是处理mask的函数要自己写,同时没有outline

"""
 -*- coding: utf-8 -*-
 author: Hao Hu
 @date   2022/3/6 3:40 PM
"""
import numpy as np
import os
# Much faster than the standard class
from fast_slic.avx2 import SlicAvx2
import maskslic as seg
import os.path as osp
from tqdm import tqdm
import cv2
from skimage import segmentation
"""超像素由一系列位置相邻且颜色、亮度、纹理等特征相似的像素点组成的小区域。
这些小区域大多保留了进一步进行图像分割的有效信息,且一般不会破坏图像中物体的边界信息,
用少量的超像素代替大量像素表达图像特征,降低了图像处理的复杂度,
一般作为分割算法的预处理步骤。"""

def get_ori_list(ori_folder):
    img_list = os.listdir(ori_folder)
    ori_list = []
    check_list = ['copper', 'bg', 'check', 'dust']
    for img_name in img_list:
        flag = 0
        for sample in check_list:
            if sample in img_name:
                flag = 1
                break
        if flag == 0:
            ori_list.append(osp.join(ori_folder, img_name))
        if len(ori_list) > 50:
            break
    return ori_list



def use_mask_to_get_two_areas(mask,end_result,image):
    """通过将指定mask来指定不画裂纹的区域"""
    where_0 = np.where(mask == False)
    end_result[where_0] = image[where_0]/255
    return end_result


def use_fast_slic_to_get_edge(img_path,mask_path,end_path):
    image = cv2.imread(img_path)
    # image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    mask_image = cv2.imread(mask_path)
    img_R = mask_image[:, :, 0]
    mask = img_R > 220
    # use fast slic
    slic = SlicAvx2(num_components=8000, compactness=10)
    slic_result = slic.iterate(image, 10) # Cluster Map
    end_result = segmentation.mark_boundaries(image, slic_result, outline_color=(0, 1, 1))
    end_result = use_mask_to_get_two_areas(mask,end_result,image)


    cv2.imwrite(end_path,end_result*255)



if __name__ == '__main__':
    ori_folder = '/Users/huhao/Documents/GitHub/real-time-semantic-segmentation/PCB/pcb_small'
    end_folder = '/Users/huhao/Documents/GitHub/real-time-semantic-segmentation/PCB/slic_result'
    ori_list = get_ori_list(ori_folder)
    for img_path in tqdm(ori_list):
        end_path = osp.join(end_folder, osp.basename(img_path[:-4])+'_end_result.jpg')
        mask_path = osp.join(ori_folder, osp.basename(img_path[:-4]) + '_bg_mask.jpg')
        use_fast_slic_to_get_edge(img_path, mask_path, end_path)
        os.system("cp {} {}".format(img_path,end_folder))



boundaries.py


import numpy as np
from scipy import ndimage as ndi
from ..morphology import dilation, erosion, square
from ..util import img_as_float, view_as_windows
from ..color import gray2rgb


def _find_boundaries_subpixel(label_img):
    """See ``find_boundaries(..., mode='subpixel')``.

    Notes
    -----
    This function puts in an empty row and column between each *actual*
    row and column of the image, for a corresponding shape of ``2s - 1``
    for every image dimension of size ``s``. These "interstitial" rows
    and columns are filled as ``True`` if they separate two labels in
    `label_img`, ``False`` otherwise.

    I used ``view_as_windows`` to get the neighborhood of each pixel.
    Then I check whether there are two labels or more in that
    neighborhood.
    """
    ndim = label_img.ndim
    max_label = np.iinfo(label_img.dtype).max

    label_img_expanded = np.zeros([(2 * s - 1) for s in label_img.shape],
                                  label_img.dtype)
    pixels = (slice(None, None, 2), ) * ndim
    label_img_expanded[pixels] = label_img

    edges = np.ones(label_img_expanded.shape, dtype=bool)
    edges[pixels] = False
    label_img_expanded[edges] = max_label
    windows = view_as_windows(np.pad(label_img_expanded, 1,
                                     mode='constant', constant_values=0),
                              (3,) * ndim)

    boundaries = np.zeros_like(edges)
    for index in np.ndindex(label_img_expanded.shape):
        if edges[index]:
            values = np.unique(windows[index].ravel())
            if len(values) > 2:  # single value and max_label
                boundaries[index] = True
    return boundaries


def find_boundaries(label_img, connectivity=1, mode='thick', background=0):
    """Return bool array where boundaries between labeled regions are True.

    Parameters
    ----------
    label_img : array of int or bool
        An array in which different regions are labeled with either different
        integers or boolean values.
    connectivity : int in {1, ..., `label_img.ndim`}, optional
        A pixel is considered a boundary pixel if any of its neighbors
        has a different label. `connectivity` controls which pixels are
        considered neighbors. A connectivity of 1 (default) means
        pixels sharing an edge (in 2D) or a face (in 3D) will be
        considered neighbors. A connectivity of `label_img.ndim` means
        pixels sharing a corner will be considered neighbors.
    mode : string in {'thick', 'inner', 'outer', 'subpixel'}
        How to mark the boundaries:

        - thick: any pixel not completely surrounded by pixels of the
          same label (defined by `connectivity`) is marked as a boundary.
          This results in boundaries that are 2 pixels thick.
        - inner: outline the pixels *just inside* of objects, leaving
          background pixels untouched.
        - outer: outline pixels in the background around object
          boundaries. When two objects touch, their boundary is also
          marked.
        - subpixel: return a doubled image, with pixels *between* the
          original pixels marked as boundary where appropriate.
    background : int, optional
        For modes 'inner' and 'outer', a definition of a background
        label is required. See `mode` for descriptions of these two.

    Returns
    -------
    boundaries : array of bool, same shape as `label_img`
        A bool image where ``True`` represents a boundary pixel. For
        `mode` equal to 'subpixel', ``boundaries.shape[i]`` is equal
        to ``2 * label_img.shape[i] - 1`` for all ``i`` (a pixel is
        inserted in between all other pairs of pixels).

    Examples
    --------
    >>> labels = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    ...                    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    ...                    [0, 0, 0, 0, 0, 5, 5, 5, 0, 0],
    ...                    [0, 0, 1, 1, 1, 5, 5, 5, 0, 0],
    ...                    [0, 0, 1, 1, 1, 5, 5, 5, 0, 0],
    ...                    [0, 0, 1, 1, 1, 5, 5, 5, 0, 0],
    ...                    [0, 0, 0, 0, 0, 5, 5, 5, 0, 0],
    ...                    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    ...                    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=np.uint8)
    >>> find_boundaries(labels, mode='thick').astype(np.uint8)
    array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
           [0, 0, 1, 1, 1, 1, 1, 1, 1, 0],
           [0, 1, 1, 1, 1, 1, 0, 1, 1, 0],
           [0, 1, 1, 0, 1, 1, 0, 1, 1, 0],
           [0, 1, 1, 1, 1, 1, 0, 1, 1, 0],
           [0, 0, 1, 1, 1, 1, 1, 1, 1, 0],
           [0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8)
    >>> find_boundaries(labels, mode='inner').astype(np.uint8)
    array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
           [0, 0, 1, 1, 1, 1, 0, 1, 0, 0],
           [0, 0, 1, 0, 1, 1, 0, 1, 0, 0],
           [0, 0, 1, 1, 1, 1, 0, 1, 0, 0],
           [0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8)
    >>> find_boundaries(labels, mode='outer').astype(np.uint8)
    array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
           [0, 0, 1, 1, 1, 1, 0, 0, 1, 0],
           [0, 1, 0, 0, 1, 1, 0, 0, 1, 0],
           [0, 1, 0, 0, 1, 1, 0, 0, 1, 0],
           [0, 1, 0, 0, 1, 1, 0, 0, 1, 0],
           [0, 0, 1, 1, 1, 1, 0, 0, 1, 0],
           [0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8)
    >>> labels_small = labels[::2, ::3]
    >>> labels_small
    array([[0, 0, 0, 0],
           [0, 0, 5, 0],
           [0, 1, 5, 0],
           [0, 0, 5, 0],
           [0, 0, 0, 0]], dtype=uint8)
    >>> find_boundaries(labels_small, mode='subpixel').astype(np.uint8)
    array([[0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 1, 1, 1, 0],
           [0, 0, 0, 1, 0, 1, 0],
           [0, 1, 1, 1, 0, 1, 0],
           [0, 1, 0, 1, 0, 1, 0],
           [0, 1, 1, 1, 0, 1, 0],
           [0, 0, 0, 1, 0, 1, 0],
           [0, 0, 0, 1, 1, 1, 0],
           [0, 0, 0, 0, 0, 0, 0]], dtype=uint8)
    >>> bool_image = np.array([[False, False, False, False, False],
    ...                        [False, False, False, False, False],
    ...                        [False, False,  True,  True,  True],
    ...                        [False, False,  True,  True,  True],
    ...                        [False, False,  True,  True,  True]],
    ...                       dtype=bool)
    >>> find_boundaries(bool_image)
    array([[False, False, False, False, False],
           [False, False,  True,  True,  True],
           [False,  True,  True,  True,  True],
           [False,  True,  True, False, False],
           [False,  True,  True, False, False]])
    """
    if label_img.dtype == 'bool':
        label_img = label_img.astype(np.uint8)
    ndim = label_img.ndim
    selem = ndi.generate_binary_structure(ndim, connectivity)
    if mode != 'subpixel':
        boundaries = dilation(label_img, selem) != erosion(label_img, selem)
        if mode == 'inner':
            foreground_image = (label_img != background)
            boundaries &= foreground_image
        elif mode == 'outer':
            max_label = np.iinfo(label_img.dtype).max
            background_image = (label_img == background)
            selem = ndi.generate_binary_structure(ndim, ndim)
            inverted_background = np.array(label_img, copy=True)
            inverted_background[background_image] = max_label
            adjacent_objects = ((dilation(label_img, selem) !=
                                 erosion(inverted_background, selem)) &
                                ~background_image)
            boundaries &= (background_image | adjacent_objects)
        return boundaries
    else:
        boundaries = _find_boundaries_subpixel(label_img)
        return boundaries


def mark_boundaries(image, label_img, color=(0, 1, 0),
                    outline_color=None, mode='outer', background_label=0):
    """Return image with boundaries between labeled regions highlighted.

    Parameters
    ----------
    image : (M, N[, 3]) array
        Grayscale or RGB image.
    label_img : (M, N) array of int
        Label array where regions are marked by different integer values.
    color : length-3 sequence, optional
        RGB color of boundaries in the output image.
    outline_color : length-3 sequence, optional
        RGB color surrounding boundaries in the output image. If None, no
        outline is drawn.
    mode : string in {'thick', 'inner', 'outer', 'subpixel'}, optional
        The mode for finding boundaries.
    background_label : int, optional
        Which label to consider background (this is only useful for
        modes ``inner`` and ``outer``).

    Returns
    -------
    marked : (M, N, 3) array of float
        An image in which the boundaries between labels are
        superimposed on the original image.

    See Also
    --------
    find_boundaries
    """
    marked = img_as_float(image, force_copy=True)
    if marked.ndim == 2:
        marked = gray2rgb(marked)
    if mode == 'subpixel':
        # Here, we want to interpose an extra line of pixels between
        # each original line - except for the last axis which holds
        # the RGB information. ``ndi.zoom`` then performs the (cubic)
        # interpolation, filling in the values of the interposed pixels
        marked = ndi.zoom(marked, [2 - 1/s for s in marked.shape[:-1]] + [1],
                          mode='mirror')
    boundaries = find_boundaries(label_img, mode=mode,
                                 background=background_label)

    boundaries = dilation(boundaries, square(10))
    if outline_color is not None:
        outlines = dilation(boundaries, square(3))
        marked[outlines] = outline_color
    marked[boundaries] = color
    #marked[boundaries] = image[boundaries]/255


    return marked

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值