일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 크롤링(crawling)
- 데이터베이스
- HeidiSQL
- 데이터 수집
- tensorflow
- 데이터전처리
- 데이터 가공
- SQL예제
- MariaDB
- 알고리즘기초
- 정확도
- python기초
- 딥러닝
- python
- 회귀모델
- 파이썬
- keras
- Deep Learning
- 시각화
- 훈련
- 해석
- pythone
- pandas
- Database
- 데이터
- sklearn
- 데이터 분석
- 예측
- 머신러닝
- 선형회기모델
- Today
- Total
코딩헤딩
Deep learning[딥러닝] YOLO 객체탐지 네트워크 가중치 모델 사용 본문
https://coding-heading.tistory.com/103
Deep learning[딥러닝] YOLO 객체탐지 네트워크 기초
- "욜로"라고 칭한다. - 한 개의 네트워크(계층, 모델 같은 의미로 칭함)에서 객체(물체, 사물)를 탐지 - 탐지된 개체의 영역(바운딩 박스-사각형)과 객체의 이름(사람, 고양이, ...)을 표시해 주는
coding-heading.tistory.com
이전 글과 이어집니다.
<사용되는 파일>
- yolov3.weights : 이미 훈련된 모델의 가중치 데이터 파일
- yolov3.cfg : yolo모델 매개변수 설정 파일
- coconames : 인식(감지)된 객체의 레이블 명칭(이름)이 저장된 파일
* DNN(심층신경망) 모델을 사용하여 모델 세팅하기
net = cv2.dnn.readNet("./yolo/config/yolov3.weights",
"./yolo/config/yolov3.cfg")
net
결과 : < cv2.dnn.Net 000001A2F38BA030>
- readNet() : 가중치 데이터 및 환경설정 파일 읽어 들이기 {네트워크 = 계층}
- 첫 번째 인자 : 가중치 파일
- 두 번째 인자 : 모델 설정 파일
* 레이블 명칭(이름) 데이터 읽어 들이기
- 인식한 객체에 대한 이름을 표시하기 위해
### 저장할 변수 정의
classes = []
### open() : 파일 열기
### "r" : 읽기모드 / "b" : 쓰기모드 / "b" : 바이너리
with open("./yolo/config/coco.names", "r") as f:
### strip() : 왼쪽 오른쪽 공백 제거
### readlines() : 파일 내에 문장들을 행단위로 모두 읽어들이기
classes = [line.strip() for line in f.readlines()]
classes
결과 :
['person',
'bicycle',
'car',
'motorbike',
'aeroplane',
.
.
.
* YOLO가 사용하는 계층 구조 확인하기
- 우리가 사용했던 summery() 함수의 기능과 유사
layer_names = net.getLayerNames()
layer_names
결과 :
('conv_0',
'bn_0',
'leaky_1',
'conv_1',
'bn_1',
.
.
.
* YOLO에서 사용하는 출력계층 확인하기
- YOLO는 객체 검증을 위해 여러 개의 출력 계층을 사용하고 있음
- 객체탐지시에 출력계층에서 출력해 준 값들을 이용해서 사용
=> 바운딩 박스의 좌표값, 객체 인자 정확도, 인지된 객체의 레이블 명칭(이름) 등의 출력을 담당함
output_layer = [layer_names[i-1]for i in net.getUnconnectedOutLayers()]
print(net.getUnconnectedOutLayers())
output_layer
결과 :
[200 227 254]
['yolo_82', 'yolo_94', 'yolo_106']
net.getUnconnectedOutLayers()
결과 : array([200, 227, 254])
* 샘플 이미지 데이터 가져오기
img = cv2.imread("./yolo/cardataset/training_images/vid_4_10000.jpg")
img
결과 :
array([[[254, 217, 161],
[254, 217, 161],
[253, 216, 158],
...,
[252, 199, 142],
[252, 199, 142],
[251, 198, 141]],
.
.
.
* BGR을 RGB로 변환하기
img=cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img
결과 :
array([[[161, 217, 254],
[161, 217, 254],
[158, 216, 253],
...,
[142, 199, 252],
[142, 199, 252],
[141, 198, 251]],
.
.
.
* 바운딩박스의 시작 좌표와 종료좌표값을 계산할 때 사용할 높이와 너비 추출
height, width, channels = img.shape
height, width, channels
결과 : (380, 676, 3)
- yolo 출력계층에서 예측한 좌표값은 객체의 중심점 좌표에 대한 비율값을 추출함
- 비율에 실제 높이와 너비를 이용해서 예측된 중심점 좌표와 계산하여 바운딩박스의 시작좌표와 종료좌표를 정의해야 함.
* yolo모델이 이미지 데이터를 처리하기 위한 Blob형태의 데이터로 구조화하기
<Blob(Binary Large Object)>
- Blob은 이미지 처리 및 딥러닝에서 사용되는 데이터 구조임
- 이미지나 동영상에서 추출된 특정 부분이나 물체를 나타내기 위한 데이터 구조형태로 되어 있음
- 주로 딥러닝 모델에 이미지를 전달하거나 이미지 프로세싱 작업에서 특정 부분을 추출하여 처리하는 데 사용되는
구조임(객체 탐지용 데이터 구조라고 이해하면 된다.)
- YOLO 모델에서 사용되는 데이터 구조가 Blob 구조를 따름
=> 사용할 이미지를 Blob 데이터 구조로 변환한 후에
=> YOLO 네트워크(모델)에 전달하여 객체를 검출하게 됨
- Blob 데이터 구조에 포함될(된) 수 있는 값들
=> 이미지 데이터 : 이미지 또는 영상 프레임(이미지)에서 추출된 특정 영역에 대한 이미지 데이터
=> 채널 정보 : 컬러 이미지인 경우 RGB 또는 BRG과 같은 컬러 정보
=> 공간 차원 정보 : 높이와 너비
=> 픽셀 값 범위 : 0~255까지의 값을 가지는 흑백 이미지 데이터 또는 -1~1 또는 0~1 사이의 정규화된 이미지 값
- YOLO모델(네트워크)에서는 이미지 데이터를 바로 사용할 수 없음
=> 먼저 이미지를 Blob 데이터 형태로 변환해야 함
=> Blob 데이터를 통해 YO:O가 예측하면서 이미지에 특징을 찾아내고, 크기를 저장하는 작업을 수행한다.
=> 이미지 크기 저장을 -> 이미지 크기 정규화 라고 한다.
==> 이미지 크기 정규화 : 사용되는 높이와 너비의 이미지 사이즈를 통일시키는 작업
- YOLO에서 사용되는 이미지 크기
=> 320 X 320 : 이미지가 작고, 정확도는 떨어지지만 속도가 빠름
=> 609 X 609 : 이미지가 크고, 정확도는 높지만 속도가 느림
=> 416 X 416 : 이미지 중간크기, 정확도와 속도가 적당함 (주로 사용되는 크기임)
* 원본 이미지 데이터를 Blob으로 변환하면서, 동시에 정규화(사이즈 통일) 하기
blob = cv2.dnn.blobFromImage(
img,
1/256,
(416, 416),
(0, 0, 0),
swapRB=True,
crop=False
)
blob.shape
결과 : (1, 3, 416, 416)
- 사용 함수 : cv2.dnn.blobFromImage()
- 4차원으로 반환됨
- img : 원본 이미지 데이터
- 1/256 : 픽셀값에서 256으로 나누어서 데이터 정규화 진행
: 0~1 사이의 값으로 정규화
- (416, 416) : 높이와 너비의 사이즈를 통일시키는 정규화 진행
- (0, 0, 0) : 원본 이미지의 채널 값을 흑백으로 변환하기
- swapRB=True : GRB에서 R값과 B값을 바꿀 것인지 결정(기본값 False)
: True인 경우 BRG를 RGB로 변경
- crop : 크기를 조정한 후에 이미지를 자를지 여부 결정
: 일반적으로 자르면 안 되기에 False지정 (기본값 False)
: 크기가 변경된 사이즈로 이미지를 변환해서 사용할지 아니면, 변경 사이즈 부분을 제외하고 자를지 결정
* YOLO 모델에 데이터 넣어주기(입력계층에 들어가게 됨)
"""YOLO 모델에 입력 데이터로 넣어주기"""
net.setInput(blob)
* YOLO 모델의 출력 계층을 이용해서 결과받아오기
"""YOLO모델의 출력계층"""
output_layer
결과 : ['yolo_82', 'yolo_94', 'yolo_106']
* 입력데이터를 이용해서 예측된 출력결과받아오기
outs = net.forward(output_layer)
len(outs)
결과 : 3
- net.forward() : YOLO 모델이 이미지 내에 있는 객체를 인식하여 정보를 출력해 준다.
: 이때, 출력계층의 이름을 넣어서 해당 출력계층의 값이 반환되게 된다.
- array 배열의 3개 데이터를 튜플형태로 반환함
-> 각 튜플은 출력계층 3개가 출력해 준 값들임
* 인식된 객체(물체) 좌표, 레이블명칭(이름)과 정확도 확인하기
### 인식된 객체(물체)의 인덱스 번호를 담을 변수
class_ids = []
### 인식된 객체의 인식률(정확도)를 담을 변수
confidences = []
### 인식된 객체의 좌표값을 담을 변수
boxes = []
### 출력계층이 반환한 값들을 처리하기 위하여 반복문 사용
for out in outs:
# print(out)
# 인식된 객체에 대한 정보가 담겨있음
for detection in out:
"""
- 0번 인덱스 값 : 인식된 객체(바운딩박스)의 x 중심좌표 비율값
- 1번 인덱스 값 : 인식된 객체(바운딩박스)의 y 중심좌표 비율값
- 2번 인덱스 값 : 바운딩 박스의 너비 비율값
- 3번 인덱스 값 : 바운딩 박스의 높이 비율값
- 4번 인덱스 값 : 물체 인식률
- 5번 인덱스부터 전체 : 바운딩 박스에 대한 클래스(레이블명칭(이름)) 확률 값들
- => 5번 이후의 갯수는 레이블의 갯수(클래스 수) 만큼
=> 레이블 이름은 실제 레이블과 값들과 비교하여 가장 높은 값을 가지는
인덱스의 값을 이용하여 실제 레이블 이름 추출함
"""
# print(detection)
# 인식된 객체에 대한 정보 추출하기(클래스=레이어 명칭) 확률정보
scores = detection[5:]
# print(len(scores), scores)
"""
scores값이 가장 큰 인덱스 번호 찾기
- 0은 인식 못했다는 의미
- 가장 큰 인덱스 값 : 레이블 명칭(이름)이 있는 리스트 배열의 인덱스 값을 의미함
"""
class_id = np.argmax(scores)
# print(class_id)
### scores 값이 가장 큰 위치의 인덱스 번호에 해당하는 값은 인식률(정확도)를 의미
confidence = scores[class_id]
# print(confidence)
### 정확도 50% 이상인 데이터에 대해서 처리하기
if confidence > 0.5:
# print(f"scores : {scores}")
# print(f"class_id : {class_id}")
# print(f"confidence : {confidence}")
"""
바운딩박스의 상대적 x, y 좌표 추출하여
- 실제 길이 좌표(절대좌표)로 반환하기
"""
# 실제 중심점 x 좌표
center_x = int(detection[0] * width)
# 실제 중심점 y 좌표
center_y = int(detection[1] * height)
print(center_x, center_y)
### 바운딩 박스의 상대적 너비와 높이 비율 추출하기
# 실제 너비로 반환
w = int(detection[2] * width)
# 실제 높이로 반환
h = int(detection[3] * height)
print(w, h)
### 시작점 좌표 계산하기
x = int(center_x -w / 2)
y = int(center_y - h / 2)
print(x, y)
"""
이미지 죄표계
- 최상단이 0, 0 이다.
- 그래프의 좌표계는 최하단이 0, 0
"""
### 실제 x, y, 너비, 높이 담기
boxes.append([x, y, w, h])
### 객체 인식률(정확도) 실수형 타입으로 담기
confidences.append(float(confidence))
### 레이블 명칭(이름) 인덱스 담기
class_ids.append(class_id)
print(boxes)
print(confidences)
print(class_ids)
결과 :
68 213
92 32
22 197
[[22, 197, 92, 32]]
[0.9849126935005188]
[2]
* * 중복된 바운딩박스 제거하기
- 인식된 객체별로 => 1개의 바운딩박스만 남기기
indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)
indexes
결과 : array([0])
- cv2.dnn.NMSBoxes() : 중복 바운딩박스 제거하는 함수
=> boxes : 추출된 바운딩 박스 데이터
=> confidences : 바운딩박스별 정확도
=> 0.5 : 정확도에 대한 임계값, 바운딩박스 정확도가 0.5보다 작으면 박스 제거
=> 0.4 : 비최대 억제 임계값이라고 칭한다. / 이 값보다 크면 박스를 제거시킨다.
- NMSBoxes() 함수가 반환하는 값은 제거된 후 남은 바운딩 인덱스의 번호값 리스트
* 원본 이미지에 예측한 위치에 바운딩박스와 레이블(이름), 정확도 출력하기
### <폰트 스타일 지정>
font = cv2.FONT_HERSHEY_PLAIN
"""
<바운딩박스 색상 지정하기>
- 인식된 객체가 많은경우, 각각 생상을 지정해서 구분해 줄 필요성이 있기 때문에
=> 랜덤하게 추출하여 정의
- np.random.uniform() : 랜덤한 값 추출 함수
- 색상을RGB의 형태로 추출하기 위해 값의 범위는 0~255를 사용
- 0, 255 : RGB 각 값의 랜덤 범위
- size=(len(boxes), 3) : 추출할 사이즈 : 행, 열 정의
=> 인식된 각 바운딩 박스의 갯수만큼, 3개씩의 RGB값 추출을 의미함
"""
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],2))
print(confidence)
### *무조건 문자타입으로 바꾸기*
"""바운딩박스의 색상 추출하기"""
color = colors[i]
print(color)
"""
바운드박스 그리기
- 마지막 값 "2" : 바운딩박스 선의 굵기
"""
cv2.rectangle(img, (x, y), ((x + w), (y + h)), color, 2)
"""
인식된 객체의 레이블 명칭(이름)과 정확도 넣기(그리기)
- putText() : 원본 이미지에 텍스트 넣는 함수
- img : 원본 이미지
- label : 인식된 레이블 명칭(이름)
- confidence : 인식률(정확도)
- (x, y+20) : 텍스트 시작 좌표
- font : 폰트 스타일
- font 다음의 숫자 "2" : 폰트 사이즈
- (0, 255, 0) : 폰트 색상
- 마지막 숫자 "2" : 폰트 굵기
"""
cv2.putText(img, label + " " + confidence,
(x, y+20), font, 2, (0, 255, 0), 2)
plt.imshow(img)
### 인식된 객체가 없는 경우
else:
print("인식된 객체가 없습니다.")
결과 :
[0]
22 197 92 32
car
0.98
[182.1187388 211.92274426 61.69087878]
'머신러닝 | 딥러닝' 카테고리의 다른 글
Deep learning[딥러닝] YOLO 객체탐지 네트워크 Camera 사 (1) | 2024.01.11 |
---|---|
Deep learning[딥러닝] YOLO 객체탐지 네트워크 기초 (0) | 2024.01.10 |
Deep learning[딥러닝] 합성곱신경망(CNN; Convolutional Neural Network) (0) | 2024.01.09 |
Deep learning[딥러닝] RNN 응용 규칙기반 챗봇 (1) | 2024.01.09 |
Deep learning[딥러닝] LSTM GRU (0) | 2024.01.08 |