Convert RGB image to index image

前端 未结 6 2330
一个人的身影
一个人的身影 2020-12-11 22:16

I want to convert a 3 channel RGB image to a index image with Python. It\'s used for handling the labels of training a deep net for semantic segmentation. By index image I m

相关标签:
6条回答
  • 2020-12-11 22:21

    actually for-loop takes much time.

    binary_mask = (im_array[:,:,0] == 255) & (im_array[:,:,1] == 255) & (im_array[:,:,2] == 0) 
    

    maybe above code can help you

    0 讨论(0)
  • 2020-12-11 22:21

    I've implemented a naive function: … I firstly tried the ufunc of numpy with something like this: …

    I suggest using an even more naive function which converts just one pixel:

    def rgb2index(rgb):
        """
        turn a 3 channel RGB color to 1 channel index color
        """
        return color2index[tuple(rgb)]
    

    Then using a numpy routine is a good idea, but we don't need a ufunc:

    np.apply_along_axis(rgb2index, 2, im)
    

    Here numpy.apply_along_axis() is used to apply our rgb2index() function to the RGB slices along the last of the three axes (0, 1, 2) for the whole image im.

    We could even do without the function and just write:

    np.apply_along_axis(lambda rgb: color2index[tuple(rgb)], 2, im)
    
    0 讨论(0)
  • 2020-12-11 22:25

    Similar to what Armali and Mendrika proposed, I somehow had to tweak it a little bit to get it to work (maybe totally my fault). So I just wanted to share a snippet that works.

    COLORS = np.array([
        [0, 0, 0],
        [0, 0, 255],
        [255, 0, 0]
    ])
    W = np.power(255, [0, 1, 2])
    
    HASHES = np.sum(W * COLORS, axis=-1)
    HASH2COLOR = {h : c for h, c in zip(HASHES, COLORS)}
    HASH2IDX = {h: i for i, h in enumerate(HASHES)}
    
    
    def rgb2index(segmentation_rgb):
        """
        turn a 3 channel RGB color to 1 channel index color
        """
        s_shape = segmentation_rgb.shape
        s_hashes = np.sum(W * segmentation_rgb, axis=-1)
        func = lambda x: HASH2IDX[int(x)]
        segmentation_idx = np.apply_along_axis(func, 0, s_hashes.reshape((1, -1)))
        segmentation_idx = segmentation_idx.reshape(s_shape[:2])
        return segmentation_idx
    
    segmentation = np.array([[0, 0, 0], [0, 0, 255], [255, 0, 0]] * 3).reshape((3, 3, 3))
    rgb2index(segmentation)
    

    Example plot

    The code is also available here: https://github.com/theRealSuperMario/supermariopy/blob/dev/scripts/rgb2labels.py

    0 讨论(0)
  • 2020-12-11 22:29

    Did you check Pillow library https://python-pillow.org/? As I remember, it has some classes and methods to deal with color conversion. See: https://pillow.readthedocs.io/en/4.0.x/reference/Image.html#PIL.Image.Image.convert

    0 讨论(0)
  • 2020-12-11 22:42

    Here's a small utility function to convert images (np.array) to per-pixel labels (indices), which can also be a one-hot encoding:

    def rgb2label(img, color_codes = None, one_hot_encode=False):
        if color_codes is None:
            color_codes = {val:i for i,val in enumerate(set( tuple(v) for m2d in img for v in m2d ))}
        n_labels = len(color_codes)
        result = np.ndarray(shape=img.shape[:2], dtype=int)
        result[:,:] = -1
        for rgb, idx in color_codes.items():
            result[(img==rgb).all(2)] = idx
    
        if one_hot_encode:
            one_hot_labels = np.zeros((img.shape[0],img.shape[1],n_labels))
            # one-hot encoding
            for c in range(n_labels):
                one_hot_labels[: , : , c ] = (result == c ).astype(int)
            result = one_hot_labels
    
        return result, color_codes
    
    
    img = cv2.imread("input_rgb_for_labels.png")
    img_labels, color_codes = rgb2label(img)
    print(color_codes) # e.g. to see what the codebook is
    
    img1 = cv2.imread("another_rgb_for_labels.png")
    img1_labels, _ = rgb2label(img1, color_codes) # use the same codebook
    

    It calculates (and returns) the color codebook if None is supplied.

    0 讨论(0)
  • 2020-12-11 22:48

    What about this?

    color2index = {
        (255, 255, 255) : 0,
        (0,     0, 255) : 1,
        (0,   255, 255) : 2,
        (0,   255,   0) : 3,
        (255, 255,   0) : 4,
        (255,   0,   0) : 5
    }
    
    def rgb2mask(img):
    
        assert len(img.shape) == 3
        height, width, ch = img.shape
        assert ch == 3
    
        W = np.power(256, [[0],[1],[2]])
    
        img_id = img.dot(W).squeeze(-1) 
        values = np.unique(img_id)
    
        mask = np.zeros(img_id.shape)
    
        for i, c in enumerate(values):
            try:
                mask[img_id==c] = color2index[tuple(img[img_id==c][0])] 
            except:
                pass
        return mask
    

    Then just call:

    mask = rgb2mask(ing)

    0 讨论(0)
提交回复
热议问题