진행중 프로젝트(1)

장준영·2021년 5월 20일
0

프로젝트

목록 보기
1/2

현재 PyQt를 이용해서 Yolo v4에 사용할 Img DataAugmentation된 데이터를 만들어줄 Tool을 제작하고 있습니다.

저번 PyQt편에서 구현했던것과 얼마 큰 차이는 없습니다
일단은 UI보다는 기능에 중점을 두자! 라는 생각으로 조금 더 기술적인것을 고민을 했습니다.
AugMix, ImgAug 등등 여러가지들을 고민해봤고
아무래도 프로젝트 자체가 Object Detection에 관한 Data Augmentation을 하는것이기에
Ground-truth를 이용할수 있는 ImgAug가 적합하다고 생각하여서 위주로 작업했습니다
사진에 나온대로 선택한 Img Data를 적용하여 Random한 Augmentation을 하였을시에,
나오는 결과는 이러합니다

예시로 10장정도를 Random하게 만들어보았는데 이러한 결과로 나옵니다.
사실 여기까지만 해도 '끝난거 아닐까?' 라는 생각이였는데
중요한걸 잊고있었습니다..
Object Detection에 사용하기위해서 Ground-truth를 이용가능한 Imgaug를 쓴건데
정작 이 기능을 이용도 안했다는 느낌입니다...
따라서 부랴부랴 Label Tool을 가져와서 label부터 잡았습니다

ImgAug의 트레이드마크인 쿼카사진으로 Face label 및 EYE 라벨을 잡아보았습니다.
이후 원하고자 하는것은 Json파일이나 Yolo에 맞는 label값 파일을 추출해 내야합니다.
여기서 저는 Pascal Voc파일과 yolo파일로 label 데이터 값을 추출해서 저장했습니다.

Pascal voc로 Xml형식으로 저장한 label data

Yolo형식으로 저장한 txt형식의 label data

우선 Face label 1개와 eye label 2개로, 총 3개의 label을 만들어서
label data정보를 추출하여 저장하였습니다.
이후 기존의 label data를 Imgaug를 통해서 Augmentation을 시행시에
label의 정보또한 augmentation 된 img와 같이 제대로 이동되는지 확인하는 간단한 예제를
시행하였습니다.

import cv2
import numpy as np
import imgaug as ia
import imgaug.augmenters as iaa
import xml.etree.ElementTree as ET
img=cv2.imread('C:/Users/SS1/PycharmProjects/gangso/no/quokka.jpg',cv2.IMREAD_COLOR)
# xml 파일 파싱하기
tree = ET.parse('quokka.xml')
bounding box를 여러개 지정 가능하니, 각 라벨들을 집합으로 빼옴
label = tree.findall("object")
label_true = [x.findtext("name")for x in label]
print(label_true[0])
# label별로 bounding 박스 값을 가져온다.
val = tree.findall("object/bndbox")
val_xmin = [x.findtext("xmin")for x in val]
val_ymin = [x.findtext("ymin")for x in val]
val_xmax = [x.findtext("xmax")for x in val]
val_ymax = [x.findtext("ymax")for x in val]
# augmentation 하고자 하는 사진에, xml 파싱데이터로 bounding box 생성
input_img = img[np.newaxis, :, :, :]
bbox = [ia.BoundingBox(x1=float(val_xmin[0]), y1=float(val_ymin[0]),
                       x2=float(val_xmax[0]), y2=float(val_ymax[0]),label=label_true[0])]
bbox1 = [ia.BoundingBox(x1=float(val_xmin[1]), y1=float(val_ymin[1]),
                       x2=float(val_xmax[1]), y2=float(val_ymax[1]),label=label_true[1])]
print(input_img.shape)
# Aug 연산 예시
seq = iaa.Sequential([
    iaa.Multiply((1.2, 1.5)),
    iaa.Affine(
        scale=(0.5, 0.7),
        rotate=45)])
# Aug연산을 이용해서 bounding box도 같이 aug
org_img, org_bbox, org_bbox1 = input_img, bbox, bbox1
print('label1= ',  org_bbox[0])
print('label2= ', org_bbox1[0])
org = org_bbox[0].draw_on_image(org_img[0], size=5, color=[0, 255, 0])
input_img1 = org[np.newaxis, :, :, :]
org1 = org_bbox1[0].draw_on_image(input_img1[0],size=5, color=[0, 255, 0])
# 연산 이미지 처리
aug_img1, aug_bbox0 = seq(images=input_img, bounding_boxes=bbox)
aug_img1, aug_bbox1 = seq(images=input_img1, bounding_boxes=bbox1)
draw1 = aug_bbox1[0].draw_on_image(aug_img1[0], size=5, color=[0, 255, 0])
# 연산되어 변형된 labeling data를 표시해준다.
print('aug_label1 = ', aug_bbox0[0])
print('aug_label2 = ', aug_bbox1[0])
res = np.hstack((org1, draw1))
cv2.imshow('res', res)
cv2.imwrite('result.jpg',org1)
cv2.waitKey(0)
cv2.destroyAllWindows()

간결하지 못한 스파게티같은 코드로 짜보긴 했는데
우선은 Label Data또한 Augmentation을 통해 원활히 변경되는지 확인을 하기 위함입니다.
기존의 label data에서 label 1과 2만 사용하여 구현해보았습니다
(Face label, eyes1 label)

label정보를 적용한 input image입니다.
이를 간단한 Augmentation을 통해서 결과를 도출할 시

좌측이 기존 input이미지 이고, 우측이 간단한 Augmentation을 통해 추출된 output img인데
img에 표시된 label이 img degree변화에도 원활하게 따라가는것을 볼 수 있습니다.
혹시 표시된 img만 그런것이 아닐까? 라는 생각에 위의 코드에서 print로 좌표값을 추출해보았는데

밑에 aug_label1,2가 augmentation된 Bounding Box의 label data들인데
변경된 img output과 같이 원활히 label data를 추출해내는것을 알 수 있습니다.
이를 통해서 label data를 기존의 xml파일이나 yolo버전 파일 형식으로 같이 추출을 해줍니다.
맨위에서 보여드렸던 PyQt를 이용한 Augmentation툴에 위 기능을 집어넣어
최종적으로는 yolo모델 학습을 위한 Data Augmentaiton 툴을 형성하는 마무리 단계에 있습니다
조만간 마무리단계 완성모델들로 작성하겠습니닷

profile
zZ.. zZ.. 🧑‍💻

1개의 댓글

comment-user-thumbnail
2021년 11월 30일

안녕하세요 재미있는 프로젝트를 진행중이시네요. 실례가 안된다면 혹시 해당 프로젝트 완성되었을까요? 사용해보고싶어서요.

답글 달기