본문 바로가기

etc/FastCampus 챌린지

[패스트캠퍼스 수강 후기] 컴퓨터비전인강 100% 환급 챌린지 19 회차

728x90
반응형

오늘은 복습이다

YOLO 코드리뷰 !

https://pjreddie.com/darknet

 

Darknet: Open Source Neural Networks in C

Nightmare Use Darknet's black magic to conjure ghosts, ghouls, and wild badgermoles. But be warned, ye who enter here: no one is safe in the land of nightmares.

pjreddie.com

 

coco dataset 을 사용 ( coco data set 은 ms에서 객체 검출용으로 특화되어 공개해놓은 트레이닝 셋 , 테스트 데이터 셋 )

일단 cfg(구성파일) 파일과 weights(학습을 시켜둔 모델파일) 파일을 받아줌

 

자 한번 뜯어봅시다

한땀 한땀 주석을 달았다 ㅜ

오늘은 여기까지 ㅜ

import sys
import numpy as np
import cv2

# Darknet 모델 & 설정 파일
model = 'yolov3.weights'   
config = 'yolov3.cfg'
class_labels = 'coco.names'
confThreshold = 0.5
nmsThreshold = 0.4

# 테스트 이미지 파일
img_files = ['dog.jpg', 'person.jpg', 'kite.jpg', 'car2.jpg', 
           'dog_1.jpg','car.jpg', 'person1.jpg','person2.jpg' ]

# 네트워크 생성 ( readNet을 사용해서 파일링 )
net = cv2.dnn.readNet(model, config)


if net.empty():
    print('Net open failed!')
    sys.exit()

# class_labels 불러와서 '\n\' 기준으로 모두 string으로 뽑아와서 list 형태로 classes 에 다시 넣어줌 
classes = []
with open(class_labels, 'rt') as f:
    classes = f.read().rstrip('\n').split('\n')

# 클래스 80개를 랜덤 RGB 배열을 생성
colors = np.random.uniform(0, 255, size=(len(classes), 3))

# 출력 레이어 이름 받아오기

layer_names = net.getLayerNames()
output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()]
#getUnconnectedOutLayers() 에 포함된 layers 의 이름을 불러온다
# 위 2줄의 코드를 실행하게 되면 output_layers = ['yolo_82', 'yolo_94', 'yolo_106'] 문자열이 저장이 됨
# 출력을 3번해서 조합해서 한개의 결과물로 출력

# 실행
# for 문으로 이미지를 한장씩 불러옴

for f in img_files:
    img = cv2.imread(f)

    if img is None:
        continue

    # 블롭 생성 & 추론 / RGB 순서이기 때문에 flag 를 swapRB=True 로 설정
    # Size : ( 320, 320 ) / ( 416, 416 ) / ( 608, 608)
    # resize : 320, 320
    # Scale : 0.00392 ( 1/ 255 ) @ 0 ~ 1 사이로 노멀라이즈 되어있기 떄문에 스케일링 팩터를 줘야 함 (1/255)
    # Mean : [0,0,0]
    # RGB : swapRB=True # BGR 순서에서 RGB 순서로

    blob = cv2.dnn.blobFromImage(img, 1/255., (320, 320), swapRB=True)
    net.setInput(blob)
    outs = net.forward(output_layers) 
    
    #forward(문자열리스트) 에 해당하는 아웃풋을 outs 에 넣어준다

    # outs는 3( 82, 94, 106 번째 layer)개의 ndarray 리스트.
    # outs[0].shape=(507, 85), 13*13*3=507
    # outs[1].shape=(2028, 85), 26*26*3=2028
    # outs[2].shape=(8112, 85), 52*52*3=8112

    h, w = img.shape[:2]

    class_ids = []
    confidences = []
    boxes = []

    for out in outs:
        for detection in out:
            # detection: 4(bounding box) + 1(objectness_score) + 80(class confidence)
            scores = detection[5:]
            # scores : 5번째 값 이상인 것 / 80개 중에서
            class_id = np.argmax(scores)
            # np.argmax(scores) 80개 중에서 최대값이 있는 위치를 class_id 에 넣어준다
            confidence = scores[class_id]
            # 그 위치에서 confidence 값을 확인
            if confidence > confThreshold: # 0.5 이상인 것만 bounding box 취합
                # 바운딩 박스 중심 좌표 & 박스 크기
                # 노멀라이즈 되어 있어서 w,h 를 곱해줘야 실제 영상에 맞는 좌표가 제대로 계산이 됨
                cx = int(detection[0] * w) # center X
                cy = int(detection[1] * h) # center Y
                bw = int(detection[2] * w) # box W
                bh = int(detection[3] * h) # box H

                # 바운딩 박스 좌상단 좌표
                sx = int(cx - bw / 2)
                sy = int(cy - bh / 2)

                boxes.append([sx, sy, bw, bh]) # boxes 라는 list 에 추가
                confidences.append(float(confidence)) # confidences list 에 추가
                class_ids.append(int(class_id)) # class_ids list 에 추가

    # 비최대 억제
    # 
    indices = cv2.dnn.NMSBoxes(boxes, confidences, confThreshold, nmsThreshold) 
    # nmsThreshold = 0.4 이상으로 겹치게 되는 박스들을 중에서
    # confThreshold = 0.5 보다 큰 것들 중에서 가장 큰 confidence 를 갖는 하나만 골라서 indices 에 넣어준다

    for i in indices: # 여기서 indices 는 2차원 행렬로 생성 ( ex n행 1열 로 생성)
        i = i[0] #i[0] 째를 다시 i 로 casting
        sx, sy, bw, bh = boxes[i] # box 정보를 다시 불러온다 , confidence 값이 가장 높은 'i' 외의 다른 box 들은 모두 무시되었음
        label = f'{classes[class_ids[i]]}: {confidences[i]:.2}' #class_ids에 해당하는 문자열을 받아온다
        color = colors[class_ids[i]]
        cv2.rectangle(img, (sx, sy, bw, bh), color, 2)
        cv2.putText(img, label, (sx, sy - 10), # 107 줄의 label 을 putText 로 출력
                    cv2.FONT_HERSHEY_SIMPLEX, 0.7, color, 2, cv2.LINE_AA)

    t, _ = net.getPerfProfile() #net.getPerfProfile() 인퍼런스 시킬때 시간을 계산하고 받아오는 함수
    label = 'Inference time: %.2f ms' % (t * 1000.0 / cv2.getTickFrequency())
    cv2.putText(img, label, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 
                0.7, (0, 0, 255), 1, cv2.LINE_AA) # 좌측 상단에 inference time 출력 

    cv2.imshow('img', img,) # img 출력
    cv2.waitKey() 

cv2.destroyAllWindows()

 

 

 

728x90
반응형