| layout | hub_detail | ||
|---|---|---|---|
| background-class | hub-background | ||
| body-class | hub | ||
| title | FCN | ||
| summary | Fully-Convolutional Network model with ResNet-50 and ResNet-101 backbones | ||
| category | researchers | ||
| image | fcn2.png | ||
| author | Pytorch Team | ||
| tags |
|
||
| github-link | https://github.com/pytorch/vision/blob/main/torchvision/models/segmentation/fcn.py | ||
| github-id | pytorch/vision | ||
| featured_image_1 | deeplab1.png | ||
| featured_image_2 | fcn2.png | ||
| accelerator | cuda-optional | ||
| order | 10 | ||
| demo-model-link | https://huggingface.co/spaces/pytorch/FCN |
import torch
model = torch.hub.load('pytorch/vision:v0.10.0', 'fcn_resnet50', pretrained=True)
# or
# model = torch.hub.load('pytorch/vision:v0.10.0', 'fcn_resnet101', pretrained=True)
model.eval()๋ชจ๋ ์ฌ์ ํ๋ จ๋ ๋ชจ๋ธ์ ๋์ผํ ๋ฐฉ์์ผ๋ก ์ ๊ทํ๋ ์
๋ ฅ ์ด๋ฏธ์ง, ์ฆ N์ด ์ด๋ฏธ์ง ์์ด๊ณ , H์ W๋ ์ต์ 224ํฝ์
์ธ (N, 3, H, W)ํํ์ 3์ฑ๋ RGB ์ด๋ฏธ์ง์ ๋ฏธ๋ ๋ฐฐ์น๋ฅผ ์๊ตฌํฉ๋๋ค.
์ด๋ฏธ์ง๋ฅผ [0, 1] ๋ฒ์๋ก ๋ก๋ํ ๋ค์ mean = [0.485, 0.456, 0.406] ๋ฐ std = [0.229, 0.224, 0.225]๋ฅผ ์ฌ์ฉํ์ฌ ์ ๊ทํํด์ผ ํฉ๋๋ค.
๋ชจ๋ธ์ ์
๋ ฅ ํ
์์ ๋์ด์ ๋๋น๋ ๊ฐ์ง๋ง ํด๋์ค๊ฐ 21๊ฐ์ธ ํ
์๋ฅผ ๊ฐ์ง OrderedDict๋ฅผ ๋ฐํํฉ๋๋ค. output['out']์๋ ์๋ฉํฑ ๋ง์คํฌ๊ฐ ํฌํจ๋๋ฉฐ output['aux']์๋ ํฝ์
๋น ๋ณด์กฐ ์์ค ๊ฐ์ด ํฌํจ๋ฉ๋๋ค. ์ถ๋ก ๋ชจ๋์์๋ output['aux']์ด ์ ์ฉํ์ง ์์ต๋๋ค.
๊ทธ๋์ output['out']์ ํฌ๊ธฐ๋ (N, 21, H, W)์
๋๋ค. ์ถ๊ฐ ์ค๋ช
์๋ ์ฌ๊ธฐ์์ ์ฐพ์ ์ ์์ต๋๋ค.
# ํ์ดํ ์น ์น์ฌ์ดํธ์์ ์์ ์ด๋ฏธ์ง ๋ค์ด๋ก๋
import urllib
url, filename = ("https://github.com/pytorch/hub/raw/master/images/deeplab1.png", "deeplab1.png")
try: urllib.URLopener().retrieve(url, filename)
except: urllib.request.urlretrieve(url, filename)# ์คํ ์์ (torchvision ํ์)
from PIL import Image
from torchvision import transforms
input_image = Image.open(filename)
input_image = input_image.convert("RGB")
preprocess = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
input_tensor = preprocess(input_image)
input_batch = input_tensor.unsqueeze(0) # ๋ชจ๋ธ์์ ์๊ตฌ๋๋ ๋ฏธ๋๋ฐฐ์น ์์ฑ
# ๊ฐ๋ฅํ๋ค๋ฉด ์๋๋ฅผ ์ํด ์
๋ ฅ๊ณผ ๋ชจ๋ธ์ GPU๋ก ์ฎ๊น๋๋ค
if torch.cuda.is_available():
input_batch = input_batch.to('cuda')
model.to('cuda')
with torch.no_grad():
output = model(input_batch)['out'][0]
output_predictions = output.argmax(0)์ฌ๊ธฐ์์ ์ถ๋ ฅ ํํ๋ (21, H, W)์ด๋ฉฐ, ๊ฐ ์์น์๋ ๊ฐ ํด๋์ค์ ์์ธก์ ํด๋นํ๋ ์ ๊ทํ๋์ง ์์ ํ๋ฅ ์ด ์์ต๋๋ค. ๊ฐ ํด๋์ค์ ์ต๋ ์์ธก์ ๊ฐ์ ธ์จ ๋ค์ ์ด๋ฅผ ๋ค์ด์คํธ๋ฆผ ์์
์ ์ฌ์ฉํ๋ ค๋ฉด output_propertions = output.slmax(0)๋ฅผ ์ํํฉ๋๋ค. ๋ค์์ ๊ฐ ํด๋์ค์ ํ ๋น๋ ๊ฐ ์์๊ณผ ํจ๊ป ์์ธก์ ํ์ํ๋ ์์ ํ ๋ง๊ธ ์
๋๋ค(์ผ์ชฝ์ ์๊ฐํ ์ด๋ฏธ์ง ์ฐธ์กฐ).
# ๊ฐ ํด๋์ค์ ๋ํ ์์์ ์ ํํ์ฌ ์์ ํ๋ ํธ๋ฅผ ๋ง๋ญ๋๋ค.
palette = torch.tensor([2 ** 25 - 1, 2 ** 15 - 1, 2 ** 21 - 1])
colors = torch.as_tensor([i for i in range(21)])[:, None] * palette
colors = (colors % 255).numpy().astype("uint8")
# ๊ฐ ์์์ 21๊ฐ ํด๋์ค์ ์๋ฉํฑ ์ธ๊ทธ๋ฉํ
์ด์
์์ธก์ ๊ทธ๋ฆผ์ผ๋ก ํ์ํฉ๋๋ค.
r = Image.fromarray(output_predictions.byte().cpu().numpy()).resize(input_image.size)
r.putpalette(colors)
import matplotlib.pyplot as plt
plt.imshow(r)
# plt.show()FCN-ResNet์ ResNet-50 ๋๋ ResNet-101 ๋ฐฑ๋ณธ์ ์ฌ์ฉํ์ฌ ์์ ์ปจ๋ณผ๋ฃจ์ ๋คํธ์ํฌ ๋ชจ๋ธ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ์ฌ์ ํ๋ จ๋ ๋ชจ๋ธ์ Pascal VOC ๋ฐ์ดํฐ ์ธํธ์ ์กด์ฌํ๋ 20๊ฐ ๋ฒ์ฃผ์ ๋ํ COCO 2017์ ํ์ ์งํฉ์ ๋ํด ํ๋ จ ๋์์ต๋๋ค.
COCO val 2017 ๋ฐ์ดํฐ์ ์์ ํ๊ฐ๋ ์ฌ์ ํ๋ จ๋ ๋ชจ๋ธ์ ์ ํ์ฑ์ ์๋์ ๋์ด๋์ด ์์ต๋๋ค.
| Model structure | Mean IOU | Global Pixelwise Accuracy |
|---|---|---|
| fcn_resnet50 | 60.5 | 91.4 |
| fcn_resnet101 | 63.7 | 91.9 |