# 동영상 오브젝트 디텍션
import cv2 #영상이나 이미지 데이터 전처리를 위한 모듈
import numpy as np
LABELS = ['gorani','raccoon'] # 라벨 데이터
#gorani, raccoon
CONFIDENCE = 0.3 # 사물이 라벨에 해당하는 데이터인지에 대한 확률 임계치
THRESHOLD = 0.3 #NMS(Num Max Suppression) 박스 안에 사물이 존재할 확률의 임계치
#yolo4버전으로 학습시킨 환경구성파일과 가중치를 로드해서 신경망 구성
net = cv2.dnn.readNetFromDarknet('c:\\animal\\yolov4_custom.cfg','c:\\animal\\yolov4_custom_final.weights')
classes =['gorani','raccoon'] # 화면 박싱할 때 사용할 클래스명을 classes에 담음
#cap = cv2.VideoCapture('D:\\test\\New folder\\test1.mp4')
cap = cv2.VideoCapture('c:\\animal\\test2.mp4') #원본 동영상 위치, 이름 / 영상이 홈디렉토리 밑에 있다면 경로 안써도 됨 -> 가끔 parsing 오류
font = cv2.FONT_HERSHEY_PLAIN # 디텍션할때 나타나는 폰트
colors = np.random.uniform(0, 255, size=(100, 3)) # 폰트 컬러
# 동영상 프레임의 가로와 세로 사이즈 변수에 담음
frame_size = (cap.get(cv2.CAP_PROP_FRAME_WIDTH), cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
#생성되는 영상의 동영상 형식을 mp4로 지정
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
fps = cap.get(cv2.CAP_PROP_FPS) #동영상을 프레임별로 가져옴
# 결과 동영상 출력
out = cv2.VideoWriter('c:\\animal\\detections.mp4', fourcc, fps, (int(frame_size[0]), int(frame_size[1])))
while True:
ret, img = cap.read() # ret변수에는 True가 들어감. 동영상에서 frame을 가져와 img에 담음
print(img) #동영상에서의 하나의 이미지인 img 출력
if not ret: # 더이상 가져오지 않을 경우 False -> break걸겠다
break
# height, width, _ = img.shape 이미지 딱 하나에 대한 높이와 넓이를 구했는데
#이번에는 동영상 frame에 대해 넓이와 높이를 구해야하므로
# cv2.CAP_PROP_FRAME_WIDTH/HEIGHT를 사용
width,height = (cap.get(cv2.CAP_PROP_FRAME_WIDTH), cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
#동영상 속의 frame 이미지 전처리 함수인 blobFrameImage를 사용해서 학습할 당시에
#수행했던대로 전처리 되게 함
blob = cv2.dnn.blobFromImage(img, 1/255, (416, 416), (0,0,0), swapRB=True, crop=False)
#학습할 당시에 학습 데이터를 정규화 했으면 object detection 할때도(데이터를 넣을때도)
# 정규화(1/255)를 해야함.
# 학습할 때 사용했던 이미지 사이즈로 resize 해줘야함. 다크넷 신경망 학습할 때
# (416,416)으로 학습함.
#(0,0,0) (red,green,blue)행렬릐 평균값을 널어서 기존 픽셀 값에서 빼주는 작업을 학습할 때
# 학습했다면 여기에 그 평균값 3개를 적어줘야함. 안했다면 안적어줘도 됨.
# 학습할 때 평균값 빼는 이유는 학습이 잘되게 하려고 하는 것같음?
# swapRB = True는 RGB를 BGR로 변경
# openCV가 RGB가 아니라 BGR순서기 때문에 변경함.
# crop = False 여기서 설명 확인 https://m.blog.daum.net/architekton/97
#학습된 가중치와 환경구성파일이 셋팅된 다크넷 신경망에 전처리된 frame을 넣음
net.setInput(blob)
#다크넷 신경망에 어느정도 결론이 난 맨 마지막층들의 이름을 가져와서 변수에 담음
output_layers_names = net.getUnconnectedOutLayersNames()
layerOutputs = net.forward(output_layers_names) # 마지막 층등을 신경망에 흘려보냄
# 하나의 사진당 박싱을 하는 윈도우들이 총 507개 생김
# 사물 검출을 위해서 사용할 비어있는 리스트 3개 선언
boxes = []
confidences = []
class_ids = []
for output in layerOutputs: # 507개의 박스 데이터 하나씩 불러옴
for detection in output: # 리스트 안에 리스트로 되어 있어서 한번 더 for문 사용해 리스트 안의 요소 가져옴
scores = detection[5:] # 507개의 박스에서 고라니와 너구리일 확률 scores에 담음
class_id = np.argmax(scores) # [0.960552 0.] 이렇게 될 경우 0이 class_id에 담김
confidence = scores[class_id] #[0]이니까 0.960552가 confidence에 담기고
if confidence > 0.2: # confidence값이 0.2보다 크면
center_x = int(detection[0]*width) #0~1사이로 변경된 좌표값을 실제 좌표로 변경
center_y = int(detection[1]*height)
w = int(detection[2]*width) #실제 가로
h = int(detection[3]*height) # 실제 높이
x = int(center_x - w/2) # 박스의 중심 x좌표
y = int(center_y - h/2) # 박스의 중심 y좌표
boxes.append([x, y, w, h]) #원하는 사물이 있는 박스 정보를 boxes에 넣음
confidences.append((float(confidence))) #0.2보다 큰 확률 데이터를 confidence에 넣음
class_ids.append(class_id) #0아니면 1이 class_ids에 담김
indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.2, 0.4)
# 여기서 0.2는 사물을 맞힐 확률이고 0.4는 박스 안에 사물이 있을 확률 임계치
# 임계치보다 더 큰 정보들만 indexes에 담음
if len(indexes)>0: #indexes에 값이 있다면
for i in indexes.flatten(): #boxes리스트에 (x,y,w,h)에 대한 정보를 flatten시켜서
x, y, w, h = boxes[i] #x,y,w,h에 넣음
label = str(classes[class_ids[i]]) #라벨링 값 담고
confidence = str(round(confidences[i],2)) # confidence값 넣고
color = colors[i]
cv2.rectangle(img, (x,y), (x+w, y+h), color, thickness = 2)
cv2.putText(img, label + " " + confidence, (x, y+20), font, 2, (255,255,255), 2)
# cv2의 putText를 이용해 라벨과 확률을 중심좌표에서 y축으로 +20지점에 표시합니다.
cv2.imshow('Image', img)
#cap = cv2.VideoCapture(input_names[0])
#win_name = 'Video detection'
#cv2.namedWindow(win_name)
out.write(img) #동영상 기록
key = cv2.waitKey(1) #opencv에서 제공하는 입력을 기다리는 대기 함수를 실행하고
if key==27: #취소키를 누르면 (esc지정키)
break
out.release() # 디텍션된 동영상에 대한 데이터가 있는 변수 지움
cv2.destroyAllWindows() # 열어높은 동영상 플레이창 닫음
문제215. 이번에는 정규화 하지 말고 detections2.mp4로 동영상을 생성하시오.
=> 정규화하지 않고 동영상 돌리면 정확도가 현저히 낮아짐. 정규화해서 돌려야함
반응형
'Study > class note' 카테고리의 다른 글
딥러닝 / 강아지 품종 detection (0) | 2022.05.10 |
---|---|
딥러닝 / 실시간 웹캠 오브젝 디텍션 (0) | 2022.05.09 |
딥러닝 / 동영상 object detection (0) | 2022.05.06 |
딥러닝 / 고속도로에서 죽는 동물 살리기 GUI 두번째_버튼 두 개 + 사진 저장하지 않고 바로 불러오기 (0) | 2022.05.06 |
딥러닝 / 고라니, 너구리 디텍션2 (0) | 2022.05.04 |