Study: Artificial Intelligence(AI)/AI: Data Pipeline

[Data] Segmentation ๋ฐ์ดํ„ฐ ์••์ถ• ์•Œ๊ณ ๋ฆฌ์ฆ˜: Run Length Encoding(RLE) - coco mask to rle์™€ rle to mask ๊ฒ€์ฆ๊นŒ์ง€

DrawingProcess 2024. 2. 28. 20:10
๋ฐ˜์‘ํ˜•
๐Ÿ’ก ๋ณธ ๋ฌธ์„œ๋Š” '[Data] Segmentation ๋ฐ์ดํ„ฐ ์••์ถ• ์•Œ๊ณ ๋ฆฌ์ฆ˜: Run Length Encoding(RLE) - coco mask to rle์™€ rle to mask ๊ฒ€์ฆ๊นŒ์ง€'์— ๋Œ€ํ•ด ์ •๋ฆฌํ•ด๋†“์€ ๊ธ€์ž…๋‹ˆ๋‹ค.
Segmentation ์—์„œ masking ๋ฐ์ดํ„ฐ๋ฅผ ์••์ถ•ํ• ๋•Œ ์ข…์ข… ์‚ฌ์šฉํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ธ Run Length Encoding(RLE)์— ๋Œ€ํ•ด ์ •๋ฆฌํ•˜์˜€์œผ๋ฉฐ, Encoder, Decoder ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ฝ”๋“œ ์ˆ˜์ค€์—์„œ ์ •๋ฆฌํ•˜์˜€์œผ๋‹ˆ ์ฐธ๊ณ ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

1. Run Length Encoding(RLE) ๋ž€?

RLE์€ "Run Length Encoding"์˜ ์•ฝ์ž๋กœ, ์ด๋ฏธ์ง€๋‚˜ ๋น„๋””์˜ค ๋ฐ์ดํ„ฐ๋ฅผ ์••์ถ•ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ์••์ถ• ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์ด๋ฏธ์ง€์—์„œ ์—ฐ์†๋œ ํ”ฝ์…€ ๊ฐ’์ด ๋ฐ˜๋ณต๋˜๋Š” ๊ฒฝ์šฐ, ๊ทธ ๊ฐ’์„ ๋ฐ˜๋ณต๋˜๋Š” ํšŸ์ˆ˜์™€ ํ•จ๊ป˜ ์ €์žฅํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์••์ถ•ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ ์šฉ๋Ÿ‰์„ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

RLE Variation

์ด์ œ RLE์— ๋Œ€ํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ž์ฒด๋Š” ๋ฐ˜๋ณต๋˜๋Š” ๋ฌธ์ž์—ด์„ ์ €์žฅํ•˜๋Š” ๊ฒƒ์ด๋ผ๊ณ  ์ดํ•ดํ–ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ฅผ ๊ตฌํ˜„ํ•จ์— ์žˆ์–ด ๋‹ค์–‘ํ•œ Variation์ด ์žˆ์–ด ๊ฐ ๋ณ€ํ˜•๋œ ๋ฐฉ๋ฒ•๋“ค์— ๋Œ€ํ•ด ์–ธ๊ธ‰ํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. 00111011 ๋ฌธ์ž์—ด์„ ์••์ถ•ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ์†Œ๊ฐœํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

  1. 3372: 1์ด ์žˆ๋Š” ์œ„์น˜๋ฅผ ์ ์€ ํ›„ ๋ช‡๊ฐœ๊ฐ€ ์—ฐ์†๋˜์–ด ์žˆ๋Š”์ง€๋ฅผ ๋‚˜์—ด
  2. 2312: 0,1,0,1, .. ์˜ ์ˆœ์„œ๋กœ ์—ฐ์†๋œ ๋ฌธ์ž์˜ ๊ฐฏ์ˆ˜๋ฅผ ๋‚˜์—ด

์ด์ œ ๊ฐ ๋ฐฉ๋ฒ•์˜ Encoder Decoder์— ํ•ด๋‹นํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด์„œ ์ดํ•ดํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

2. RLE Converter

