IT_World
[리뷰] Computer Vision Tutorial: Image Segmentation을 위한 마스크 R-CNN 구현 본문
[리뷰] Computer Vision Tutorial: Image Segmentation을 위한 마스크 R-CNN 구현
engine 2021. 5. 28. 14:19Mask R-CNN을 탐색하여 인스턴스 분할이 Mask R-CNN과 어떻게 작동하는지 이해 한 다음
Keras를 사용하여 Mask R-CNN을 사용하여 이미지의 분할을 예측
개요
- Mask R-CNN은 이미지 분할 작업을 위한 최첨단 프레임 워크
- Mask R-CNN이 어떻게 작동하는지 단계별로 배울 수 있다.
- 또한 Python에서 Mask R-CNN을 구현하고 자체 이미지에 사용하는 방법도 살펴보자
소개
자율 주행 자동차 시스템이 급회전을 안전하게 탐색할 수 있도록 정확한 도로 형태를 감지할 수 있는 기술이 필요하다.
그러한 시스템을 구축하는 데 사용할 수있는 최신 최첨단 프레임 워크? 그것이 마스크 R-CNN이다.
- 먼저 이미지 분할이 무엇인지 빠르게 살펴볼 것이다.
- 그런 다음이 기사의 핵심 인 Mask R-CNN 프레임 워크를 살펴본다.
- 마지막으로 Python에서 자체 Mask R-CNN 모델을 구현하는 방법에 대해 알아본다.
목차
- 이미지 분할에 대한 간략한 개요
- Mask R-CNN 이해
- Mask R-CNN 구현 단계
- Mask R-CNN 구현
이미지 분할에 대한 간략한 개요
이미지 분할은 이미지의 각 개체에 대해 픽셀 단위 마스크를 만든다. 이 기술은 이미지에 있는 물체에 대한 훨씬 더 세밀한 이해를 제공한다. 아래에 표시된 이미지는 이미지 분할이 무엇인지 이해하는 데 도움이 된다.
여기에서 각 개체 (이 특정 이미지의 셀)가 분할되었음을 확인할 수 있다. 이것이 이미지 분할이 작동하는 방식이다.
또한 두 가지 유형의 이미지 분할, 즉 시맨틱 분할 및 인스턴스 분할에 대해 논의했다. 다시 한번 다음 두 가지 유형을 모두 이해하는 것이다.
예를 들어
왼쪽 이미지의 5 개 개체는 모두 사람이다. 따라서 semantic segmentation 은 모든 사람을 단일 인스턴스로 분류한다. 이제 오른쪽 이미지에도 5 개의 (모두 사람) 개체가 있다.그러나 여기에서는 동일한 클래스의 다른 개체가 다른 인스턴스로 할당되었다. 이것은 instance segmentation의 예다.
인스턴스 분할 문제를 해결하기 위해 Mask R-CNN이라는 최첨단 이미지 분할 기술을 구현할 것이다.
Mask R-CNN 이해
Mask R-CNN은 기본적으로 Faster R-CNN의 확장이다.Faster R-CNN은 물체 감지 작업에 널리 사용되며, 주어진 이미지에 대해 이미지의 각 객체에 대한 클래스 레이블 및 경계 상자 좌표를 반환한다.
다음 이미지를 전달한다고 가정하면
Fast R-CNN 모델은 다음과 같은 결과를 반환한다.
Mask R-CNN 프레임 워크는 Faster R-CNN을 기반으로 구축되었다. 따라서 주어진 이미지에 대해 Mask R-CNN은 각 객체의 클래스 레이블 및 경계 상자 좌표 외에도 객체 마스크를 반환한다.
먼저 Faster R-CNN이 어떻게 작동하는지 빠르게 이해하고 이해한 것은 Mask R-CNN의 직관을 이해하는 데에도 도움이 될 것이다.
- 더 빠른 R-CNN은 먼저 ConvNet을 사용하여 이미지에서 특징 맵을 추출 한다.
- 그런 다음 이러한 기능 맵은 후보 경계 상자를 반환하는 RPN (Region Proposal Network)을 통해 전달된다.
- 그런 다음 이러한 후보 경계 상자에 RoI 풀링 레이어를 적용하여 모든 후보를 동일한 크기로 가져온다.
- 마지막으로 제안은 완전히 연결된 레이어로 전달되어 객체의 경계 상자를 분류하고 출력한다.
Faster R-CNN의 작동 방식을 이해했다면 Mask R-CNN을 이해하는 것은 매우 쉽다. 입력부터 시작하여 the class label, bounding box, and object mask를 예측하는 단계를 단계별로 이해해 보자.
backbone 모델
Faster R-CNN에서 이미지에서 피쳐 맵을 추출하기 위해 사용하는유사하게 ResNet 101 아키텍처를 사용하여 Mask R-CNN의 이미지에서 피쳐를 추출한다. 첫 번째 단계는 ResNet 101 아키텍처를 사용하여 이미지를 가져오고 특징을 추출하는 것이다. 이러한 기능은 다음 레이어의 입력 역할을 한다.
지역 제안 네트워크 (RPN)
이제 이전 단계에서 얻은 기능 맵을 가져와서 지역 제안 네트워크 (RPM)를 적용한다. 이것은 기본적으로 객체가 해당 영역에 있는지 여부를 예측한다. 이 단계에서는 모델이 어떤 객체를 포함한다고 예측하는 지역 또는 기능 맵을 얻는다.
관심 영역 (RoI)
RPN에서 얻은 영역은 모양이 다를 수 있다. 따라서 풀링 레이어를 적용하고 모든 영역을 동일한 모양으로 변환한다. 다음으로 이러한 영역은 완전히 연결된 네트워크를 통해 전달되므로 클래스 레이블 및 경계 상자가 예측된다.
이 시점까지 단계는 Faster R-CNN이 작동하는 방식과 거의 유사합니다. 이제 두 프레임 워크의 차이점이 있다. 이 외에도 Mask R-CNN은 분할 마스크도 생성한다. 이를 위해 먼저 관심 영역을 계산하여 계산 시간을 줄일 수 있다. 모든 예측 지역에 대해 Ground Truth 상자를 사용하여 IoU (Intersection over Union)를 계산한다. 다음과 같이 IoU를 컴퓨터 할 수 있다.
IoU = 교차 영역 / 조합 영역
이제 IoU가 0.5보다 크거나 같은 경우에만 이를 관심 영역으로 간주한다. 그렇지 않으면 특정 지역을 무시한다. 모든 지역에 대해이 작업을 수행 한 다음 IoU가 0.5보다 큰 지역 집합만 선택한다.
예를 들어 여기에서 빨간색 상자는이 이미지에 대한 ground truth box다. 이제 아래와 같이 RPN에서 4개의 regions을 얻었다고 가정해보자.
여기에서 상자 1과 상자 2의 IoU는 0.5보다 작을 수 있지만 상자 3과 상자 4의 IoU는 약 0.5보다 크다. 그 후. Box 3과 Box 4는이 특정 이미지의 관심 영역이고 Box 1과 Box 2는 무시된다. 다음으로 Mask R-CNN의 마지막 단계를 살펴보자.
Segmentation Mask
IoU 값을 기반으로 하는 RoI가 있으면 기존 아키텍처에 마스크 분기를 추가할 수 있다. 이것은 객체를 포함하는 각 영역에 대한 분할 마스크를 반환한다. 각 영역에 대해 28 X 28 크기의 마스크를 반환 한 다음 추론을 위해 확장한다.
이 이미지의 분할 마스크는 다음과 같다.
여기서 우리 모델은 이미지의 모든 개체를 분할했다. 이것은 이미지의 모든 객체에 대한 마스크를 예측하는 Mask R-CNN의 마지막 단계이다.
Mask R-CNN의 훈련 시간은 상당히 길다. 유명한 COCO 데이터 세트에서 Mask R-CNN을 훈련시키는 데 약 1 ~ 2 일이 걸렸다. 이 기사의 범위에서는 자체 Mask R-CNN 모델을 학습하지 않는다.
대신 COCO 데이터 세트에서 훈련된 Mask R-CNN 모델의 사전 훈련 된 가중치를 사용한다. 이제 Python 코드를 살펴보기 전에 Mask R-CNN 모델을 사용하여 인스턴스 분할을 수행하는 단계를 살펴보자.
Mask R-CNN 구현 단계
이미지 분할 작업을 수행할 시간이다. FAIR (Facebook AI Research)의 데이터 과학자 및 연구원이 만든 mask rcnn 프레임 워크를 사용할 것이다.
Mask R-CNN을 사용하여 이미지 분할을 수행하기 위해 따라야 할 단계를 살펴본다.
1 단계: Clone the repository
먼저 Mask R-CNN에 대한 아키텍처가 있는mask rcnn 저장소를 복제한다.
밑 명령을 사용해서 명령 프롬프트에 저장소를 복제한다.
git clone https://github.com/matterport/Mask_RCNN.git
2 단계: Install the dependencies
- numpy
- scipy
- Pillow
- cython
- matplotlib
- scikit-image
- tensor flow>=1.3.0
- keras>=2.0.8
- opencv-python
- h5py
- imgaug
- IPython
3 단계 : 사전 훈련된 가중치 다운로드 (MS COCO에서 훈련됨)
다음으로 사전 훈련된 가중치를 다운로드해야 한다.이 링크를 사전 훈련된 가중치를 다운로드할 수 있다.이러한 가중치는 MS COCO 데이터 세트에서 학습된 모델에서 얻는다. weight를 download(다운로드) 한 후 1 단계에서 복제 한 Mask_RCNN 저장소의 샘플 폴더 에이 파일을 붙여 넣기
4 단계 : 이미지 예측
마지막으로 Mask R-CNN 아키텍처와 사전 훈련된 가중치를 사용하여 자체 이미지에 대한 예측을 생성한다.
이 모든 것을 Python으로 구현 한 다음 이미지의 객체에 대한 클래스 및 경계 상자와 함께 마스크를 생성한다.
Python에서 Mask R-CNN 구현
import os
import sys
import random
import math
import numpy as np
import skimage.io
import matplotlib
import matplotlib.pyplot as plt
# Root directory of the project
ROOT_DIR = os.path.abspath("../")
import warnings
warnings.filterwarnings("ignore")
# Import Mask RCNN
sys.path.append(ROOT_DIR) # To find local version of the library
from mrcnn import utils
import mrcnn.model as modellib
from mrcnn import visualize
# Import COCO config
sys.path.append(os.path.join(ROOT_DIR, "samples/coco/")) # To find local version
import coco
# Directory to save logs and trained model
#사전 훈련 된 가중치의 경로와 분할을 수행 할 이미지를 정의
MODEL_DIR = os.path.join(ROOT_DIR, "logs")
# Local path to trained weights file
COCO_MODEL_PATH = os.path.join('', "mask_rcnn_coco.h5")
# Download COCO trained weights from Releases if needed
if not os.path.exists(COCO_MODEL_PATH):
utils.download_trained_weights(COCO_MODEL_PATH)
# Directory of images to run detection on
IMAGE_DIR = os.path.join(ROOT_DIR, "images")
#샘플 폴더에 가중치를 배치하지 않은 경우 가중치가 다시 다운로드된다.
#Mask R-CNN 모델을 추론하는 데 사용할 추론 클래스를 생성한다.
class InferenceConfig(coco.CocoConfig):
# Set batch size to 1 since we'll be running inference on
# one image at a time. Batch size = GPU_COUNT * IMAGES_PER_GPU
GPU_COUNT = 1
IMAGES_PER_GPU = 1
config = InferenceConfig()
config.display()
우리가 사용할 Mask R-CNN 모델의 여러 사양을 볼 수 있다. 백본은 앞에서 설명한 것처럼 resnet101이다. 모델에서 반환할 마스크 모양은 COCO 데이터 세트에서 학습되었으므로 28X28이다. 그리고 총 81 개의 수업 (배경 포함)이 있다.
다음과 같은 다양한 다른 통계도 볼 수 있다.
- 입력 모양
- 사용할 GPU 수
- 검증 단계
Loading Weights
다음으로 모델을 생성하고 앞서 다운로드 한 사전 훈련된 가중치를 로드한다.사전 훈련된 가중치가 노트북과 동일한 폴더에 있는지 확인하고 가중치 파일의 위치를 작성해야 한다.
# Create model object in inference mode.
model = modellib.MaskRCNN(mode="inference", model_dir='mask_rcnn_coco.hy', config=config)
# Load weights trained on MS-COCO
model.load_weights('mask_rcnn_coco.h5', by_name=True)
#이제 예측 단계에서 도움이 될 COCO 데이터 세트의 클래스를 정의
# COCO Class names
class_names = ['BG', 'person', 'bicycle', 'car', 'motorcycle', 'airplane',
'bus', 'train', 'truck', 'boat', 'traffic light',
'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird',
'cat', 'dog', 'horse', 'sheep', 'cow', 'elephant', 'bear',
'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie',
'suitcase', 'frisbee', 'skis', 'snowboard', 'sports ball',
'kite', 'baseball bat', 'baseball glove', 'skateboard',
'surfboard', 'tennis racket', 'bottle', 'wine glass', 'cup',
'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',
'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza',
'donut', 'cake', 'chair', 'couch', 'potted plant', 'bed',
'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote',
'keyboard', 'cell phone', 'microwave', 'oven', 'toaster',
'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors',
'teddy bear', 'hair drier', 'toothbrush']
# 이미지를로드하고 모델이 어떻게 작동하는지 살펴 보자
# Load a random image from the images folder
image = skimage.io.imread('sample.jpg')
# original image
plt.figure(figsize=(12,10))
skimage.io.imshow(image)
이것이 우리가 작업할 이미지다. 자전거와 함께 두 대의 자동차 (전면에 1 대, 후면에 1 대)가 있음을 명확하게 식별할 수 있다.
Making Predictions
사전 훈련된 가중치와 함께 Mask R-CNN 모델을 사용하고 이미지에서 개체를 얼마나 잘 분할하는지 확인한다. 먼저 모델에서 예측을 가져온 다음 결과를 플로팅 하여 시각화한다.
# Run detection
results = model.detect([image], verbose=1)
# Visualize results
r = results[0]
visualize.display_instances(image, r['rois'], r['masks'], r['class_ids'], class_names, r['scores'])
이 모델은 이미지에서 자동차와 자전거를 모두 분할하는 데 매우 효과적이다. 각 마스크 또는 분할된 개체를 개별적으로 볼 수도 있다.
먼저 모델에서 예측 한 모든 마스크를 가져와서 마스크 변수에 저장한다. 이제 이러한 마스크는 부울 형식 (True 및 False)이므로 숫자 (1 및 0)로 변환해야 한다.
mask = r['masks']
mask = mask.astype(int)
mask.shape
위는 0과 1의 배열을 제공할 것이다. 여기서 0은 특정 픽셀에 객체가 없음을 의미하고 1은 해당 픽셀에 객체가 있음을 의미한다. 마스크의 모양은 원본 이미지의 모양과 비슷하다. (원본 이미지의 모양을 인쇄하여 확인할 수 있음)
그러나 마스크 모양의 3은 채널을 나타내지 않는다. 대신 모델별로 분할된 개체의 수를 나타낸다. 위의 샘플 이미지에서 모델이 3 개의 물체를 식별했으므로 마스크의 모양은 (480, 640, 3)이다. 5 개의 물체가 있었다면이 모양은 (480, 640, 5)가 되었을 것이다.
이제 원본 이미지와 마스크 배열이 있다. 이미지에서 각 세그먼트를 인쇄하거나 가져오기위해 for 루프를 만들고 각 마스크를 원본 이미지와 곱하여 각 세그먼트를 가져온다.
for i in range(mask.shape[2]):
temp = skimage.io.imread('sample.jpg')
for j in range(temp.shape[2]):
temp[:,:,j] = temp[:,:,j] * mask[:,:,i]
plt.figure(figsize=(8,8))
plt.imshow(temp)
이미지에서 각 마스크 또는 객체를 그리는 방법이며, 흥미롭고 유용한 사용 사례를 가질 수 있다. 전체 이미지에서 세그먼트를 가져오면 지금 전체 이미지를 전처리할 필요가 없고 세그먼트만 처리되므로 계산 비용을 줄일 수 있다.
원문 : https://towardsdatascience.com/computer-vision-instance-segmentation-with-mask-r-cnn-7983502fcad1