코딩헤딩

Deep learning[딥러닝] YOLO 객체탐지 네트워크 Camera 사 본문

머신러닝 | 딥러닝

Deep learning[딥러닝] YOLO 객체탐지 네트워크 Camera 사

멈머이 2024. 1. 11. 23:10
728x90

https://coding-heading.tistory.com/104

 

Deep learning[딥러닝] YOLO 객체탐지 네트워크 가중치 모델 사용

https://coding-heading.tistory.com/103 Deep learning[딥러닝] YOLO 객체탐지 네트워크 기초 - "욜로"라고 칭한다. - 한 개의 네트워크(계층, 모델 같은 의미로 칭함)에서 객체(물체, 사물)를 탐지 - 탐지된 개체의

coding-heading.tistory.com

이전 글에서는 정적인 이미지에서 객체를 탐지하는 프로그램을 만들었는데 이번에는 카메라에서 들어오는 동영상을 처리하는 프로그램을 해보겠다.


### 사용할 라이브러리

import cv2
import numpy as np

 

* 데이터 읽어 들이기

VideoSignal = cv2.VideoCapture(0)
VideoSignal

결과 : < cv2.VideoCapture 0000019491FEDF70> 

- 웹캠 신호 받기
    - 어떤 카메라를 사용할지 채널 선택
    - 여러 개의 카메라가 있으면, 카메라 별로 번호가 부여된다.
    - 내 PC에 1개만 연결되어 있다면, 0번 카메라 번호가 부여된다.

* YOLO 모델 생성하기

YOLO_net= cv2.dnn.readNet("./yolo/config/yolov2-tiny.weights",
                          "./yolo/config/yolov2-tiny.cfg")
YOLO_net

결과 : < cv2.dnn.Net 0000019491FEDA30>

 

* 라벨링 명칭(이름) 데이터 읽어 들이기

classes = []

with open("./yolo/config/coco.names", "r") as f:
    
    classes = [line.strip() for line in f.readlines()]

classes

결과 : 