1) 3372: 1์ด ์žˆ๋Š” ์œ„์น˜๋ฅผ ์ ์€ ํ›„ ๋ช‡๊ฐœ๊ฐ€ ์—ฐ์†๋˜์–ด ์žˆ๋Š”์ง€๋ฅผ ๋‚˜์—ด

mask to rle

RLE ์ธ์ฝ”๋”ฉ ํ•จ์ˆ˜์ธ mask2rle๋Š” ์ด๋ฏธ์ง€ ๋งˆ์Šคํฌ๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์•„์„œ RLE ํ˜•์‹์œผ๋กœ ์••์ถ•๋œ ๋งˆ์Šคํฌ๋ฅผ ๋ฐ˜ํ™˜

# ref.: https://www.kaggle.com/stainsby/fast-tested-rle
def mask2rle(img):
    """
    img: numpy array, 1 - mask, 0 - background
    Returns run length as string formatted
    """
    pixels = img.flatten()
    pixels = np.concatenate([[0], pixels, [0]])
    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1
    runs[1::2] -= runs[::2]
    return ' '.join(str(x) for x in runs)
  • ์ด๋ฏธ์ง€ ๋งˆ์Šคํฌ๋ฅผ 1์ฐจ์› ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜
  • ๋ฐฐ์—ด์˜ ์‹œ์ž‘๊ณผ ๋์— 0์„ ์ถ”๊ฐ€
  • ์—ฐ์†๋˜๋Š” ๊ฐ’์˜ ์‹œ์ž‘ ์ธ๋ฑ์Šค ํƒ์ƒ‰
  • ์—ฐ์†๋œ ๊ฐ’์˜ ๊ธธ์ด ๊ณ„์‚ฐ
  • ๊ธธ์ด ์ •๋ณด๋ฅผ RLE ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜. ์‹œ์ž‘ ์œ„์น˜์™€ ๊ธธ์ด๋ฅผ ๋ฒˆ๊ฐˆ์•„๊ฐ€๋ฉด์„œ ๊ธฐ๋กํ•˜๋ฉฐ, ๊ธธ์ด๋Š” ์‹œ์ž‘ ์œ„์น˜์˜ ์ฐจ์ด๋กœ ํ‘œํ˜„
  • RLE ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜๋œ ์ •๋ณด๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜

rle to mask

RLE ๋””์ฝ”๋”ฉ ํ•จ์ˆ˜์ธ rle2mask๋Š” ์••์ถ•๋œ RLE ํ˜•์‹์˜ ๋งˆ์Šคํฌ๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์•„์„œ ์›๋ž˜์˜ ํ˜•ํƒœ๋กœ ๋””์ฝ”๋”ฉ๋œ ์ด๋ฏธ์ง€ ๋งˆ์Šคํฌ๋ฅผ ๋ฐ˜ํ™˜

def rle2mask(mask_rle: str, label=1, shape=DEFAULT_IMAGE_SHAPE):
    """
    mask_rle: run-length as string formatted (start length)
    shape: (height,width) of array to return
    Returns numpy array, 1 - mask, 0 - background

    """
    s = mask_rle.split()
    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]
    starts -= 1
    ends = starts + lengths
    img = np.zeros(shape[0] * shape[1], dtype=np.uint8)
    for lo, hi in zip(starts, ends):
        img[lo:hi] = label
    return img.reshape(shape)  # Needed to align to RLE direction

 

  • RLE ํ˜•์‹์˜ ๋งˆ์Šคํฌ๋ฅผ ๊ณต๋ฐฑ ๋ฌธ์ž๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ์‹œ์ž‘ ์œ„์น˜(starts)์™€ ๊ธธ์ด(lengths)๋ฅผ ์–ป์Œ
  • ์‹œ์ž‘ ์œ„์น˜๋ฅผ 0๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š” ์ธ๋ฑ์Šค๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด 1 ๋นผ๊ธฐ
  • ์ข…๋ฃŒ ์œ„์น˜(ends)๋ฅผ ์‹œ์ž‘ ์œ„์น˜(starts)์— ๊ธธ์ด(lengths)๋ฅผ ๋”ํ•ด์„œ ๊ตฌํ•˜๊ธฐ
  • ์ด๋ฏธ์ง€ ๋งˆ์Šคํฌ๋ฅผ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด ์ง€์ •๋œ ๋ชจ์–‘(shape)์— ๋งž๊ฒŒ 0์œผ๋กœ ์ดˆ๊ธฐํ™”๋œ ๋ฐฐ์—ด ์ƒ์„ฑ
  • ์‹œ์ž‘ ์œ„์น˜(starts)์™€ ์ข…๋ฃŒ ์œ„์น˜(ends)๋ฅผ ์ด์šฉํ•˜์—ฌ ๋งˆ์Šคํฌ์˜ ํ•ด๋‹น ์˜์—ญ์„ 1๋กœ ์„ค์ •
  • ์ตœ์ข…์ ์œผ๋กœ ์ƒ์„ฑ๋œ 1์ฐจ์› ๋ฐฐ์—ด์„ ์ง€์ •๋œ ๋ชจ์–‘(shape)์œผ๋กœ ์žฌ๊ตฌ์„ฑํ•˜์—ฌ ์ด๋ฏธ์ง€ ๋งˆ์Šคํฌ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ : https://velog.io/@hajieun02/Image-Segmentation3-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%95%95%EC%B6%95-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-RLE-%EC%9D%B8%EC%BD%94%EB%94%A9%EB%94%94%EC%BD%94%EB%94%A9

