Image Segmentation을 위해서는 마스킹 데이터가 필요하다.
마스킹 된 정답 데이터가 존재하지 않기 때문에 직접 만들어 줄 필요가 있었다.
VIA : VGG Image Annotator를 이용해서 마스킹을 해 준 후 이미지로 변환하여 정답데이터로 이용했다.
▶ VIA
Visual Geometry Group - University of Oxford
Abhishek Dutta, Ankush Gupta and Andrew Zisserman Overview VGG Image Annotator is a simple and standalone manual annotation software for image, audio and video. VIA runs in a web browser and does not require any installation or setup. The complete VIA soft
www.robots.ox.ac.uk
VGG Image Annotator
Starting VGG Image Annotator ... VGG Image Annotator version 1.0.6 VGG Image Annotator (VIA) is an open source project developed at the Visual Geometry Group and released under the BSD-2 clause license. With this standalone application, you can define regi
www.robots.ox.ac.uk
아래와 같이 이미지를 마스킹한 후 json파일로 다운을 받아 이미지로 변환을 했다.
우리가 필요한 image segmentation은 sementic image segmentation으로
청경채 객체별로 구분할 필요는 없었고, 청경채이다 아니다만 구분하면 되는 간단한 이진 분류였다.
이미지에 있는 객체도 청경채뿐이었기 때문에 더욱 간단한 케이스 였다.
그래서 이미지 한 장당 0과 1로만 이루어진 마스킹 이미지 한 장이 필요했다.
create_seperate_mask_img : 이미지별로 마스킹된 객체별 마스크 이미지를 생성
import os
import cv2
import json
import matplotlib.pyplot as plt
import numpy as np
def create_seperate_mask_img(json_file_name) :
source_folder = os.path.join(os.getcwd(), "train_images")
json_path = json_file_name # Relative to root directory
count = 0 # Count of total images saved
file_bbs = {} # Dictionary containing polygon coordinates for mask
file_names_dict = {}
file_names = []
# Read JSON file
with open(json_path) as f:
data = json.load(f)
# Extract X and Y coordinates if available and update dictionary
# json 딕셔너리에서 x, y 좌표 추출
def add_to_dict(data, itr, key, count, file_name):
# data : json, itr : 이미지 이름, key : mask 이름, count : mask index
try:
x_points = data[itr]["regions"][str(count)]["shape_attributes"]["all_points_x"]
y_points = data[itr]["regions"][str(count)]["shape_attributes"]["all_points_y"]
except:
print("No BB. Skipping", key)
return
all_points = []
for i, x in enumerate(x_points):
all_points.append([x, y_points[i]])
file_bbs[key] = all_points
file_names_dict[key] = file_name
# file_bbs = {image이름-mask이름 : [x points, y points]}
## Json 파일에서 x,y points를 뽑아 file_bbs 에 저장.
for itr in data:
file_name_json = data[itr]["filename"]
file_names.append(file_name_json)
sub_count = 0
# Contains count of masks for a single ground truth image
if len(data[itr]["regions"]) > 1: # 마스크의 개수가 여러개
for _ in range(len(data[itr]["regions"])):
key = file_name_json[:-4] + "-" + str(sub_count+1)
add_to_dict(data, itr, key, sub_count, file_name_json)
sub_count += 1
else: # 마스크 개수가 1개
add_to_dict(data, itr, file_name_json[:-4], 0, file_name_json)
print("\nDict size: ", len(file_bbs))
########## 경로 생성
mask_folder = os.path.join(os.getcwd(), "masks")
try :
os.mkdir(mask_folder)
except :
print('mask folder already exist')
for f in file_names :
try :
os.mkdir(os.path.join(mask_folder, f[:-4]))
except :
print('folder already exist')
######### 마스크 저장
for itr in file_bbs:
num_masks = itr.split("-")
save_directory = os.path.join(mask_folder, file_names_dict[itr][:-4])
# Dimensions should match those of ground truth image
img = cv2.imread(source_folder+'/'+file_names_dict[itr])
MASK_WIDTH = img.shape[0]
MASK_HEIGHT = img.shape[1]
mask = np.zeros((MASK_WIDTH, MASK_HEIGHT))
try:
arr = np.array(file_bbs[itr])
except:
print("Not found:", itr)
continue
count += 1
cv2.fillPoly(mask, [arr], color=(255))
if len(num_masks) > 1:
cv2.imwrite(os.path.join(save_directory, itr + ".png") , mask)
else:
cv2.imwrite(os.path.join(save_directory, itr + ".png") , mask)
print("Images saved:", count)
위의 함수를 실행하면 아래와 같은 구조가 된다.
merge_masks : 여러 마스크 이미지를 한 장의 마스크로 합침
import os
import cv2
import json
import matplotlib.pyplot as plt
import numpy as np
import shutil
import glob
def merge_masks() :
# 현재 경로에서 실행
source_folder = os.path.join(os.getcwd(), "masks")
mask_folder_list = list(filter(os.path.isdir, glob.glob(source_folder+'/*')))
for case in mask_folder_list :
curr_directory = os.path.join(source_folder, case)
mask = None
try :
for i, img in enumerate(os.listdir(curr_directory)) :
img_directory = os.path.join(curr_directory, img)
if i == 0 :
mask = plt.imread(img_directory)
else :
other_mask = plt.imread(img_directory)
mask = np.logical_or(mask, other_mask)
mask = mask.astype(np.float32)
cv2.imwrite(os.path.join(source_folder, case+'.png'), mask)
print('Image Saved')
if os.path.exists(curr_directory):
shutil.rmtree(curr_directory)
except :
print('Mask Image Not Found')
위의 함수까지 실행해주면 다음과 같은 결과를 얻을 수 있다.
참고
Generating Image Segmentation Masks — The Easy Way
…in under 5 Minutes. Trust me :)
towardsdatascience.com
'Projects' 카테고리의 다른 글
[MLOps] wandb sweep으로 하이퍼파라미터 튜닝하기 - jupyter notbebook에서 실행하기 (0) | 2022.07.12 |
---|---|
multi-columns: stratify split, 여러 개의 클래스 stratify로 데이터셋 분리하기 (0) | 2022.06.14 |
데이콘 경진대회 참여 - 주제, 데이터 (0) | 2022.05.24 |
[proj] 기상데이터와 대기질데이터를 이용한 미세먼지 단계 예측 (0) | 2022.04.19 |
[kaggle] Titanic Dataset predictions (0) | 2022.03.22 |