Image segmentation ๊ธฐ์ ์ ์ด๋ฏธ์ง๋ก๋ถํฐ ๊ฐ ํฝ์ ์ด ์ด๋ค ํด๋์ค์ ์ํ๋์ง๋ฅผ ๊ตฌ๋ถํ๋ ๋คํธ์ํฌ์ฃ .
์ฌ๋ฌ ๊ฐ์ง ๊ธฐ์ ์ด ์กด์ฌํ์ง๋ง, ์ด๋ฏธ์ง ๋ถ๋ฅ ์์ ์ ๋ง์ฐฌ๊ฐ์ง๋ก ํ์ดํ ์น์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ๋ FCN์ ์ฌ์ฉํด๋ณด๊ฒ ์ต๋๋ค.
Inference [Image]
์ญ์๋ ํฐ ํ์์ ์ค์ํ ๋ถ๋ถ๋ง ์ง๊ณ ๋์ด๊ฐ๊ฒ ์ต๋๋ค.
label_map = [
(0, 0, 0), # background
(128, 0, 0), # aeroplane
(0, 128, 0), # bicycle
(128, 128, 0), # bird
(0, 0, 128), # boat
(128, 0, 128), # bottle
(0, 128, 128), # bus
(128, 128, 128), # car
(64, 0, 0), # cat
(192, 0, 0), # chair
(64, 128, 0), # cow
(192, 128, 0), # dining table
(64, 0, 128), # dog
(192, 0, 128), # horse
(64, 128, 128), # motorbike
(192, 128, 128), # person
(0, 64, 0), # potted plant
(128, 64, 0), # sheep
(0, 192, 0), # sofa
(128, 192, 0), # train
(0, 64, 128) # tv/monitor
]FCN์์ ์ฌ์ฉํ ๋ฐ์ดํฐ์
์ PASCAL-VOC ๋ฐ์ดํฐ์
์
๋๋ค.
PASCAL-VOC ๋ฐ์ดํฐ์
์ ์ด๋ฏธ์ง์์ ํฝ์
๋ณ ์ด 21๊ฐ ํด๋์ค๋ฅผ ๊ตฌ๋ถํด๋๋ค.
utils.py์ ์๋ label_map์ ๊ฐ ํด๋์ค ์ ๋ณด์, ์ถ๋ก ์ดํ ๊ฐ์ํ๋ฅผ ์ํ ์์ ์ ๋ณด๊ฐ ๋ด๊ฒจ์์ต๋๋ค.
def get_segment_labels(image, model, DEVICE):
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
image = transform(image).to(DEVICE).unsqueeze(0)
outputs = model(image)
return outputs์ด๋ฏธ์ง ๋ถ๋ฅ์ ์ฌ์ฉํ์๋ ๋คํธ์ํฌ๋ค์ ImageNet ์ด๋ผ๋ ๋ฐ์ดํฐ์
์ ๋ํด์ ํ์ต์ ์ํํ์๋๋ฐ, FCN์์๋ PASCAL-VOC๋ฐ์ดํฐ์
์ ์ฌ์ฉํ๋ค๊ณ ๋ง์๋๋ ธ์ฃ .
๊ทธ๋ฐ๋ฐ๋ transform์ ๋์ผํ ํํ๋ก ์ฌ์ฉ์ด ๋๋ค์.
์ด๋ฏธ์ง ๋ถ๋ฅ์ ์ ํํ๊ฒ ๋์ผํ ํํ๋ก ์ถ๋ก ์ ์ค์ํฉ๋๋ค. ๋ค๋ง, ๋ถ๋ฅ์ ๊ฒฐ๊ณผ๋ ํด๋์ค์ ์ํ ํ๋ฅ ์ ๋ํ๋ด๋ ๋ฒกํฐ ํ๋์๋ค๋ฉด,
์ธ๊ทธ๋จผํ ์ด์ ์ ๊ฒฐ๊ณผ๋ ๊ฐ ํฝ์ ๋ณ๋ก ๋ฒกํฐ๊ฐ ๋์ค๊ฒ ์ฃ (๊ฐ๋ก x ์ธ๋ก x ํด๋์ค ์).
model = torchvision.models.segmentation.fcn_resnet50(pretrained=True)
model.to(DEVICE)
model.eval()
image = Image.open(args.input)
outputs = utils.get_segment_labels(image, model, DEVICE)
outputs = outputs['out'] # output์ ํด๋์ค์ ์ํ๋ ํ๋ฅ ์ด ๋ด๊ธด 'out'๊ณผ auxilliary loss๊ฐ ๋ด๊ธด 'aux'๋ก ๊ตฌ์ฑ๋์ด ์์.
overlay, segmented = utils.visualize(image, outputs)ํ์ดํ ์น์ pretrained ๋ชจ๋ธ, fcn_resnet50์ ์ฌ์ฉํ ํ
๋ฐ, ํ์ธํด๋ณด๋ ์ถ๋ก ๊ฒฐ๊ณผ๋ก ํด๋์ค์ ๋ํ ํ๋ฅ ์ ๋ด์ ๋ฒกํฐ out๊ณผ loss๊ฐ ๋ด๊ธด aux๋ฅผ ๋ฐํํ๋ค์.
๊ฐ์ํ๋ฅผ ์ํ out๋ง ๊ฐ์ ธ์ต๋๋ค.
def visualize(input, outputs):
labels = torch.argmax(outputs.squeeze(), dim=0).detach().cpu().numpy()
segmented_image = np.zeros([len(labels), len(labels[0]), 3]).astype(np.uint8)
for label_num in range(0, len(label_map)):
index = labels == label_num
segmented_image[index] = np.array(label_map)[label_num]
image = np.array(input)
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
segmented_image = cv2.cvtColor(segmented_image, cv2.COLOR_RGB2BGR)
cv2.addWeighted(segmented_image, 0.5, image, 0.5, 0, image)
return image, segmented_image์ธ๊ทธ๋จผํ ์ด์ ์ ๊ฐ์ํ๋ ๋๊ด์ด์ฃ . ํด๋์ค์ ํด๋นํ๋ ๊ฐ์ํ์ฉ ์์ ์ ๋ณด๋ฅผ ๋ชจ๋ ํฝ์ ์ ๋ํด ์ ํ์ค๋๋ค.
์
๋ ฅ ์ด๋ฏธ์ง input๊ณผ ํด๋์ค์ ์ํ๋ ํ๋ฅ ์ ๋ด์ outputs๋ฅผ ์
๋ ฅ์ผ๋ก ๋ฐ์์ค๋๋ค.
labels = torch.argmax(outputs.squeeze(), dim=0).detach().cpu().numpy() ๋ gpu๋ก ์ฐ์ฐํ ๋คํธ์ํฌ์ ๊ฒฐ๊ณผ๋ฅผ cpu์, ์ดํ numpyํ์ผ๋ก ๋ฐํํ๋๋ก ํ๋ ๊ตฌ๋ฌธ์
๋๋ค.
์ดํ segmented_image = np.zeros([len(labels), len(labels[0]), 3]).astype(np.uint8) ๊ตฌ๋ฌธ์ ํตํด ์ถ๋ ฅ ์ด๋ฏธ์ง ํฌ๊ธฐ์ ๋์ผํ ๋น ์ด๋ฏธ์ง๋ฅผ ์์ฑํ๊ณ ,
for label_num in range(0, len(label_map)):
index = labels == label_num
segmented_image[index] = np.array(label_map)[label_num]์์ ๋ผ๋ฒจ์ ํด๋นํ๋ ์์ ์ ๋ณด๋ฅผ ํฝ์ ๋ณ๋ก ์ ํ์ค๋๋ค.
| Input | Segmentation result | Visualize |
|---|---|---|
![]() |
![]() |
![]() |
Inference [Video]
์์์ ๋ํ ์ถ๋ก ๋ ์ฌ์ค์ ๋ค๋ฅผ ๊ฒ ์์ต๋๋ค. ์ด์ ๋ ์์ ๋ฅผ ๊ตฌํํ์๋ ๋ถ์ด๋ผ๋ฉด opencv์ ์์์ ๋ํด์ ์ ๊ฐ ๋ค๋ฃฐ ์ด์ ๊ฐ ์์ ๊ฒ ๊ฐ์ ์ค๋ช ์ ์๋ตํ๊ฒ ์ต๋๋ค.
๋ค๋ง ํ ๊ฐ์ง ์ง๊ณ ๋์ด๊ฐ๋ค๋ฉด,
frame = cv2.resize(frame, (640, 360))
์ผ๋ก ์์์ ํฌ๊ธฐ๋ฅผ ์ค์ฌ ๋คํธ์ํฌ์ ์
๋ ฅ์ผ๋ก ์ฌ์ฉํ์๋ค๋ ์ ์ด๊ฒ ๋ค์. ์๋ณธ ์์ ๊ทธ๋๋ก (FHD, 1920 x 1080) ์ฌ์ฉํ์ฌ๋ ๋๋, ์ถ๋ก ์๋๊ฐ ๋งค์ฐ ๋๋ ค์ง๊ธฐ์ ์ฌ์ด์ฆ๋ฅผ ์กฐ์ ํด์ ์ฌ์ฉํฉ๋๋ค.
๋ํ ๊ณต๋ถ๋ฅผ ์ ๋๋ก ํ์
จ๋ค๋ฉด ๋น์ฐํ ๋ด์ฉ์ธ๋ฐ์, ์ด๋ฏธ์ง๋ [1280 x 853] ํฌ๊ธฐ์ธ๋ฐ ์์์ ์ถ๋ก ํ ๋๋ [1920 x 1080] ์ด๋ [640 x 360]์ฌ์ด์ฆ ๋ฃ์ด๋ ๋ผ?
๋ผ๋ ์๋ฌธ์ ๊ฐ์ ์ ์์ง๋ง, ์ด๋ Fully Convolutional Network์ ํน์ง ๋๋ถ์ ๊ฐ๋ฅํ ๊ฒ์ด์ฃ .
๋ถ๋ฅ๋ฅผ ์ํด ๊ณ ์ ๋ ํฌ๊ธฐ์ Fully Connected Layers, FCL๋ฅผ ์ฌ์ฉํ๋ ๊ธฐ์กด Classification ๋คํธ์ํฌ๋ค๊ณผ ๋ค๋ฅด๊ฒ ๋ชจ๋ ๋ ์ด์ด๋ฅผ Convolution ์ผ๋ก ๋ฐ๊ฟ ์ด๋ฏธ์ง ํฌ๊ธฐ๊ฐ ์๊ด ์๋ ํ์ต/์ถ๋ก ์ด ๊ฐ๋ฅํ๋๋ก ํด ์ค๋๋ค.
๋ํ, FCN์ semantic segmentaiton์ด๋ฏ๋ก, ํฝ์ ์ด ์ด๋ ํด๋์ค์ ์ํ๋์ง๋ง์ ๊ตฌ๋ถํฉ๋๋ค (ex:์ฌ๋)
instance segmentation์ ํฝ์ ์ด ๋ช ๋ฒ์ฌ ๊ฐ์ฒด์ ์ํ๋์ง๊น์ง ๊ตฌ๋ถํ๋ฏ๋ก semantic segmentation๊ณผ๋ ๋ค๋ฅธ ๊ฒฐ๊ณผ ๋ฐ ๊ฐ์ํ๋ฅผ ํด์ค์ผ๊ฒ ์ฃ (ex: ์ฌ๋1, ์ฌ๋2, ...)
์ฐธ๊ณ ๋ก ์์ ์ ์ฌ์ฉํ ์์์ Cambridge Landmarks dataset ์ Shop Facade ์ ์์์
๋๋ค. [Link]
์ด๋ฏธ์ง ์ธ๊ทธ๋จผํ ์ด์ ์ ์ฃผ๋ก ์ฌ์ฉํ์ง ์์ ๊ฐ์ํ๋ก ์ ๋นํ ๋ฐ์ดํฐ์ ์ ๊ฐ๊ณ ์์ง ์์ ๊ทธ๋ด์ธํ ์์์ ๊ฐ์ ธ์์ต๋๋ค!
Camera localization (Visual localization)์ ์ํ ๋ฐ์ดํฐ์
์ด๊ธฐ์ ๋น์ฐํ๊ฒ๋ PASCAL-VOC๋ก ํ์ตํ FCN์ ํ๊ฐ๋ก๋ ์ ํฉํ์ง ์์ ๋ฐ์ดํฐ์
์ด๋ ์ฐธ๊ณ ๋ง ํด์ฃผ์ธ์!