2) 2312: 0,1,0,1, .. ์˜ ์ˆœ์„œ๋กœ ์—ฐ์†๋œ ๋ฌธ์ž์˜ ๊ฐฏ์ˆ˜๋ฅผ ๋‚˜์—ด

mask to rle

import numpy as np
from itertools import groupby

def binary_mask_to_rle(binary_mask):
    rle = {'counts': [], 'size': list(binary_mask.shape)}
    counts = rle.get('counts')
    for i, (value, elements) in enumerate(groupby(binary_mask.ravel(order='F'))):
        if i == 0 and value == 1:
            counts.append(0)
        counts.append(len(list(elements)))
    return rle

coco = COCO('/home/avs/dataset/train_exd/con2.json')

annids = coco.getAnnIds()
anns = coco.loadAnns(annids)
mask = coco.annToMask(anns[0])
rle = binary_mask_to_rle(mask)
print(rle)

rle to mask

rle segmentation count ๋‚ด๋ถ€์— ์žˆ๋Š” ๋ฐฐ์—ด์„ np.array ๋‚ด๋ถ€์— ๋„ฃ๊ณ  ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰

from PIL import Image

enco1_arr = np.array([773632, 50, 669, 52, 668, 52, 668, 52, 668, 52, 668, 52, 668, 52, 668, 52, 667, 53, 667, 53, 667, 53, 667, 53, 667, 53, 667, 53, 667, 53, 667, 53, 667, 53, 667, 53, 667, 53, 667, 53, 667, 53, 667, 53, 667, 53, 667, 53, 666, 54, 666, 54, 666, 54, 666, 54, 666, 55, 665, 55, 665, 55, 665, 55, 665, 55, 665, 55, 665, 55, 665, 55, 665, 55, 665, 55, 665, 55, 665, 54, 667, 53, 667, 52, 668, 52, 668, 52, 669, 51, 669, 51, 670, 50, 671, 48, 673, 47, 675, 45, 677, 43, 678, 41, 679, 40, 682, 36, 684, 36, 685, 37, 683, 38, 681, 39, 681, 5, 1, 33, 681, 5, 1, 33, 681, 5, 1, 33, 681, 4, 3, 32, 688, 32, 689, 31, 693, 23, 101844, 0])
print(enco1_arr.sum())

enco1_pos = enco1_arr[0::2]
enco1_len = enco1_arr[1::2]

print(enco1_pos)
print(enco1_len)

mask_1d = np.zeros(720 * 1280, dtype=np.uint8)

start = 0
end = 0
for po, le in zip(enco1_pos, enco1_len):
    start = end + po
    end = start + le
    mask_1d[start:end]=255
print(mask_1d)

mask2d = mask_1d.reshape(720, 1280, order='F')
print(mask2d)

im = Image.fromarray(mask2d)
im.save("your_file.jpeg")

์ฐธ๊ณ 

๋ฐ˜์‘ํ˜•