안녕하세요!

YOLO 함수화 및 여러 그림으로 확인해보기 본문

개발일지/ML(Machine Learning),DL(Deep Learning)

YOLO 함수화 및 여러 그림으로 확인해보기

shinyfood 2024. 1. 11. 00:55
728x90
반응형

https://shinyfood.tistory.com/96

 

YOLO 설치 및 객체탐지

YOLO란 무엇인가? YOLO(You Only Look Once) 한개의 네트워크(계충, 모델 같은 의미로 칭함.)에서 객체(물체, 사물)을 탐지 탐지된 객체의 영역(바운딩 박스 - 사각형)과 객체의 이름(사람, 고양이 등...)을

shinyfood.tistory.com

해당 글에서 이어집니다.

원본 이미지의 예측한 위치에 바운딩 박스와 레이블(이름), 정확도 출력하기

 

net = cv2.dnn.readNet("./yolo/config/yolov3.weights",
                     "./yolo/config/yolov3.cfg")

classes = []

# open(): 파일 열기, r: 읽기, w:쓰기, b가붙으면 바이너리
# f가 곧 open(내용물) 을 뜻하는 변수
with open("./yolo/config/coco.names", "r") as f :
    classes = [line.strip() for line in f.readlines()]
                # strip() : 왼쪽 공백 제거
                # readlines() : 파일 내의 문장들을 행단위로 모두 읽어들이기

 

해당 폴더에 해당 파일들을 각각 놓고 실행한다.

 

def predict_yolo(img_path):
    # 이미지 
    img = cv2.imread(img_path)
    # BGR을 RGB로 변환하기
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    #높이 너비 채널(색상)로 분리
    height, width, channels = img.shape

    layer_names = net.getLayerNames()
    
    output_layer = [layer_names[i-1] for i in net.getUnconnectedOutLayers()]

    # 원본 이미지 데이터를 Blob로 변환하면서, 동시에 정규화(사이즈 통일)하기
    blob = cv2.dnn.blobFromImage(
            img,
            1/256,
            (416,416),
            (0, 0, 0),
            swapRB = True,
            crop = False
            )
    
    net.setInput(blob)
    outs = net.forward(output_layer)

    # 인식된 객체(물체)의 인덱스 번호를 담을 변수
    class_ids = []
    # 인식된 객체의 인식률(정확도)를 담을 변수
    confidences = []
    # 인식된 객체의 좌표값을 담을 변수
    boxes= []

    # 출력계층이 반환한 값들을 처리하기 위하여 반복문 사용
    for out in outs :
        #print(out)
           # 인식된 객체에 대한 정보가 담겨 있음.
        for detection in out :
            # 인식된 객체에 대한 정보 추출하기(클래스=레이어 명칭) 확률 정보
            scores = detection[5:]
            # print(len(score),score)
            """scores 값이 가장 큰 인덱스 번호 찾기
              - 0은 인식 못했다는 의미
              - 가장 큰 인덱스 값 : 렝리블 명칭(이름)이 있는 리스트 배열의 인덱스 값을 의미함
            """
            
            class_id = np.argmax(scores)
            # print(class_id)
    
            """score 값이 가장 큰 위치의 인덱스 번호에 해당하는 값은 인식률(정확도)를 의미"""
            confidence = scores[class_id]
            # print(confidence)
    
            # 정확도(인식률) 50% 이상인 데이터에 대해서 처리하기
            if confidence > 0.5 :
                # print(f"score : {scores}")
                # print(f"class_id : {class_id}")
                # print(f"class_id : {classes[class_id]}")
                # print(f"confidence : {confidence}")
                """ 바운딩 박스의 상태적 x, y 좌표비율 추출하여 
                    - 실제 중심점 길이 좌표(절대 좌표)로 변환하기
                """
                # 실제 중심점 x와 y 좌표
                center_x = int(detection[0] * width)
                center_y = int(detection[1] * height)
                """바운딩 박스의 상대적 너비와 높이 비율 추출하기"""
                # 실제 너비, 높이로 변환
                w = int(detection[2] * width)
                h = int(detection[3] * height)
                # print(center_x, center_y, w, h)
    
                # 이미지 좌표계는 좌상단이 0,0 그래프 좌표계는 좌하단이 0,0
                """시작점 좌표 계산하기"""
                x = int(center_x - w / 2)
                y = int(center_y - h / 2)
                # print(x, y)
                
                """실제 x,y, 너비, 높이 값을 리스트로 담기"""
                boxes.append([x, y, w, h])
    
                """객체 인식률(정확도) 실수형 타입으로 담기"""
                confidences.append(float(confidence))
    
                """레이블 명칭(이름) 인덱스 담기"""
                class_ids.append(class_id)
                

    indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.1, 0.4)
    # <폰트스타일 지정>
    font = cv2.FONT_HERSHEY_PLAIN

    colors = np.random.uniform(0,255, size=(len(boxes), 3))
    # 인식된 객체가 있는 경우
    if len(indexes) > 0 :
        # 무조건 1차원으로 변환
        # print(indexes.flatten())
        for i in indexes.flatten() :
            #x,y,w,h 값 추출하기
            x, y, w, h = boxes[i]
            # print(x, y, w, h)
            
            # 실제 레이블 명칭(이름) 추출하기
            label = str(classes[class_ids[i]])
            print(label)
    
            # 인식률(정확도) 추출하기
            confidence = str(round(confidences[i], 3))
            # print(confidence)
    
            # 바운딩 박스의 색상 추출하기
            color = colors[i]
            # print(color)
    
            """ 바운딩 박스 그리기
                - 마지막 값 2 : 바운딩 박스 선의 굵기(thickness)
            """
            cv2.rectangle(img, (x, y), ((x+w), (y+h)), color, 2)
    
            """인식된 객체의 레이블 명칭(이름)과 정확도 넣기(그리기)"""
            cv2.putText(img, label + " " + confidence, 
                       (x, y+20), font, 2, (0,255,0), 2)
    
        plt.axis("off")
        plt.imshow(img)
        plt.show()
    #인식된 객체가 없는 경우
    else :
        print("I can't detecting!!! No Object!!!")

이제 신나게 이 함수를 부르기만 하면 된다.

 

"""테스트이미지 모두 가지고오기"""
import glob
import random

#OpenCV 프레임워크 라이브러리
import cv2

paths = glob.glob("./yolo/new_img/*.jpg")

# 랜덤하게 이미지 한개 선택하기
img_path = random.choice(paths)

# 파일 경로의 문자열 내에 역슬래시를 정상적인 슬래시로 변경

img_path = img_path.replace("\\","/")

# 함수 호출하기

print(f"사용된 이미지 : {img_path}")
predict_yolo(img_path)

사용된 이미지 : ./yolo/new_img/1212.jpg
person
person
person
person
person
person
person
person
person

이런식으로 출력된다.

 

이걸 사람으로 인식하네....

728x90
반응형