본문 바로가기

etc/FastCampus 챌린지

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

728x90
반응형

YOLO 코드 분석

import sys
import numpy as np
import cv2

# Darknet model & config 
model = 'yolov3.weights'   
config = 'yolov3.cfg'
class_labels = 'coco.names'
confThreshold = 0.5
nmsThreshold = 0.4

# Test image file
img_files = ['dog.jpg', 'person.jpg', 'kite.jpg', 'car2.jpg', 
           'dog_1.jpg','car.jpg', 'person1.jpg','person2.jpg' ]

# Network creation ( 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')

# calss_labels 80EA random RGB 배열을 생성
colors = np.random.uniform(0, 255, size=(len(classes), 3))

# out layer names 받아오기
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

    # blob(Binary Large Object) 생성 & 추론  
    # 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 # opencv는 BGR format.. flag 를 swapRB=True 로 설정

    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]) # confidence 값이 0.5보다 큰 bounding box를 모두 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()

 

video 도 돌려보고싶은데

에러가 자꾸 난다

yolov3_tf2.models
yolov3_tf2.utils 이게 자꾸 에러가 남 ㅠ

from absl import app, flags, logging
from absl.flags import FLAGS
import numpy as np
from yolov3_tf2.models import YoloV3, YoloV3Tiny
from yolov3_tf2.utils import load_darknet_weights
import tensorflow as tf

flags.DEFINE_string('weights', './data/yolov3.weights', 'path to weights file')
flags.DEFINE_string('output', './checkpoints/yolov3.tf', 'path to output')
flags.DEFINE_boolean('tiny', False, 'yolov3 or yolov3-tiny')
flags.DEFINE_integer('num_classes', 80, 'number of classes in the model')


def main(_argv):
    physical_devices = tf.config.experimental.list_physical_devices('GPU')
    if len(physical_devices) > 0:
        tf.config.experimental.set_memory_growth(physical_devices[0], True)

    if FLAGS.tiny:
        yolo = YoloV3Tiny(classes=FLAGS.num_classes)
    else:
        yolo = YoloV3(classes=FLAGS.num_classes)
    yolo.summary()
    logging.info('model created')

    load_darknet_weights(yolo, FLAGS.weights, FLAGS.tiny)
    logging.info('weights loaded')

    img = np.random.random((1, 320, 320, 3)).astype(np.float32)
    output = yolo(img)
    logging.info('sanity check passed')

    yolo.save_weights(FLAGS.output)
    logging.info('weights saved')


if __name__ == '__main__':
    try:
        app.run(main)
    except SystemExit:
        pass

    
# python detect_video.py --video 0

 

 

 

 

728x90
반응형