['person',
 'bicycle',
 'car',

    .

    .

    .

 

* 출력 계층 이름 추출하기

### YOLO 레이어 전체 이름 추출
layer_names = YOLO_net.getLayerNames()
layer_names

### YOLO 출력 레이어(켸층)만 이름 추출
output_layer = [layer_names[i-1] for i in YOLO_net.getUnconnectedOutLayers()]
output_layer

 

* 윈도우 창 관리 영역 : 카메라 영상 처리 영역

cv2.namedWindow("YOLO3_CM_01")

* 대표 윈도우 설정
  - 윈도우 창 관리는 이름으로 한다.


### * 사용할 라이브러리
import cv2
import numpy as np

### * 데이터 읽어들이기
"""
 * 웹캠 신호 받기
    - 어떤 카메라를 사용할지 채널 선택
    - 여러개의 카메라가 있으면, 카메라 별로 번호가 부여된다.
    - 내 PC에 1개만 연결되어 있다면, 0번 카메라 번호가 부여된다.
"""
VideoSignal = cv2.VideoCapture(0)

### * YOLO 모델 생성하기
YOLO_net= cv2.dnn.readNet("./yolo/config/yolov2-tiny.weights",
                          "./yolo/config/yolov2-tiny.cfg")

### * 라벨링 명칭(이름) 데이터 읽어들이기
classes = []

with open("./yolo/config/coco.names", "r") as f:
    
    classes = [line.strip() for line in f.readlines()]

### * 출력 계층 이름 추출하기
### YOLO 레이어 전체 이름 추출
layer_names = YOLO_net.getLayerNames()

### YOLO 출력 레이어(켸층)만 이름 추출
output_layer = [layer_names[i-1] for i in YOLO_net.getUnconnectedOutLayers()]

cv2.namedWindow("YOLO3_CM_01")

"""
  - 카메라를 통한 영상처리 시에는 원되우 창을 계속 띄어 놓아야 한다
  - 정지 옵션(윈도우 창 닫기)은 필수
"""
while True:
### ---------------------------------------------widow 창관리----------------------------------------------------
    """
    * 카메라에서 영상 읽어 들이기 : read()함수 사용
      - 영상파일 또는 카메라로부터 프레임을 읽어오는 역할 수행
        * rec : 읽어 들이는 프레임이 있는지 여부 판단(True or False)
              : 더 이상 읽어들일 프레임이 없으면 False가 됨
        * frame : 실제로 읽어들인 프레임(이미지) 자체
                : 더 이상 읽어들일 프레임이 없으면 None이 됨
                : 우리가 사용할 변수 
    """
    ret, frame = VideoSignal.read()

    ### * Frame정보에서 높이, 너비, 체널(흑백 또는 컬러) 추출하기
    h, w, c = frame.shape

###-----------------------------------------------YOLO----------------------------------------------------
    ### * BLOB 데이터 구조화
    blob = cv2.dnn.blobFromImage(
        
        # 카메라에서 읽어들인 frame(미미지) 데이터
        image = frame,

        # 이미지 픽셀 값 정규화(스케일링)
        scalefactor = 0.00392,

        # YOLO모델이 사용할 크기로 조정
        size = (416, 416),

        # BRG or RGB 선택
        #  - True 이면 : OpenCV의 기본 BRG 색상 순서를 RGB로 변경
        swapRB = True,

        # 위에 size로 조정 후 어떻게 할지 결정
        #  - True 이면 : 잘라내기
        #  - Flase 이면 : size로 전체 조정하기
        crop = False
    )

    ### * YOLO입력 데이터로 넣어주기
    YOLO_net.setInput(blob)

    ### * YOLO모델에 출력계층 이름을 알려주고, 출력 결고 받아오기
    outs = YOLO_net.forward(output_layer)

###---------------------------------------리스트 변수-------------------------------------------------
    ### * 라벨(명칭, 이름) 담을 리스트 변수
    class_ids = []
    ### 인식률(정확도) 담을 리스트 변수
    confidences =[]
    ### 바운딩박스의 좌표를 담을 리스트 변수
    boxes = []

    ### 출력결과(여러개)(인식된 객체 여러개)
    for out in outs:
        
        # 실제 객체 인식 데이터 처리
        for detection in out:
            
            # 인식 데이터의 인식률(정밀도)
            scores = detection[5:]

            # 인식률(정밀도)가 가장 높은 인덱스 위치 열기 : 라벨(명칭, 이름)의 위치값
            class_id = np.argmax(scores)

            # 인식률(정밀도) 값 추출하기 : class_id의 인덱스 번호 위치값이 정밀도
            confidence = scores[class_id]

            ### 정밀도가 50% 이상인 경우만 처리 : 기준은 자유롭게 처리
            if confidence > 0.5:

                # 중앙값의 좌표 비율에 실제 너비로 연산하여 중앙 x값 추출
                center_x = int(detection[0] * w)
                # 중앙값의 좌표 비율에 실제 높이로 연산하여 중앙 y값 추출
                center_y = int(detection[1] * h)

                ### 바운딩박스의 실제 너비와 높이 계산하기
                dw = int(detection[2] * w)
                dh = int(detection[3] * h)

                ### 바운딩박스의 시작 좌표(x, y) 계산하기
                x = int(center_x - dw /2)
                y = int(center_y - dh /2)

                boxes.append([x, y, dw, dh])
                confidences.append(float(confidence))
                class_ids.append(class_id)

    ### * 증복된 바운딩박스 제거하기
    # - 정확도가 0.45보다 작으면 제거하기
    indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.45, 0.4)

    ### 인식된 객체마다 바운딩박스 처리하기
    for i in range(len(boxes)):

        # 중복 제거 이후 남은 바운딩박스의 정보만 이용
        if i in indexes:
            # 해당 객체에 대한 좌표값
            x, y, w, h = boxes[i]

            # 해당 객체에 대한 라벨값
            label = str(classes[class_ids[i]])

            # 해당 객체에 대한 정확도
            score = confidences[i]

            # 바운딩박스 그리기
            cv2.rectangle(
                # 원본이미지(frame)
                frame,
                # 시작 좌표
                (x, y),
                # 종료좌표
                (x+w, y+y),
                # 선 색상
                (0, 0, 255),
                # 선 굵기
                5
            )

            # 라벨 이미지에 택스트 그리기
            cv2.putText(
                # 지금까지 그려진 frame 이미지
                img = frame,
                # 추가할 텍스트(문자열 타입으로)
                text = label,
                # 텍스트 시작 위치 지정
                org = (x, y-20),
                # 텍스트 font스타일 
                fontFace = cv2.FONT_ITALIC,
                # font 크기
                fontScale = 0.5,
                # font 색상
                color = (255, 255, 255),
                # font 굵기기
                thickness = 1
            )
    
    ### * 윈도우 창 open하기
    cv2.imshow("YOLO3_CM_01", frame)

    ### * 윈도두 창 크기 조절하기
    cv2.resizeWindow("YOLO3_CM_01", 650, 500)


    ### * 키보드에서 아무키나 눌리면 while문 종료하기
    ### while문 종료하기
    if cv2.waitKey(100) > 0:
        ### 윈도우 무조건 종료
        cv2.destroyAllWindows()
        break

    ### 키보드에서 q입력 시 종료시키기
    if cv2.waitKey(1) & 0xFF == ord("q"):
        ### 윈도우 무조건 종료
        cv2.destroyAllWindows()
        break

  - 윈도우 종료 후 재실행 시 안 되는 경우가 발생할 수 있음
    - 이때는 주피터가 실행된 프롬프트 창에서 [CTRL+C] 정지 후, 다시 실행

728x90