'Projects > 21년 통계청 통계데이터 분석활용대회' 카테고리의 다른 글
3. 분석 보고서 - 1) 제출용 보고서 (0) | 2021.10.13 |
---|---|
1. 프로젝트 기획단계 - 1) 여건 조성 (0) | 2021.10.13 |
1. 프로젝트 기획단계 - 2) 결정적 시행 (0) | 2021.10.13 |
2. 분석 기획 단계 - 3) 결론 (0) | 2021.10.13 |
2. 분석기획단계 - 2) 본론 (0) | 2021.10.13 |
3. 분석 보고서 - 1) 제출용 보고서 (0) | 2021.10.13 |
---|---|
1. 프로젝트 기획단계 - 1) 여건 조성 (0) | 2021.10.13 |
1. 프로젝트 기획단계 - 2) 결정적 시행 (0) | 2021.10.13 |
2. 분석 기획 단계 - 3) 결론 (0) | 2021.10.13 |
2. 분석기획단계 - 2) 본론 (0) | 2021.10.13 |
classes 만 바뀜
%cd /content
!mkdir /content/data
!wget -O /content/data/the_rock_chase.mp4 https://github.com/chulminkw/DLCV/blob/master/data/video/the_rock_chase.mp4?raw=true
CLASSES = ('Car', 'Truck', 'Pedestrian', 'Cyclist')
labels_to_names_seq = {i:k for i, k in enumerate(CLASSES)}
labels_to_names_seq
# {0: 'Car', 1: 'Truck', 2: 'Pedestrian', 3: 'Cyclist'}
CLASSES = ('Car', 'Truck', 'Pedestrian', 'Cyclist')
cat2label = {k:i for i, k in enumerate(CLASSES)}
def get_detected_img(model, img_array, score_threshold=0.3, is_print=True):
# 인자로 들어온 image_array를 복사.
draw_img = img_array.copy()
bbox_color=(0, 255, 0)
text_color=(0, 0, 255)
# model과 image array를 입력 인자로 inference detection 수행하고 결과를 results로 받음.
# results는 80개의 2차원 array(shape=(오브젝트갯수, 5))를 가지는 list.
results = inference_detector(model, img_array)
# 80개의 array원소를 가지는 results 리스트를 loop를 돌면서 개별 2차원 array들을 추출하고 이를 기반으로 이미지 시각화
# results 리스트의 위치 index가 바로 COCO 매핑된 Class id. 여기서는 result_ind가 class id
# 개별 2차원 array에 오브젝트별 좌표와 class confidence score 값을 가짐.
for result_ind, result in enumerate(results):
# 개별 2차원 array의 row size가 0 이면 해당 Class id로 값이 없으므로 다음 loop로 진행.
if len(result) == 0:
continue
# 2차원 array에서 5번째 컬럼에 해당하는 값이 score threshold이며 이 값이 함수 인자로 들어온 score_threshold 보다 낮은 경우는 제외.
result_filtered = result[np.where(result[:, 4] > score_threshold)]
# 해당 클래스 별로 Detect된 여러개의 오브젝트 정보가 2차원 array에 담겨 있으며, 이 2차원 array를 row수만큼 iteration해서 개별 오브젝트의 좌표값 추출.
for i in range(len(result_filtered)):
# 좌상단, 우하단 좌표 추출.
left = int(result_filtered[i, 0])
top = int(result_filtered[i, 1])
right = int(result_filtered[i, 2])
bottom = int(result_filtered[i, 3])
caption = "{}: {:.4f}".format(labels_to_names_seq[result_ind], result_filtered[i, 4])
cv2.rectangle(draw_img, (left, top), (right, bottom), color=bbox_color, thickness=2)
cv2.putText(draw_img, caption, (int(left), int(top - 7)), cv2.FONT_HERSHEY_SIMPLEX, 0.37, text_color, 1)
if is_print:
print(caption)
return draw_img
import time
def do_detected_video(model, input_path, output_path, score_threshold, do_print=True):
cap = cv2.VideoCapture(input_path)
codec = cv2.VideoWriter_fourcc(*'XVID')
vid_size = (round(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),round(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
vid_fps = cap.get(cv2.CAP_PROP_FPS)
vid_writer = cv2.VideoWriter(output_path, codec, vid_fps, vid_size)
frame_cnt = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
print('총 Frame 갯수:', frame_cnt)
btime = time.time()
while True:
hasFrame, img_frame = cap.read()
if not hasFrame:
print('더 이상 처리할 frame이 없습니다.')
break
stime = time.time()
img_frame = get_detected_img(model, img_frame, score_threshold=score_threshold, is_print=False)
if do_print:
print('frame별 detection 수행 시간:', round(time.time() - stime, 4))
vid_writer.write(img_frame)
# end of while loop
vid_writer.release()
cap.release()
print('최종 detection 완료 수행 시간:', round(time.time() - btime, 4))
do_detected_video(model, '/content/data/the_rock_chase.mp4', '/content/data/the_rock_chase_out1.mp4', score_threshold=0.4, do_print=True)
# 총 Frame 갯수: 503
frame별 detection 수행 시간: 0.1158
frame별 detection 수행 시간: 0.0974
frame별 detection 수행 시간: 0.0929
frame별 detection 수행 시간: 0.102
frame별 detection 수행 시간: 0.1017
frame별 detection 수행 시간: 0.1063
frame별 detection 수행 시간: 0.0948
frame별 detection 수행 시간: 0.1055
frame별 detection 수행 시간: 0.0973
frame별 detection 수행 시간: 0.1025
frame별 detection 수행 시간: 0.096
frame별 detection 수행 시간: 0.0997
frame별 detection 수행 시간: 0.0982
frame별 detection 수행 시간: 0.1127
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.0982
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0966
frame별 detection 수행 시간: 0.0955
frame별 detection 수행 시간: 0.0945
frame별 detection 수행 시간: 0.0959
frame별 detection 수행 시간: 0.1024
frame별 detection 수행 시간: 0.0985
frame별 detection 수행 시간: 0.095
frame별 detection 수행 시간: 0.1022
frame별 detection 수행 시간: 0.0937
frame별 detection 수행 시간: 0.096
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0958
frame별 detection 수행 시간: 0.1023
frame별 detection 수행 시간: 0.0971
frame별 detection 수행 시간: 0.0946
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0938
frame별 detection 수행 시간: 0.0946
frame별 detection 수행 시간: 0.0938
frame별 detection 수행 시간: 0.0965
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0954
frame별 detection 수행 시간: 0.0955
frame별 detection 수행 시간: 0.0991
frame별 detection 수행 시간: 0.0997
frame별 detection 수행 시간: 0.0964
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0965
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.0968
frame별 detection 수행 시간: 0.0928
frame별 detection 수행 시간: 0.0995
frame별 detection 수행 시간: 0.0998
frame별 detection 수행 시간: 0.0933
frame별 detection 수행 시간: 0.0931
frame별 detection 수행 시간: 0.095
frame별 detection 수행 시간: 0.103
frame별 detection 수행 시간: 0.1082
frame별 detection 수행 시간: 0.091
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.0926
frame별 detection 수행 시간: 0.0929
frame별 detection 수행 시간: 0.092
frame별 detection 수행 시간: 0.094
frame별 detection 수행 시간: 0.0917
frame별 detection 수행 시간: 0.0964
frame별 detection 수행 시간: 0.092
frame별 detection 수행 시간: 0.0937
frame별 detection 수행 시간: 0.0936
frame별 detection 수행 시간: 0.1009
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0985
frame별 detection 수행 시간: 0.0968
frame별 detection 수행 시간: 0.092
frame별 detection 수행 시간: 0.0959
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0946
frame별 detection 수행 시간: 0.0926
frame별 detection 수행 시간: 0.0954
frame별 detection 수행 시간: 0.0925
frame별 detection 수행 시간: 0.0987
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0927
frame별 detection 수행 시간: 0.0974
frame별 detection 수행 시간: 0.0932
frame별 detection 수행 시간: 0.1043
frame별 detection 수행 시간: 0.0947
frame별 detection 수행 시간: 0.1006
frame별 detection 수행 시간: 0.0955
frame별 detection 수행 시간: 0.1049
frame별 detection 수행 시간: 0.0924
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0959
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.094
frame별 detection 수행 시간: 0.0949
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.0952
frame별 detection 수행 시간: 0.0974
frame별 detection 수행 시간: 0.1047
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0977
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0965
frame별 detection 수행 시간: 0.0927
frame별 detection 수행 시간: 0.0957
frame별 detection 수행 시간: 0.0938
frame별 detection 수행 시간: 0.0997
frame별 detection 수행 시간: 0.0979
frame별 detection 수행 시간: 0.0972
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0992
frame별 detection 수행 시간: 0.1034
frame별 detection 수행 시간: 0.1029
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.0946
frame별 detection 수행 시간: 0.0934
frame별 detection 수행 시간: 0.0966
frame별 detection 수행 시간: 0.0917
frame별 detection 수행 시간: 0.1
frame별 detection 수행 시간: 0.0979
frame별 detection 수행 시간: 0.0953
frame별 detection 수행 시간: 0.0932
frame별 detection 수행 시간: 0.0946
frame별 detection 수행 시간: 0.0906
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.094
frame별 detection 수행 시간: 0.0969
frame별 detection 수행 시간: 0.0925
frame별 detection 수행 시간: 0.0967
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0934
frame별 detection 수행 시간: 0.0924
frame별 detection 수행 시간: 0.0924
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0965
frame별 detection 수행 시간: 0.1
frame별 detection 수행 시간: 0.092
frame별 detection 수행 시간: 0.0928
frame별 detection 수행 시간: 0.0921
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.092
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0954
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0937
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0961
frame별 detection 수행 시간: 0.0928
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0905
frame별 detection 수행 시간: 0.0912
frame별 detection 수행 시간: 0.0927
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0958
frame별 detection 수행 시간: 0.0936
frame별 detection 수행 시간: 0.0922
frame별 detection 수행 시간: 0.0926
frame별 detection 수행 시간: 0.0928
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0954
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.0924
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0972
frame별 detection 수행 시간: 0.0925
frame별 detection 수행 시간: 0.0948
frame별 detection 수행 시간: 0.0924
frame별 detection 수행 시간: 0.0932
frame별 detection 수행 시간: 0.0925
frame별 detection 수행 시간: 0.09
frame별 detection 수행 시간: 0.097
frame별 detection 수행 시간: 0.0927
frame별 detection 수행 시간: 0.0955
frame별 detection 수행 시간: 0.0926
frame별 detection 수행 시간: 0.0947
frame별 detection 수행 시간: 0.0917
frame별 detection 수행 시간: 0.1029
frame별 detection 수행 시간: 0.0912
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0921
frame별 detection 수행 시간: 0.0967
frame별 detection 수행 시간: 0.0906
frame별 detection 수행 시간: 0.0945
frame별 detection 수행 시간: 0.0954
frame별 detection 수행 시간: 0.0952
frame별 detection 수행 시간: 0.0904
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0905
frame별 detection 수행 시간: 0.092
frame별 detection 수행 시간: 0.0902
frame별 detection 수행 시간: 0.0927
frame별 detection 수행 시간: 0.0963
frame별 detection 수행 시간: 0.0989
frame별 detection 수행 시간: 0.0917
frame별 detection 수행 시간: 0.0952
frame별 detection 수행 시간: 0.0965
frame별 detection 수행 시간: 0.0905
frame별 detection 수행 시간: 0.0933
frame별 detection 수행 시간: 0.0906
frame별 detection 수행 시간: 0.0981
frame별 detection 수행 시간: 0.0928
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0904
frame별 detection 수행 시간: 0.094
frame별 detection 수행 시간: 0.0909
frame별 detection 수행 시간: 0.0961
frame별 detection 수행 시간: 0.0936
frame별 detection 수행 시간: 0.0978
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.0961
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0955
frame별 detection 수행 시간: 0.0954
frame별 detection 수행 시간: 0.0906
frame별 detection 수행 시간: 0.0933
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.0898
frame별 detection 수행 시간: 0.0893
frame별 detection 수행 시간: 0.0923
frame별 detection 수행 시간: 0.0999
frame별 detection 수행 시간: 0.0909
frame별 detection 수행 시간: 0.1059
frame별 detection 수행 시간: 0.0957
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0931
frame별 detection 수행 시간: 0.1005
frame별 detection 수행 시간: 0.0927
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0967
frame별 detection 수행 시간: 0.0912
frame별 detection 수행 시간: 0.097
frame별 detection 수행 시간: 0.0902
frame별 detection 수행 시간: 0.0934
frame별 detection 수행 시간: 0.0907
frame별 detection 수행 시간: 0.0956
frame별 detection 수행 시간: 0.0933
frame별 detection 수행 시간: 0.0953
frame별 detection 수행 시간: 0.0946
frame별 detection 수행 시간: 0.0965
frame별 detection 수행 시간: 0.0934
frame별 detection 수행 시간: 0.0965
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0994
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0974
frame별 detection 수행 시간: 0.097
frame별 detection 수행 시간: 0.0927
frame별 detection 수행 시간: 0.0999
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.0933
frame별 detection 수행 시간: 0.0974
frame별 detection 수행 시간: 0.0938
frame별 detection 수행 시간: 0.1012
frame별 detection 수행 시간: 0.0964
frame별 detection 수행 시간: 0.0978
frame별 detection 수행 시간: 0.0947
frame별 detection 수행 시간: 0.0949
frame별 detection 수행 시간: 0.0926
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0955
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0963
frame별 detection 수행 시간: 0.0936
frame별 detection 수행 시간: 0.096
frame별 detection 수행 시간: 0.1008
frame별 detection 수행 시간: 0.0964
frame별 detection 수행 시간: 0.0937
frame별 detection 수행 시간: 0.0947
frame별 detection 수행 시간: 0.094
frame별 detection 수행 시간: 0.095
frame별 detection 수행 시간: 0.0929
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.1009
frame별 detection 수행 시간: 0.0948
frame별 detection 수행 시간: 0.0917
frame별 detection 수행 시간: 0.0931
frame별 detection 수행 시간: 0.0954
frame별 detection 수행 시간: 0.0934
frame별 detection 수행 시간: 0.0932
frame별 detection 수행 시간: 0.0961
frame별 detection 수행 시간: 0.0972
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.1005
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0954
frame별 detection 수행 시간: 0.0967
frame별 detection 수행 시간: 0.0998
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.0947
frame별 detection 수행 시간: 0.0921
frame별 detection 수행 시간: 0.0945
frame별 detection 수행 시간: 0.0932
frame별 detection 수행 시간: 0.0934
frame별 detection 수행 시간: 0.0913
frame별 detection 수행 시간: 0.0918
frame별 detection 수행 시간: 0.0949
frame별 detection 수행 시간: 0.0956
frame별 detection 수행 시간: 0.0991
frame별 detection 수행 시간: 0.096
frame별 detection 수행 시간: 0.1012
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.095
frame별 detection 수행 시간: 0.0947
frame별 detection 수행 시간: 0.0949
frame별 detection 수행 시간: 0.0959
frame별 detection 수행 시간: 0.0977
frame별 detection 수행 시간: 0.0962
frame별 detection 수행 시간: 0.1024
frame별 detection 수행 시간: 0.0923
frame별 detection 수행 시간: 0.0971
frame별 detection 수행 시간: 0.0973
frame별 detection 수행 시간: 0.0992
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0991
frame별 detection 수행 시간: 0.0937
frame별 detection 수행 시간: 0.0988
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0993
frame별 detection 수행 시간: 0.0968
frame별 detection 수행 시간: 0.1021
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.0995
frame별 detection 수행 시간: 0.0964
frame별 detection 수행 시간: 0.1024
frame별 detection 수행 시간: 0.0987
frame별 detection 수행 시간: 0.1017
frame별 detection 수행 시간: 0.0925
frame별 detection 수행 시간: 0.0965
frame별 detection 수행 시간: 0.0926
frame별 detection 수행 시간: 0.1026
frame별 detection 수행 시간: 0.096
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.09
frame별 detection 수행 시간: 0.0969
frame별 detection 수행 시간: 0.0927
frame별 detection 수행 시간: 0.1002
frame별 detection 수행 시간: 0.0901
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0915
frame별 detection 수행 시간: 0.0916
frame별 detection 수행 시간: 0.0924
frame별 detection 수행 시간: 0.0936
frame별 detection 수행 시간: 0.0928
frame별 detection 수행 시간: 0.0996
frame별 detection 수행 시간: 0.0977
frame별 detection 수행 시간: 0.095
frame별 detection 수행 시간: 0.0898
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0925
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0925
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0926
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0987
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0945
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0923
frame별 detection 수행 시간: 0.0902
frame별 detection 수행 시간: 0.0915
frame별 detection 수행 시간: 0.0931
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0948
frame별 detection 수행 시간: 0.0928
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0945
frame별 detection 수행 시간: 0.091
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0974
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0985
frame별 detection 수행 시간: 0.0918
frame별 detection 수행 시간: 0.0916
frame별 detection 수행 시간: 0.0901
frame별 detection 수행 시간: 0.0938
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0909
frame별 detection 수행 시간: 0.0931
frame별 detection 수행 시간: 0.1007
frame별 detection 수행 시간: 0.0966
frame별 detection 수행 시간: 0.0917
frame별 detection 수행 시간: 0.0912
frame별 detection 수행 시간: 0.0926
frame별 detection 수행 시간: 0.092
frame별 detection 수행 시간: 0.0937
frame별 detection 수행 시간: 0.0898
frame별 detection 수행 시간: 0.0884
frame별 detection 수행 시간: 0.0916
frame별 detection 수행 시간: 0.0936
frame별 detection 수행 시간: 0.0885
frame별 detection 수행 시간: 0.0902
frame별 detection 수행 시간: 0.089
frame별 detection 수행 시간: 0.0985
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0959
frame별 detection 수행 시간: 0.0947
frame별 detection 수행 시간: 0.0982
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0959
frame별 detection 수행 시간: 0.0922
frame별 detection 수행 시간: 0.0925
frame별 detection 수행 시간: 0.0932
frame별 detection 수행 시간: 0.0955
frame별 detection 수행 시간: 0.0912
frame별 detection 수행 시간: 0.096
frame별 detection 수행 시간: 0.0933
frame별 detection 수행 시간: 0.1
frame별 detection 수행 시간: 0.0987
frame별 detection 수행 시간: 0.1007
frame별 detection 수행 시간: 0.097
frame별 detection 수행 시간: 0.098
frame별 detection 수행 시간: 0.0934
frame별 detection 수행 시간: 0.0985
frame별 detection 수행 시간: 0.0926
frame별 detection 수행 시간: 0.0973
frame별 detection 수행 시간: 0.0918
frame별 detection 수행 시간: 0.0914
frame별 detection 수행 시간: 0.0931
frame별 detection 수행 시간: 0.0991
frame별 detection 수행 시간: 0.0922
frame별 detection 수행 시간: 0.095
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0954
frame별 detection 수행 시간: 0.0908
frame별 detection 수행 시간: 0.0938
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0921
frame별 detection 수행 시간: 0.0967
frame별 detection 수행 시간: 0.0933
frame별 detection 수행 시간: 0.0896
frame별 detection 수행 시간: 0.0989
frame별 detection 수행 시간: 0.092
frame별 detection 수행 시간: 0.097
frame별 detection 수행 시간: 0.0936
frame별 detection 수행 시간: 0.0992
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0937
frame별 detection 수행 시간: 0.0952
frame별 detection 수행 시간: 0.0937
frame별 detection 수행 시간: 0.0906
frame별 detection 수행 시간: 0.1034
frame별 detection 수행 시간: 0.0936
frame별 detection 수행 시간: 0.0929
frame별 detection 수행 시간: 0.09
frame별 detection 수행 시간: 0.0968
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0921
frame별 detection 수행 시간: 0.0952
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.095
frame별 detection 수행 시간: 0.0945
frame별 detection 수행 시간: 0.0929
frame별 detection 수행 시간: 0.0965
frame별 detection 수행 시간: 0.0962
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0958
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0979
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0983
frame별 detection 수행 시간: 0.0967
frame별 detection 수행 시간: 0.0925
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0933
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0961
frame별 detection 수행 시간: 0.1017
frame별 detection 수행 시간: 0.096
frame별 detection 수행 시간: 0.0971
frame별 detection 수행 시간: 0.0948
frame별 detection 수행 시간: 0.095
frame별 detection 수행 시간: 0.0933
frame별 detection 수행 시간: 0.0952
frame별 detection 수행 시간: 0.0907
더 이상 처리할 frame이 없습니다.
최종 detection 완료 수행 시간: 53.1923
5-2. config의 이해 - data pipeline (0) | 2021.10.17 |
---|---|
5-1. config의 이해 - 대분류 및 주요 설정 (0) | 2021.10.17 |
4-11~14. tiny kitti data로 customdataset, config 설정, image inference (0) | 2021.10.11 |
4-8~10. tiny kitti 데이터로 mmdetection train (0) | 2021.10.11 |
4-7. tiny kitti - dataset (0) | 2021.10.11 |
# 원본 kitti Dataset는 10개의 Class로 되어 있음. 'Car Van Truck Pedestrian Person_sitting Cyclist Tram Misc DontCare'
CLASSES = ('Car', 'Truck', 'Pedestrian', 'Cyclist')
cat2label = {k:i for i, k in enumerate(CLASSES)}
print(cat2label)
cat2label['Car']
# {'Car': 0, 'Truck': 1, 'Pedestrian': 2, 'Cyclist': 3}
# 0
# data_anno {label}에 넣기 위한것
image_list = mmcv.list_from_file('/content/kitti_tiny/train.txt')
lines = mmcv.list_from_file('/content/kitti_tiny/training/label_2/000064.txt')
#print(lines)
content = [line.strip().split(' ') for line in lines]
bbox_names = [x[0] for x in content]
#print(bbox_names)
# bounding box 읽기
bboxes = [ [float(info) for info in x[4:8]] for x in content]
print(bboxes)
# [[657.65, 179.93, 709.86, 219.92], [731.51, 180.39, 882.28, 275.8], [715.18, 175.63, 762.77, 203.9], [816.58, 59.74, 1112.51, 266.07], [626.78, 174.27, 647.77, 192.18], [546.19, 168.97, 554.01, 177.09]]
import copy
import os.path as osp
import cv2
import mmcv
import numpy as np
from mmdet.datasets.builder import DATASETS
from mmdet.datasets.custom import CustomDataset
# 반드시 아래 Decorator 설정 할것.@DATASETS.register_module() 설정 시 force=True를 입력하지 않으면 Dataset 재등록 불가.
@DATASETS.register_module(force=True)
class KittyTinyDataset(CustomDataset):
CLASSES = ('Car', 'Truck', 'Pedestrian', 'Cyclist')
# __init__ 가 없는것은 customdataset것을 이용
##### self.data_root: /content/kitti_tiny/ self.ann_file: /content/kitti_tiny/train.txt self.img_prefix: /content/kitti_tiny/training/image_2
#### ann_file: /content/kitti_tiny/train.txt
# annotation에 대한 모든 파일명을 가지고 있는 텍스트 파일을 __init__(self, ann_file)로 입력 받고, 이 self.ann_file이 load_annotations()의 인자로 입력
def load_annotations(self, ann_file):
print('##### self.data_root:', self.data_root, 'self.ann_file:', self.ann_file, 'self.img_prefix:', self.img_prefix)
print('#### ann_file:', ann_file)
cat2label = {k:i for i, k in enumerate(self.CLASSES)}
image_list = mmcv.list_from_file(self.ann_file)
# 포맷 중립 데이터를 담을 list 객체
data_infos = []
for image_id in image_list: # 000000
filename = '{0:}/{1:}.jpeg'.format(self.img_prefix, image_id)
# 원본 이미지의 너비, 높이를 image를 직접 로드하여 구함.
image = cv2.imread(filename)
height, width = image.shape[:2]
# 개별 image의 annotation 정보 저장용 Dict 생성. key값 filename 에는 image의 파일명만 들어감(디렉토리는 제외)
data_info = {'filename': str(image_id) + '.jpeg',
'width': width, 'height': height}
# 개별 annotation이 있는 서브 디렉토리의 prefix 변환.
label_prefix = self.img_prefix.replace('image_2', 'label_2')
# 개별 annotation 파일을 1개 line 씩 읽어서 list 로드
lines = mmcv.list_from_file(osp.join(label_prefix, str(image_id)+'.txt'))
# 전체 lines를 개별 line별 공백 레벨로 parsing 하여 다시 list로 저장. content는 list의 list형태임.
# ann 정보는 numpy array로 저장되나 텍스트 처리나 데이터 가공이 list 가 편하므로 일차적으로 list로 변환 수행.
content = [line.strip().split(' ') for line in lines]
# 오브젝트의 클래스명은 bbox_names로 저장.
bbox_names = [x[0] for x in content]
# bbox 좌표를 저장
bboxes = [ [float(info) for info in x[4:8]] for x in content]
# 클래스명이 해당 사항이 없는 대상 Filtering out, 'DontCare'sms ignore로 별도 저장.
gt_bboxes = []
gt_labels = []
gt_bboxes_ignore = []
gt_labels_ignore = []
# 파일 내용을 읽는 loop
for bbox_name, bbox in zip(bbox_names, bboxes):
# 만약 bbox_name이 클래스명에 해당 되면, gt_bboxes와 gt_labels에 추가, 그렇지 않으면 gt_bboxes_ignore, gt_labels_ignore에 추가
if bbox_name in cat2label:
gt_bboxes.append(bbox)
# gt_labels에는 class id를 입력
gt_labels.append(cat2label[bbox_name])
else:
gt_bboxes_ignore.append(bbox)
gt_labels_ignore.append(-1)
# 개별 image별 annotation 정보를 가지는 Dict 생성. 해당 Dict의 value값은 모두 np.array임.
data_anno = {
'bboxes': np.array(gt_bboxes, dtype=np.float32).reshape(-1, 4),
'labels': np.array(gt_labels, dtype=np.long),
'bboxes_ignore': np.array(gt_bboxes_ignore, dtype=np.float32).reshape(-1, 4),
'labels_ignore': np.array(gt_labels_ignore, dtype=np.long)
}
# image에 대한 메타 정보를 가지는 data_info Dict에 'ann' key값으로 data_anno를 value로 저장.
data_info.update(ann=data_anno)
# 전체 annotation 파일들에 대한 정보를 가지는 data_infos에 data_info Dict를 추가
data_infos.append(data_info)
return data_infos
### Config 설정하고 Pretrained 모델 다운로드
config_file = '/content/mmdetection/configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py'
checkpoint_file = '/content/mmdetection/checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth'
!cd mmdetection; mkdir checkpoints
!wget -O /content/mmdetection/checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth http://download.openmmlab.com/mmdetection/v2.0/faster_rcnn/faster_rcnn_r50_fpn_1x_coco/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth
from mmcv import Config
cfg = Config.fromfile(config_file)
print(cfg.pretty_text)
# model = dict(
type='FasterRCNN',
pretrained='torchvision://resnet50',
backbone=dict(
type='ResNet',
depth=50,
num_stages=4,
out_indices=(0, 1, 2, 3),
frozen_stages=1,
norm_cfg=dict(type='BN', requires_grad=True),
norm_eval=True,
style='pytorch'),
neck=dict(
type='FPN',
in_channels=[256, 512, 1024, 2048],
out_channels=256,
num_outs=5),
rpn_head=dict(
type='RPNHead',
in_channels=256,
feat_channels=256,
anchor_generator=dict(
type='AnchorGenerator',
scales=[8],
ratios=[0.5, 1.0, 2.0],
strides=[4, 8, 16, 32, 64]),
bbox_coder=dict(
type='DeltaXYWHBBoxCoder',
target_means=[0.0, 0.0, 0.0, 0.0],
target_stds=[1.0, 1.0, 1.0, 1.0]),
loss_cls=dict(
type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),
loss_bbox=dict(type='L1Loss', loss_weight=1.0)),
roi_head=dict(
type='StandardRoIHead',
bbox_roi_extractor=dict(
type='SingleRoIExtractor',
roi_layer=dict(type='RoIAlign', output_size=7, sampling_ratio=0),
out_channels=256,
featmap_strides=[4, 8, 16, 32]),
bbox_head=dict(
type='Shared2FCBBoxHead',
in_channels=256,
fc_out_channels=1024,
roi_feat_size=7,
num_classes=80,
bbox_coder=dict(
type='DeltaXYWHBBoxCoder',
target_means=[0.0, 0.0, 0.0, 0.0],
target_stds=[0.1, 0.1, 0.2, 0.2]),
reg_class_agnostic=False,
loss_cls=dict(
type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),
loss_bbox=dict(type='L1Loss', loss_weight=1.0))),
train_cfg=dict(
rpn=dict(
assigner=dict(
type='MaxIoUAssigner',
pos_iou_thr=0.7,
neg_iou_thr=0.3,
min_pos_iou=0.3,
match_low_quality=True,
ignore_iof_thr=-1),
sampler=dict(
type='RandomSampler',
num=256,
pos_fraction=0.5,
neg_pos_ub=-1,
add_gt_as_proposals=False),
allowed_border=-1,
pos_weight=-1,
debug=False),
rpn_proposal=dict(
nms_pre=2000,
max_per_img=1000,
nms=dict(type='nms', iou_threshold=0.7),
min_bbox_size=0),
rcnn=dict(
assigner=dict(
type='MaxIoUAssigner',
pos_iou_thr=0.5,
neg_iou_thr=0.5,
min_pos_iou=0.5,
match_low_quality=False,
ignore_iof_thr=-1),
sampler=dict(
type='RandomSampler',
num=512,
pos_fraction=0.25,
neg_pos_ub=-1,
add_gt_as_proposals=True),
pos_weight=-1,
debug=False)),
test_cfg=dict(
rpn=dict(
nms_pre=1000,
max_per_img=1000,
nms=dict(type='nms', iou_threshold=0.7),
min_bbox_size=0),
rcnn=dict(
score_thr=0.05,
nms=dict(type='nms', iou_threshold=0.5),
max_per_img=100)))
dataset_type = 'CocoDataset'
data_root = 'data/coco/'
img_norm_cfg = dict(
mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
train_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='LoadAnnotations', with_bbox=True),
dict(type='Resize', img_scale=(1333, 800), keep_ratio=True),
dict(type='RandomFlip', flip_ratio=0.5),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='Pad', size_divisor=32),
dict(type='DefaultFormatBundle'),
dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])
]
test_pipeline = [
dict(type='LoadImageFromFile'),
dict(
type='MultiScaleFlipAug',
img_scale=(1333, 800),
flip=False,
transforms=[
dict(type='Resize', keep_ratio=True),
dict(type='RandomFlip'),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='Pad', size_divisor=32),
dict(type='ImageToTensor', keys=['img']),
dict(type='Collect', keys=['img'])
])
]
data = dict(
samples_per_gpu=2,
workers_per_gpu=2,
train=dict(
type='CocoDataset',
ann_file='data/coco/annotations/instances_train2017.json',
img_prefix='data/coco/train2017/',
pipeline=[
dict(type='LoadImageFromFile'),
dict(type='LoadAnnotations', with_bbox=True),
dict(type='Resize', img_scale=(1333, 800), keep_ratio=True),
dict(type='RandomFlip', flip_ratio=0.5),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='Pad', size_divisor=32),
dict(type='DefaultFormatBundle'),
dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])
]),
val=dict(
type='CocoDataset',
ann_file='data/coco/annotations/instances_val2017.json',
img_prefix='data/coco/val2017/',
pipeline=[
dict(type='LoadImageFromFile'),
dict(
type='MultiScaleFlipAug',
img_scale=(1333, 800),
flip=False,
transforms=[
dict(type='Resize', keep_ratio=True),
dict(type='RandomFlip'),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='Pad', size_divisor=32),
dict(type='ImageToTensor', keys=['img']),
dict(type='Collect', keys=['img'])
])
]),
test=dict(
type='CocoDataset',
ann_file='data/coco/annotations/instances_val2017.json',
img_prefix='data/coco/val2017/',
pipeline=[
dict(type='LoadImageFromFile'),
dict(
type='MultiScaleFlipAug',
img_scale=(1333, 800),
flip=False,
transforms=[
dict(type='Resize', keep_ratio=True),
dict(type='RandomFlip'),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='Pad', size_divisor=32),
dict(type='ImageToTensor', keys=['img']),
dict(type='Collect', keys=['img'])
])
]))
evaluation = dict(interval=1, metric='bbox')
optimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001)
optimizer_config = dict(grad_clip=None)
lr_config = dict(
policy='step',
warmup='linear',
warmup_iters=500,
warmup_ratio=0.001,
step=[8, 11])
runner = dict(type='EpochBasedRunner', max_epochs=12)
checkpoint_config = dict(interval=1)
log_config = dict(interval=50, hooks=[dict(type='TextLoggerHook')])
custom_hooks = [dict(type='NumClassCheckHook')]
dist_params = dict(backend='nccl')
log_level = 'INFO'
load_from = None
resume_from = None
workflow = [('train', 1)]
from mmdet.apis import set_random_seed
# dataset에 대한 환경 파라미터 수정.
cfg.dataset_type = 'KittyTinyDataset'
cfg.data_root = '/content/kitti_tiny/'
# train, val, test dataset에 대한 type, data_root, ann_file, img_prefix 환경 파라미터 수정.
cfg.data.train.type = 'KittyTinyDataset'
cfg.data.train.data_root = '/content/kitti_tiny/'
cfg.data.train.ann_file = 'train.txt'
cfg.data.train.img_prefix = 'training/image_2'
cfg.data.val.type = 'KittyTinyDataset'
cfg.data.val.data_root = '/content/kitti_tiny/'
cfg.data.val.ann_file = 'val.txt'
cfg.data.val.img_prefix = 'training/image_2'
cfg.data.test.type = 'KittyTinyDataset'
cfg.data.test.data_root = '/content/kitti_tiny/'
cfg.data.test.ann_file = 'val.txt'
cfg.data.test.img_prefix = 'training/image_2'
# class의 갯수 수정.
cfg.model.roi_head.bbox_head.num_classes = 4
# pretrained 모델
cfg.load_from = 'checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth'
# 학습 weight 파일로 로그를 저장하기 위한 디렉토리 설정.
cfg.work_dir = './tutorial_exps'
# 학습율 변경 환경 파라미터 설정.
cfg.optimizer.lr = 0.02 / 8
cfg.lr_config.warmup = None
cfg.log_config.interval = 10
# config 수행 시마다 policy값이 없어지는 bug로 인하여 설정.
cfg.lr_config.policy = 'step'
# Change the evaluation metric since we use customized dataset.
cfg.evaluation.metric = 'mAP'
# We can set the evaluation interval to reduce the evaluation times
cfg.evaluation.interval = 12
# We can set the checkpoint saving interval to reduce the storage cost
cfg.checkpoint_config.interval = 12
# Set seed thus the results are more reproducible
cfg.seed = 0
set_random_seed(0, deterministic=False)
cfg.gpu_ids = range(1)
# We can initialize the logger for training and have a look
# at the final config used for training
print(f'Config:\n{cfg.pretty_text}')
# Config:
model = dict(
type='FasterRCNN',
pretrained='torchvision://resnet50',
backbone=dict(
type='ResNet',
depth=50,
num_stages=4,
out_indices=(0, 1, 2, 3),
frozen_stages=1,
norm_cfg=dict(type='BN', requires_grad=True),
norm_eval=True,
style='pytorch',
pretrained='torchvision://resnet50'),
neck=dict(
type='FPN',
in_channels=[256, 512, 1024, 2048],
out_channels=256,
num_outs=5),
rpn_head=dict(
type='RPNHead',
in_channels=256,
feat_channels=256,
anchor_generator=dict(
type='AnchorGenerator',
scales=[8],
ratios=[0.5, 1.0, 2.0],
strides=[4, 8, 16, 32, 64]),
bbox_coder=dict(
type='DeltaXYWHBBoxCoder',
target_means=[0.0, 0.0, 0.0, 0.0],
target_stds=[1.0, 1.0, 1.0, 1.0]),
loss_cls=dict(
type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),
loss_bbox=dict(type='L1Loss', loss_weight=1.0)),
roi_head=dict(
type='StandardRoIHead',
bbox_roi_extractor=dict(
type='SingleRoIExtractor',
roi_layer=dict(type='RoIAlign', output_size=7, sampling_ratio=0),
out_channels=256,
featmap_strides=[4, 8, 16, 32]),
bbox_head=dict(
type='Shared2FCBBoxHead',
in_channels=256,
fc_out_channels=1024,
roi_feat_size=7,
num_classes=4,
bbox_coder=dict(
type='DeltaXYWHBBoxCoder',
target_means=[0.0, 0.0, 0.0, 0.0],
target_stds=[0.1, 0.1, 0.2, 0.2]),
reg_class_agnostic=False,
loss_cls=dict(
type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),
loss_bbox=dict(type='L1Loss', loss_weight=1.0)),
train_cfg=dict(
assigner=dict(
type='MaxIoUAssigner',
pos_iou_thr=0.5,
neg_iou_thr=0.5,
min_pos_iou=0.5,
match_low_quality=False,
ignore_iof_thr=-1),
sampler=dict(
type='RandomSampler',
num=512,
pos_fraction=0.25,
neg_pos_ub=-1,
add_gt_as_proposals=True),
pos_weight=-1,
debug=False),
test_cfg=dict(
score_thr=0.05,
nms=dict(type='nms', iou_threshold=0.5),
max_per_img=100),
pretrained='torchvision://resnet50'),
train_cfg=dict(
rpn=dict(
assigner=dict(
type='MaxIoUAssigner',
pos_iou_thr=0.7,
neg_iou_thr=0.3,
min_pos_iou=0.3,
match_low_quality=True,
ignore_iof_thr=-1),
sampler=dict(
type='RandomSampler',
num=256,
pos_fraction=0.5,
neg_pos_ub=-1,
add_gt_as_proposals=False),
allowed_border=-1,
pos_weight=-1,
debug=False),
rpn_proposal=dict(
nms_pre=2000,
max_per_img=1000,
nms=dict(type='nms', iou_threshold=0.7),
min_bbox_size=0),
rcnn=dict(
assigner=dict(
type='MaxIoUAssigner',
pos_iou_thr=0.5,
neg_iou_thr=0.5,
min_pos_iou=0.5,
match_low_quality=False,
ignore_iof_thr=-1),
sampler=dict(
type='RandomSampler',
num=512,
pos_fraction=0.25,
neg_pos_ub=-1,
add_gt_as_proposals=True),
pos_weight=-1,
debug=False)),
test_cfg=dict(
rpn=dict(
nms_pre=1000,
max_per_img=1000,
nms=dict(type='nms', iou_threshold=0.7),
min_bbox_size=0),
rcnn=dict(
score_thr=0.05,
nms=dict(type='nms', iou_threshold=0.5),
max_per_img=100)))
dataset_type = 'KittyTinyDataset'
data_root = '/content/kitti_tiny/'
img_norm_cfg = dict(
mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
train_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='LoadAnnotations', with_bbox=True),
dict(type='Resize', img_scale=(1333, 800), keep_ratio=True),
dict(type='RandomFlip', flip_ratio=0.5),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='Pad', size_divisor=32),
dict(type='DefaultFormatBundle'),
dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])
]
test_pipeline = [
dict(type='LoadImageFromFile'),
dict(
type='MultiScaleFlipAug',
img_scale=(1333, 800),
flip=False,
transforms=[
dict(type='Resize', keep_ratio=True),
dict(type='RandomFlip'),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='Pad', size_divisor=32),
dict(type='ImageToTensor', keys=['img']),
dict(type='Collect', keys=['img'])
])
]
data = dict(
samples_per_gpu=2,
workers_per_gpu=2,
train=dict(
type='KittyTinyDataset',
ann_file='train.txt',
img_prefix='training/image_2',
pipeline=[
dict(type='LoadImageFromFile'),
dict(type='LoadAnnotations', with_bbox=True),
dict(type='Resize', img_scale=(1333, 800), keep_ratio=True),
dict(type='RandomFlip', flip_ratio=0.5),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='Pad', size_divisor=32),
dict(type='DefaultFormatBundle'),
dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])
],
data_root='/content/kitti_tiny/'),
val=dict(
type='KittyTinyDataset',
ann_file='val.txt',
img_prefix='training/image_2',
pipeline=[
dict(type='LoadImageFromFile'),
dict(
type='MultiScaleFlipAug',
img_scale=(1333, 800),
flip=False,
transforms=[
dict(type='Resize', keep_ratio=True),
dict(type='RandomFlip'),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='Pad', size_divisor=32),
dict(type='ImageToTensor', keys=['img']),
dict(type='Collect', keys=['img'])
])
],
data_root='/content/kitti_tiny/'),
test=dict(
type='KittyTinyDataset',
ann_file='val.txt',
img_prefix='training/image_2',
pipeline=[
dict(type='LoadImageFromWebcam'),
dict(
type='MultiScaleFlipAug',
img_scale=(1333, 800),
flip=False,
transforms=[
dict(type='Resize', keep_ratio=True),
dict(type='RandomFlip'),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='Pad', size_divisor=32),
dict(type='DefaultFormatBundle'),
dict(type='Collect', keys=['img'])
])
],
data_root='/content/kitti_tiny/'))
evaluation = dict(interval=12, metric='mAP', by_epoch=True)
optimizer = dict(type='SGD', lr=0.0025, momentum=0.9, weight_decay=0.0001)
optimizer_config = dict(grad_clip=None, type='OptimizerHook')
lr_config = dict(
warmup=None,
warmup_iters=500,
warmup_ratio=0.001,
step=[8, 11],
type='StepLrUpdaterHook',
policy='step')
runner = dict(type='EpochBasedRunner', max_epochs=12)
checkpoint_config = dict(interval=12, type='CheckpointHook')
log_config = dict(interval=10, hooks=[dict(type='TextLoggerHook')])
custom_hooks = [dict(type='NumClassCheckHook')]
dist_params = dict(backend='nccl')
log_level = 'INFO'
load_from = 'checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth'
resume_from = None
workflow = [('train', 1)]
work_dir = './tutorial_exps'
seed = 0
gpu_ids = range(0, 1)
from mmdet.datasets import build_dataset
from mmdet.models import build_detector
from mmdet.apis import train_detector
# train용 Dataset 생성.
datasets = [build_dataset(cfg.data.train)]
datasets
# [
# KittyTinyDataset Train dataset with number of images 50, and instance counts:
# +----------+-------+-----------+-------+----------------+-------+-------------+-------+---------------+-------+
# | category | count | category | count | category | count | category | count | category | count |
# +----------+-------+-----------+-------+----------------+-------+-------------+-------+---------------+-------+
# | 0 [Car] | 147 | 1 [Truck] | 7 | 2 [Pedestrian] | 23 | 3 [Cyclist] | 7 | -1 background | 0 |
# +----------+-------+-----------+-------+----------------+-------+-------------+-------+---------------+-------+]
datasets[0].CLASSES
# ('Car', 'Truck', 'Pedestrian', 'Cyclist')
model = build_detector(cfg.model, train_cfg=cfg.get('train_cfg'), test_cfg=cfg.get('test_cfg'))
model.CLASSES = datasets[0].CLASSES
# /usr/local/lib/python3.7/dist-packages/mmdet-2.12.0-py3.7.egg/mmdet/models/backbones/resnet.py:400: UserWarning: DeprecationWarning: pretrained is a deprecated, please use "init_cfg" instead
# warnings.warn('DeprecationWarning: pretrained is a deprecated, '
# 주의, config에 pretrained 모델 지정이 상대 경로로 설정됨 cfg.load_from = 'checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth'
# 아래와 같이 %cd mmdetection 지정 필요.
%cd mmdetection
mmcv.mkdir_or_exist(osp.abspath(cfg.work_dir))
# epochs는 config의 runner 파라미터로 지정됨. 기본 12회
train_detector(model, datasets, cfg, distributed=False, validate=True)
/content/mmdetection
2021-05-27 02:01:03,488 - mmdet - INFO - load checkpoint from checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth
2021-05-27 02:01:03,489 - mmdet - INFO - Use load_from_local loader
##### self.data_root: /content/kitti_tiny/ self.ann_file: /content/kitti_tiny/val.txt self.img_prefix: /content/kitti_tiny/training/image_2
#### ann_file: /content/kitti_tiny/val.txt
2021-05-27 02:01:03,630 - mmdet - WARNING - The model and loaded state dict do not match exactly
size mismatch for roi_head.bbox_head.fc_cls.weight: copying a param with shape torch.Size([81, 1024]) from checkpoint, the shape in current model is torch.Size([5, 1024]).
size mismatch for roi_head.bbox_head.fc_cls.bias: copying a param with shape torch.Size([81]) from checkpoint, the shape in current model is torch.Size([5]).
size mismatch for roi_head.bbox_head.fc_reg.weight: copying a param with shape torch.Size([320, 1024]) from checkpoint, the shape in current model is torch.Size([16, 1024]).
size mismatch for roi_head.bbox_head.fc_reg.bias: copying a param with shape torch.Size([320]) from checkpoint, the shape in current model is torch.Size([16]).
2021-05-27 02:01:03,639 - mmdet - INFO - Start running, host: root@d7fd648a5af0, work_dir: /content/mmdetection/tutorial_exps
2021-05-27 02:01:03,640 - mmdet - INFO - workflow: [('train', 1)], max: 12 epochs
2021-05-27 02:01:08,457 - mmdet - INFO - Epoch [1][10/25] lr: 2.500e-03, eta: 0:02:18, time: 0.476, data_time: 0.229, memory: 2226, loss_rpn_cls: 0.0275, loss_rpn_bbox: 0.0179, loss_cls: 0.7554, acc: 73.3594, loss_bbox: 0.4131, loss: 1.2139
2021-05-27 02:01:10,877 - mmdet - INFO - Epoch [1][20/25] lr: 2.500e-03, eta: 0:01:40, time: 0.242, data_time: 0.012, memory: 2226, loss_rpn_cls: 0.0178, loss_rpn_bbox: 0.0128, loss_cls: 0.2395, acc: 92.2559, loss_bbox: 0.3446, loss: 0.6147
2021-05-27 02:01:16,800 - mmdet - INFO - Epoch [2][10/25] lr: 2.500e-03, eta: 0:01:29, time: 0.464, data_time: 0.228, memory: 2226, loss_rpn_cls: 0.0151, loss_rpn_bbox: 0.0156, loss_cls: 0.2097, acc: 93.5547, loss_bbox: 0.3205, loss: 0.5609
2021-05-27 02:01:19,231 - mmdet - INFO - Epoch [2][20/25] lr: 2.500e-03, eta: 0:01:20, time: 0.243, data_time: 0.012, memory: 2226, loss_rpn_cls: 0.0133, loss_rpn_bbox: 0.0131, loss_cls: 0.1617, acc: 94.0332, loss_bbox: 0.2242, loss: 0.4123
2021-05-27 02:01:25,113 - mmdet - INFO - Epoch [3][10/25] lr: 2.500e-03, eta: 0:01:15, time: 0.462, data_time: 0.227, memory: 2226, loss_rpn_cls: 0.0048, loss_rpn_bbox: 0.0117, loss_cls: 0.1387, acc: 95.1465, loss_bbox: 0.1990, loss: 0.3543
2021-05-27 02:01:27,568 - mmdet - INFO - Epoch [3][20/25] lr: 2.500e-03, eta: 0:01:10, time: 0.246, data_time: 0.012, memory: 2226, loss_rpn_cls: 0.0069, loss_rpn_bbox: 0.0125, loss_cls: 0.1741, acc: 93.4863, loss_bbox: 0.2716, loss: 0.4651
2021-05-27 02:01:33,510 - mmdet - INFO - Epoch [4][10/25] lr: 2.500e-03, eta: 0:01:05, time: 0.466, data_time: 0.225, memory: 2226, loss_rpn_cls: 0.0071, loss_rpn_bbox: 0.0151, loss_cls: 0.1503, acc: 94.2578, loss_bbox: 0.2479, loss: 0.4204
2021-05-27 02:01:35,960 - mmdet - INFO - Epoch [4][20/25] lr: 2.500e-03, eta: 0:01:01, time: 0.245, data_time: 0.013, memory: 2226, loss_rpn_cls: 0.0028, loss_rpn_bbox: 0.0123, loss_cls: 0.1339, acc: 95.1172, loss_bbox: 0.2092, loss: 0.3582
2021-05-27 02:01:41,874 - mmdet - INFO - Epoch [5][10/25] lr: 2.500e-03, eta: 0:00:57, time: 0.466, data_time: 0.226, memory: 2226, loss_rpn_cls: 0.0038, loss_rpn_bbox: 0.0100, loss_cls: 0.1278, acc: 94.9512, loss_bbox: 0.2143, loss: 0.3559
2021-05-27 02:01:44,334 - mmdet - INFO - Epoch [5][20/25] lr: 2.500e-03, eta: 0:00:53, time: 0.246, data_time: 0.012, memory: 2226, loss_rpn_cls: 0.0071, loss_rpn_bbox: 0.0119, loss_cls: 0.1317, acc: 94.7852, loss_bbox: 0.2035, loss: 0.3542
2021-05-27 02:01:50,296 - mmdet - INFO - Epoch [6][10/25] lr: 2.500e-03, eta: 0:00:49, time: 0.467, data_time: 0.228, memory: 2226, loss_rpn_cls: 0.0014, loss_rpn_bbox: 0.0094, loss_cls: 0.1039, acc: 96.0059, loss_bbox: 0.1820, loss: 0.2968
2021-05-27 02:01:52,762 - mmdet - INFO - Epoch [6][20/25] lr: 2.500e-03, eta: 0:00:45, time: 0.247, data_time: 0.012, memory: 2226, loss_rpn_cls: 0.0039, loss_rpn_bbox: 0.0104, loss_cls: 0.1045, acc: 96.0840, loss_bbox: 0.1877, loss: 0.3065
2021-05-27 02:01:58,690 - mmdet - INFO - Epoch [7][10/25] lr: 2.500e-03, eta: 0:00:41, time: 0.465, data_time: 0.225, memory: 2226, loss_rpn_cls: 0.0019, loss_rpn_bbox: 0.0106, loss_cls: 0.1018, acc: 96.2402, loss_bbox: 0.1835, loss: 0.2978
2021-05-27 02:02:01,159 - mmdet - INFO - Epoch [7][20/25] lr: 2.500e-03, eta: 0:00:38, time: 0.247, data_time: 0.011, memory: 2226, loss_rpn_cls: 0.0039, loss_rpn_bbox: 0.0125, loss_cls: 0.0970, acc: 96.2500, loss_bbox: 0.1859, loss: 0.2993
2021-05-27 02:02:07,094 - mmdet - INFO - Epoch [8][10/25] lr: 2.500e-03, eta: 0:00:33, time: 0.464, data_time: 0.225, memory: 2226, loss_rpn_cls: 0.0029, loss_rpn_bbox: 0.0088, loss_cls: 0.0875, acc: 96.6309, loss_bbox: 0.1584, loss: 0.2575
2021-05-27 02:02:09,550 - mmdet - INFO - Epoch [8][20/25] lr: 2.500e-03, eta: 0:00:30, time: 0.246, data_time: 0.012, memory: 2226, loss_rpn_cls: 0.0020, loss_rpn_bbox: 0.0089, loss_cls: 0.0976, acc: 96.4160, loss_bbox: 0.1765, loss: 0.2850
2021-05-27 02:02:15,504 - mmdet - INFO - Epoch [9][10/25] lr: 2.500e-04, eta: 0:00:26, time: 0.466, data_time: 0.225, memory: 2226, loss_rpn_cls: 0.0029, loss_rpn_bbox: 0.0093, loss_cls: 0.0829, acc: 96.8457, loss_bbox: 0.1472, loss: 0.2423
2021-05-27 02:02:17,968 - mmdet - INFO - Epoch [9][20/25] lr: 2.500e-04, eta: 0:00:23, time: 0.246, data_time: 0.013, memory: 2226, loss_rpn_cls: 0.0012, loss_rpn_bbox: 0.0071, loss_cls: 0.0760, acc: 97.2168, loss_bbox: 0.1358, loss: 0.2201
2021-05-27 02:02:23,924 - mmdet - INFO - Epoch [10][10/25] lr: 2.500e-04, eta: 0:00:19, time: 0.466, data_time: 0.226, memory: 2226, loss_rpn_cls: 0.0027, loss_rpn_bbox: 0.0095, loss_cls: 0.0899, acc: 96.4160, loss_bbox: 0.1554, loss: 0.2575
2021-05-27 02:02:26,391 - mmdet - INFO - Epoch [10][20/25] lr: 2.500e-04, eta: 0:00:15, time: 0.247, data_time: 0.012, memory: 2226, loss_rpn_cls: 0.0013, loss_rpn_bbox: 0.0064, loss_cls: 0.0731, acc: 97.2168, loss_bbox: 0.1324, loss: 0.2132
2021-05-27 02:02:32,334 - mmdet - INFO - Epoch [11][10/25] lr: 2.500e-04, eta: 0:00:11, time: 0.465, data_time: 0.225, memory: 2226, loss_rpn_cls: 0.0037, loss_rpn_bbox: 0.0084, loss_cls: 0.0911, acc: 96.3965, loss_bbox: 0.1458, loss: 0.2490
2021-05-27 02:02:34,811 - mmdet - INFO - Epoch [11][20/25] lr: 2.500e-04, eta: 0:00:08, time: 0.248, data_time: 0.012, memory: 2226, loss_rpn_cls: 0.0012, loss_rpn_bbox: 0.0087, loss_cls: 0.0703, acc: 97.3047, loss_bbox: 0.1367, loss: 0.2168
2021-05-27 02:02:40,779 - mmdet - INFO - Epoch [12][10/25] lr: 2.500e-05, eta: 0:00:04, time: 0.469, data_time: 0.226, memory: 2226, loss_rpn_cls: 0.0016, loss_rpn_bbox: 0.0065, loss_cls: 0.0630, acc: 97.5586, loss_bbox: 0.1168, loss: 0.1879
2021-05-27 02:02:43,234 - mmdet - INFO - Epoch [12][20/25] lr: 2.500e-05, eta: 0:00:01, time: 0.245, data_time: 0.013, memory: 2226, loss_rpn_cls: 0.0016, loss_rpn_bbox: 0.0070, loss_cls: 0.0700, acc: 97.2949, loss_bbox: 0.1068, loss: 0.1853
[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>] 25/25, 13.7 task/s, elapsed: 2s, ETA: 0s
---------------iou_thr: 0.5---------------
2021-05-27 02:02:46,577 - mmdet - INFO -
+------------+-----+------+--------+-------+
| class | gts | dets | recall | ap |
+------------+-----+------+--------+-------+
| Car | 62 | 145 | 0.935 | 0.829 |
| Truck | 3 | 16 | 1.000 | 0.600 |
| Pedestrian | 13 | 49 | 0.923 | 0.781 |
| Cyclist | 7 | 51 | 0.714 | 0.180 |
+------------+-----+------+--------+-------+
| mAP | | | | 0.598 |
+------------+-----+------+--------+-------+
2021-05-27 02:02:46,581 - mmdet - INFO - Saving checkpoint at 12 epochs
2021-05-27 02:02:47,549 - mmdet - INFO - Epoch(val) [12][25] AP50: 0.5980, mAP: 0.5975
from mmdet.apis import inference_detector, init_detector, show_result_pyplot
# BGR Image 사용
img = cv2.imread('/content/kitti_tiny/training/image_2/000068.jpeg')
model.cfg = cfg
result = inference_detector(model, img)
show_result_pyplot(model, img, result)
5-1. config의 이해 - 대분류 및 주요 설정 (0) | 2021.10.17 |
---|---|
4-15. tiny kitti video inference (0) | 2021.10.11 |
4-8~10. tiny kitti 데이터로 mmdetection train (0) | 2021.10.11 |
4-7. tiny kitti - dataset (0) | 2021.10.11 |
4-6. faster-rcnn pretrained model로 video inference 실행 (0) | 2021.10.10 |
# https://github.com/open-mmlab/mmdetection/blob/master/demo/MMDet_Tutorial.ipynb 에서 발췌
# mmcv를 위해서 mmcv-full을 먼저 설치해야 함.
!pip install mmcv-full
# mmdetection 설치
!git clone https://github.com/open-mmlab/mmdetection.git
!cd mmdetection; python setup.py install
# 아래를 수행하기 전에 kernel을 restart 해야 함.
from mmdet.apis import init_detector, inference_detector
import mmcv
# 튜토리얼용 dataset
!wget https://download.openmmlab.com/mmdetection/data/kitti_tiny.zip
!unzip kitti_tiny.zip > /dev/null
import matplotlib.pyplot as plt
import cv2
img = cv2.cvtColor(cv2.imread('/content/kitti_tiny/training/image_2/000068.jpeg'), cv2.COLOR_BGR2RGB)
plt.figure(figsize=(15, 10))
plt.imshow(img)
!cat /content/kitti_tiny/training/label_2/000068.txt
# Car 0.25 0 1.94 69.26 200.28 435.08 374.00 1.46 1.62 4.04 -3.00 1.79 6.98 1.55
# Car 0.80 1 2.26 0.00 209.20 198.59 374.00 1.46 1.58 3.72 -5.44 1.85 6.22 1.56
# Cyclist 0.97 0 2.34 1210.28 199.77 1241.00 374.00 1.55 0.57 1.73 4.04 1.69 3.57 -3.14
# Car 0.00 2 1.68 478.18 187.68 549.54 249.43 1.57 1.60 3.99 -2.73 2.03 20.96 1.55
# Car 0.00 1 1.66 530.03 187.79 573.10 226.09 1.52 1.54 3.68 -2.53 2.20 31.50 1.58
# Van 0.00 1 1.63 547.61 171.12 584.05 212.41 2.47 1.98 5.81 -2.79 2.41 46.44 1.57
# Car 0.00 1 -0.16 667.74 182.35 790.82 230.38 1.62 1.65 4.14 4.19 1.99 25.95 0.00
# Car 0.00 2 -0.11 657.37 184.48 763.34 221.64 1.55 1.66 4.47 4.35 2.10 32.00 0.02
# Car 0.00 1 -0.01 637.45 180.34 714.44 212.34 1.69 1.76 4.12 3.59 2.12 39.79 0.08
# Van 0.00 1 1.61 572.52 175.02 596.26 199.95 2.13 1.91 6.40 -2.28 2.36 65.43 1.57
# Van 0.00 1 1.77 380.78 167.69 523.29 288.56 1.95 1.75 4.63 -2.89 1.90 14.05 1.57
# Cyclist 0.00 1 1.09 958.95 167.55 1036.88 254.43 1.68 0.53 1.96 7.95 1.59 14.95 1.57
!cat /content/kitti_tiny/train.txt
000000
000001
000002
000003
000004
000005
000006
000007
000008
000009
000010
000011
000012
000013
000014
000015
000016
000017
000018
000019
000020
000021
000022
000023
000024
000025
000026
000027
000028
000029
000030
000031
000032
000033
000034
000035
000036
000037
000038
000039
000040
000041
000042
000043
000044
000045
000046
000047
000048
000049
# 원본 kitti Dataset는 10개의 Class로 되어 있음. 'Car Van Truck Pedestrian Person_sitting Cyclist Tram Misc DontCare'
CLASSES = ('Car', 'Truck', 'Pedestrian', 'Cyclist')
cat2label = {k:i for i, k in enumerate(CLASSES)}
print(cat2label)
cat2label['Car']
# {'Car': 0, 'Truck': 1, 'Pedestrian': 2, 'Cyclist': 3}
# 0
image_list = mmcv.list_from_file('/content/kitti_tiny/train.txt')
lines = mmcv.list_from_file('/content/kitti_tiny/training/label_2/000064.txt')
#print(lines)
content = [line.strip().split(' ') for line in lines]
bbox_names = [x[0] for x in content]
#print(bbox_names)
bboxes = [ [float(info) for info in x[4:8]] for x in content]
print(bboxes)
# [[657.65, 179.93, 709.86, 219.92], [731.51, 180.39, 882.28, 275.8], [715.18, 175.63, 762.77, 203.9], [816.58, 59.74, 1112.51, 266.07], [626.78, 174.27, 647.77, 192.18], [546.19, 168.97, 554.01, 177.09]]
dataset, config의 관계를 이해하는 것이 가장 중요하다.
custom dataset 생성 주요 로직
0. dataset을 위한 config 설정(data_root, ann_file, img_prefix)
- build_dataset()으로 아래 작업해줌
1. customdataset객체를 mmdetection framework에 등록
- @DATASETS.register_module(force=True) customdataset을 상속한 클래스 생성
- load_annotations()을 재정의 하여 middle format으로 원본 소스 변환
2. config에 설정된 주요값으로 customdataset 객체 생성
import copy
import os.path as osp
import cv2
import mmcv
import numpy as np
from mmdet.datasets.builder import DATASETS
from mmdet.datasets.custom import CustomDataset
# 반드시 아래 Decorator 설정 할것.@DATASETS.register_module() 설정 시 force=True를 입력하지 않으면 Dataset 재등록 불가.
@DATASETS.register_module(force=True)
class KittyTinyDataset(CustomDataset):
CLASSES = ('Car', 'Truck', 'Pedestrian', 'Cyclist')
##### self.data_root: /content/kitti_tiny/ self.ann_file: /content/kitti_tiny/train.txt self.img_prefix: /content/kitti_tiny/training/image_2
#### ann_file: /content/kitti_tiny/train.txt
# annotation에 대한 모든 파일명을 가지고 있는 텍스트 파일을 __init__(self, ann_file)로 입력 받고, 이 self.ann_file이 load_annotations()의 인자로 입력
def load_annotations(self, ann_file):
print('##### self.data_root:', self.data_root, 'self.ann_file:', self.ann_file, 'self.img_prefix:', self.img_prefix)
print('#### ann_file:', ann_file)
cat2label = {k:i for i, k in enumerate(self.CLASSES)}
image_list = mmcv.list_from_file(self.ann_file)
# 포맷 중립 데이터를 담을 list 객체
data_infos = []
for image_id in image_list:
filename = '{0:}/{1:}.jpeg'.format(self.img_prefix, image_id)
# 원본 이미지의 너비, 높이를 image를 직접 로드하여 구함.
image = cv2.imread(filename)
height, width = image.shape[:2]
# 개별 image의 annotation 정보 저장용 Dict 생성. key값 filename 에는 image의 파일명만 들어감(디렉토리는 제외)
data_info = {'filename': str(image_id) + '.jpeg',
'width': width, 'height': height}
# 개별 annotation이 있는 서브 디렉토리의 prefix 변환.
label_prefix = self.img_prefix.replace('image_2', 'label_2')
# 개별 annotation 파일을 1개 line 씩 읽어서 list 로드
lines = mmcv.list_from_file(osp.join(label_prefix, str(image_id)+'.txt'))
# 전체 lines를 개별 line별 공백 레벨로 parsing 하여 다시 list로 저장. content는 list의 list형태임.
# ann 정보는 numpy array로 저장되나 텍스트 처리나 데이터 가공이 list 가 편하므로 일차적으로 list로 변환 수행.
content = [line.strip().split(' ') for line in lines]
# 오브젝트의 클래스명은 bbox_names로 저장.
bbox_names = [x[0] for x in content]
# bbox 좌표를 저장
bboxes = [ [float(info) for info in x[4:8]] for x in content]
# 클래스명이 해당 사항이 없는 대상 Filtering out, 'DontCare'sms ignore로 별도 저장.
gt_bboxes = []
gt_labels = []
gt_bboxes_ignore = []
gt_labels_ignore = []
for bbox_name, bbox in zip(bbox_names, bboxes):
# 만약 bbox_name이 클래스명에 해당 되면, gt_bboxes와 gt_labels에 추가, 그렇지 않으면 gt_bboxes_ignore, gt_labels_ignore에 추가
if bbox_name in cat2label:
gt_bboxes.append(bbox)
# gt_labels에는 class id를 입력
gt_labels.append(cat2label[bbox_name])
else:
gt_bboxes_ignore.append(bbox)
gt_labels_ignore.append(-1)
# 개별 image별 annotation 정보를 가지는 Dict 생성. 해당 Dict의 value값은 모두 np.array임.
data_anno = {
'bboxes': np.array(gt_bboxes, dtype=np.float32).reshape(-1, 4),
'labels': np.array(gt_labels, dtype=np.long),
'bboxes_ignore': np.array(gt_bboxes_ignore, dtype=np.float32).reshape(-1, 4),
'labels_ignore': np.array(gt_labels_ignore, dtype=np.long)
}
# image에 대한 메타 정보를 가지는 data_info Dict에 'ann' key값으로 data_anno를 value로 저장.
data_info.update(ann=data_anno)
# 전체 annotation 파일들에 대한 정보를 가지는 data_infos에 data_info Dict를 추가
data_infos.append(data_info)
return data_infos
data_root, ann_file, img_prefix의 활용
- 학습용, 검증용, 테스트용으로 dataset이 만들어져야한다.
소스 데이터들의 학습용, 검증용, 테스트용 분리유형
- image 들과 annotation파일이 학습용, 검증용, 테스트용 디렉토리에 별도로 분리
- 별도의 메타 파일에서 각 image, annotation 지정
- image들 각 용도에 맞게 디렉토리별 분리, annotation은 각 용도별 하나만 가짐(3개 json)
* img_prefix는 여러개의 image들을 포함할 수 있는 디렉토리 형태로 지정되지만, ann_file은 단하나만 지정할 수 있음
# 학습 data config 셋팅
train.data_root=/content/kitti_tiny
train.ann_file='train.txt'
train.img_prefix='training/image_2'
# 학습 kitti data config 셋팅
train_dataset = kittiYinydataset(ann_file = train.data_root,
data_root = train.ann_file,
img_prefix = train.img_prefix )
4-15. tiny kitti video inference (0) | 2021.10.11 |
---|---|
4-11~14. tiny kitti data로 customdataset, config 설정, image inference (0) | 2021.10.11 |
4-7. tiny kitti - dataset (0) | 2021.10.11 |
4-6. faster-rcnn pretrained model로 video inference 실행 (0) | 2021.10.10 |
4-3-5. MMDetection faster-RCNN pretrained model inference 실행 (0) | 2021.10.10 |
mmdetection의 주요구성요소
dataset을 model에 입력시켜야 함.
model을 weight값을 갱신하면서 고도화시켜야함
dataset에는 image, detection을 위한 annotation이 있고, dataset config file에 저장이 되어있음.
전체적으로 config 파일에 의해서 통제가 됨.
dataset의 변환도 중요함
pv, coco 등 많은 dataset이 있는데 이것을 mmdetection이 받아들이기 쉽게 transformation해야 함.
mmdetection dataset 지원
=> mmdetection은 다양한 유형의 dataset을 변환 클래스를 통해서 지원함
custom dataset, cocodataset, vocdataset, widerfaceDataset, XMLdataset 중
customdataset, cocodataset이 쉽게 적용될 수 있는 dataset임
pascal voc 데이터 세트 특징
ds_name = 'voc07'으로 pascal 형식을 그대로 따름
VOCdevkit - voc2012 - annotations, imageset, jpegimage, segmentationclass, segmentationobject
=> 디렉토리 의 구조를 맞춰줘야함. 차라리 custom dataset 을 parsing 하는게 나음
ms-coco 데이터 세트 특징
모든 이미지들에 대해 단 1개의 annotation 파일을 가짐
train, val, test전부 json 포맷인 한개의 파일, 한 라인으로 구성됨
json { info, license,
images {id, file_name, width, height},
annotations {image, object id, segmentation, bounding box, pixel area},
categories (80개 object categories 에 대한 id, names, group)
}
custom dataset에 사용되는 포멧
- 모든 이미지에 대한 annotation정보들을 list객체로 가짐
- list 내 개별 원소는 dict로 구성되면 개별 dict는 1개 이미지에 대한 annotation 정보를 가짐
- 1개 이미지는 여러개의 object bbox와 labels annotation 정보들을 개별 dict로 가짐
- 1개 이미지의 object bbox와 2차원 array로 , label은 1차원 array로 구성됨.
4-11~14. tiny kitti data로 customdataset, config 설정, image inference (0) | 2021.10.11 |
---|---|
4-8~10. tiny kitti 데이터로 mmdetection train (0) | 2021.10.11 |
4-6. faster-rcnn pretrained model로 video inference 실행 (0) | 2021.10.10 |
4-3-5. MMDetection faster-RCNN pretrained model inference 실행 (0) | 2021.10.10 |
4-1~2. pytorch 기반 주요 object detection / segmentation 패키지 (0) | 2021.09.28 |
!wget -O /content/data/John_Wick_small.mp4 https://github.com/chulminkw/DLCV/blob/master/data/video/John_Wick_small.mp4?raw=true
from mmdet.apis import init_detector, inference_detector
import mmcv
config_file = '/content/mmdetection/configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py'
checkpoint_file = '/content/mmdetection/checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth'
model = init_detector(config_file, checkpoint_file, device='cuda:0')
# https://github.com/open-mmlab/mmdetection/blob/master/demo/video_demo.py 대로 video detection 수행.
import cv2
video_reader = mmcv.VideoReader('/content/data/John_Wick_small.mp4')
video_writer = None
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
video_writer = cv2.VideoWriter('/content/data/John_Wick_small_out1.mp4', fourcc, video_reader.fps,(video_reader.width, video_reader.height))
for frame in mmcv.track_iter_progress(video_reader):
result = inference_detector(model, frame)
frame = model.show_result(frame, result, score_thr=0.4)
video_writer.write(frame)
if video_writer:
video_writer.release()
# model과 원본 이미지 array, filtering할 기준 class confidence score를 인자로 가지는 inference 시각화용 함수 생성.
import numpy as np
# 0부터 순차적으로 클래스 매핑된 label 적용.
labels_to_names_seq = {0:'person',1:'bicycle',2:'car',3:'motorbike',4:'aeroplane',5:'bus',6:'train',7:'truck',8:'boat',9:'traffic light',10:'fire hydrant',
11:'stop sign',12:'parking meter',13:'bench',14:'bird',15:'cat',16:'dog',17:'horse',18:'sheep',19:'cow',20:'elephant',
21:'bear',22:'zebra',23:'giraffe',24:'backpack',25:'umbrella',26:'handbag',27:'tie',28:'suitcase',29:'frisbee',30:'skis',
31:'snowboard',32:'sports ball',33:'kite',34:'baseball bat',35:'baseball glove',36:'skateboard',37:'surfboard',38:'tennis racket',39:'bottle',40:'wine glass',
41:'cup',42:'fork',43:'knife',44:'spoon',45:'bowl',46:'banana',47:'apple',48:'sandwich',49:'orange',50:'broccoli',
51:'carrot',52:'hot dog',53:'pizza',54:'donut',55:'cake',56:'chair',57:'sofa',58:'pottedplant',59:'bed',60:'diningtable',
61:'toilet',62:'tvmonitor',63:'laptop',64:'mouse',65:'remote',66:'keyboard',67:'cell phone',68:'microwave',69:'oven',70:'toaster',
71:'sink',72:'refrigerator',73:'book',74:'clock',75:'vase',76:'scissors',77:'teddy bear',78:'hair drier',79:'toothbrush' }
def get_detected_img(model, img_array, score_threshold=0.3, is_print=True):
# 인자로 들어온 image_array를 복사.
draw_img = img_array.copy()
bbox_color=(0, 255, 0)
text_color=(0, 0, 255)
# model과 image array를 입력 인자로 inference detection 수행하고 결과를 results로 받음.
# results는 80개의 2차원 array(shape=(오브젝트갯수, 5))를 가지는 list.
results = inference_detector(model, img_array)
# 80개의 array원소를 가지는 results 리스트를 loop를 돌면서 개별 2차원 array들을 추출하고 이를 기반으로 이미지 시각화
# results 리스트의 위치 index가 바로 COCO 매핑된 Class id. 여기서는 result_ind가 class id
# 개별 2차원 array에 오브젝트별 좌표와 class confidence score 값을 가짐.
for result_ind, result in enumerate(results):
# 개별 2차원 array의 row size가 0 이면 해당 Class id로 값이 없으므로 다음 loop로 진행.
if len(result) == 0:
continue
# 2차원 array에서 5번째 컬럼에 해당하는 값이 score threshold이며 이 값이 함수 인자로 들어온 score_threshold 보다 낮은 경우는 제외.
result_filtered = result[np.where(result[:, 4] > score_threshold)]
# 해당 클래스 별로 Detect된 여러개의 오브젝트 정보가 2차원 array에 담겨 있으며, 이 2차원 array를 row수만큼 iteration해서 개별 오브젝트의 좌표값 추출.
for i in range(len(result_filtered)):
# 좌상단, 우하단 좌표 추출.
left = int(result_filtered[i, 0])
top = int(result_filtered[i, 1])
right = int(result_filtered[i, 2])
bottom = int(result_filtered[i, 3])
caption = "{}: {:.4f}".format(labels_to_names_seq[result_ind], result_filtered[i, 4])
cv2.rectangle(draw_img, (left, top), (right, bottom), color=bbox_color, thickness=2)
cv2.putText(draw_img, caption, (int(left), int(top - 7)), cv2.FONT_HERSHEY_SIMPLEX, 0.37, text_color, 1)
if is_print:
print(caption)
return draw_img
import time
def do_detected_video(model, input_path, output_path, score_threshold, do_print=True):
cap = cv2.VideoCapture(input_path)
codec = cv2.VideoWriter_fourcc(*'XVID')
vid_size = (round(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),round(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
vid_fps = cap.get(cv2.CAP_PROP_FPS)
vid_writer = cv2.VideoWriter(output_path, codec, vid_fps, vid_size)
frame_cnt = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
print('총 Frame 갯수:', frame_cnt)
btime = time.time()
while True:
hasFrame, img_frame = cap.read()
if not hasFrame:
print('더 이상 처리할 frame이 없습니다.')
break
stime = time.time()
img_frame = get_detected_img(model, img_frame, score_threshold=score_threshold, is_print=False)
if do_print:
print('frame별 detection 수행 시간:', round(time.time() - stime, 4))
vid_writer.write(img_frame)
# end of while loop
vid_writer.release()
cap.release()
print('최종 detection 완료 수행 시간:', round(time.time() - btime, 4))
do_detected_video(model, '/content/data/John_Wick_small.mp4', '/content/data/John_Wick_small_out2.mp4', score_threshold=0.4, do_print=True)
frame별 detection 수행 시간: 0.304
frame별 detection 수행 시간: 0.3139
frame별 detection 수행 시간: 0.2853
frame별 detection 수행 시간: 0.2918
frame별 detection 수행 시간: 0.2905
frame별 detection 수행 시간: 0.299
frame별 detection 수행 시간: 0.3006
frame별 detection 수행 시간: 0.2887
frame별 detection 수행 시간: 0.295
frame별 detection 수행 시간: 0.2932
frame별 detection 수행 시간: 0.2991
frame별 detection 수행 시간: 0.303
frame별 detection 수행 시간: 0.2913
frame별 detection 수행 시간: 0.2953
frame별 detection 수행 시간: 0.3003
frame별 detection 수행 시간: 0.3022
frame별 detection 수행 시간: 0.3018
frame별 detection 수행 시간: 0.2954
frame별 detection 수행 시간: 0.2975
frame별 detection 수행 시간: 0.3034
frame별 detection 수행 시간: 0.292
frame별 detection 수행 시간: 0.288
frame별 detection 수행 시간: 0.2939
frame별 detection 수행 시간: 0.2911
frame별 detection 수행 시간: 0.2969
frame별 detection 수행 시간: 0.2903
frame별 detection 수행 시간: 0.2912
frame별 detection 수행 시간: 0.2906
frame별 detection 수행 시간: 0.2947
frame별 detection 수행 시간: 0.2956
frame별 detection 수행 시간: 0.2936
frame별 detection 수행 시간: 0.2939
frame별 detection 수행 시간: 0.2925
frame별 detection 수행 시간: 0.2939
frame별 detection 수행 시간: 0.3
frame별 detection 수행 시간: 0.2862
frame별 detection 수행 시간: 0.2961
frame별 detection 수행 시간: 0.2958
frame별 detection 수행 시간: 0.2943
frame별 detection 수행 시간: 0.2931
frame별 detection 수행 시간: 0.2856
frame별 detection 수행 시간: 0.2911
frame별 detection 수행 시간: 0.2967
frame별 detection 수행 시간: 0.2944
frame별 detection 수행 시간: 0.2933
frame별 detection 수행 시간: 0.2886
frame별 detection 수행 시간: 0.2926
frame별 detection 수행 시간: 0.2991
frame별 detection 수행 시간: 0.2963
frame별 detection 수행 시간: 0.2885
frame별 detection 수행 시간: 0.2917
frame별 detection 수행 시간: 0.292
frame별 detection 수행 시간: 0.3013
frame별 detection 수행 시간: 0.2963
frame별 detection 수행 시간: 0.2903
더 이상 처리할 frame이 없습니다.
최종 detection 완료 수행 시간: 17.738
4-8~10. tiny kitti 데이터로 mmdetection train (0) | 2021.10.11 |
---|---|
4-7. tiny kitti - dataset (0) | 2021.10.11 |
4-3-5. MMDetection faster-RCNN pretrained model inference 실행 (0) | 2021.10.10 |
4-1~2. pytorch 기반 주요 object detection / segmentation 패키지 (0) | 2021.09.28 |
3-13. 모던 object Detection 모델 아키텍처 (0) | 2021.09.27 |
# 버전 확인
import torch
print(torch.__version__)
# mmcv를 위해서 mmcv-full을 설치해야 함.
!pip install mmcv-full
from google.colab import drive
drive.mount('/content/drive')
!git clone https://github.com/open-mmlab/mmdetection.git
!cd mmdetection; python setup.py install
# 아래를 수행하기 전에 kernel을 restart 해야 함.
# 런타임 초기화하면 설치한 파일 날라감
from mmdet.apis import init_detector, inference_detector
import mmcv
# pretrained weight 모델을 다운로드 받기 위해서 mmdetection/checkpoints 디렉토리를 만듬.
!cd mmdetection; mkdir checkpoints
# pretrained model faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth 설치
!wget -O /content/mmdetection/checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth http://download.openmmlab.com/mmdetection/v2.0/faster_rcnn/faster_rcnn_r50_fpn_1x_coco/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth
# pretrained model 경로 확인
!ls -lia /content/mmdetection/checkpoints
# total 163376
# 3951436 drwxr-xr-x 2 root root 4096 Oct 10 13:13 .
# 3932841 drwxr-xr-x 19 root root 4096 Oct 10 13:13 ..
# 3951438 -rw-r--r-- 1 root root 167287506 Aug 28 2020 faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth
# config 파일을 설정하고, 다운로드 받은 pretrained 모델을 checkpoint로 설정.
config_file = '/content/mmdetection/configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py'
checkpoint_file = '/content/mmdetection/checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth'
# config 파일과 pretrained 모델을 기반으로 Detector 모델을 생성.
from mmdet.apis import init_detector, inference_detector
model = init_detector(config_file, checkpoint_file, device='cuda:0') # gpu 지정
# /usr/local/lib/python3.7/dist-packages/mmdet-2.17.0-py3.7.egg/mmdet/core/anchor/builder.py:17: UserWarning: ``build_anchor_generator`` would be deprecated soon, please use ``build_prior_generator``
# '``build_anchor_generator`` would be deprecated soon, please use '
# Use load_from_local loader
# mmdetection은 상대 경로를 인자로 주면 무조건 mmdetection 디렉토리를 기준으로 함.
%cd mmdetection
from mmdet.apis import init_detector, inference_detector
# init_detector() 인자로 config와 checkpoint를 입력함.
model = init_detector(config='configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py', checkpoint='checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth')
# /content/mmdetection
# /usr/local/lib/python3.7/dist-packages/mmdet-2.17.0-py3.7.egg/mmdet/core/anchor/builder.py:17: UserWarning: ``build_anchor_generator`` would be deprecated soon, please use ``build_prior_generator``
# '``build_anchor_generator`` would be deprecated soon, please use '
# Use load_from_local loader
# mmdetection/configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py - _base_
=> 모델 별로 각각 다른 config를 가지는게 아니라 공통의 config를 지님
mmdetection/configs/_base_/models/fast_rcnn_r50_fpn.py에 neck=dict에 type=fpn으로 되어있음
참고로 나중에 커스컴 할 때 num_classes = n을 바꿔야함, coco dataset이 n개라서
%cd /content
# /content
import cv2
import matplotlib.pyplot as plt
img = '/content/mmdetection/demo/demo.jpg'
img_arr = cv2.cvtColor(cv2.imread(img), cv2.COLOR_BGR2RGB)
plt.figure(figsize=(12, 12))
plt.imshow(img_arr)
img = '/content/mmdetection/demo/demo.jpg'
# inference_detector의 인자로 string(file경로), ndarray가 단일 또는 list형태로 입력 될 수 있음.
results = inference_detector(model, img)
# /usr/local/lib/python3.7/dist-packages/mmdet-2.17.0-py3.7.egg/mmdet/datasets/utils.py:69: UserWarning: "ImageToTensor" pipeline is replaced by "DefaultFormatBundle" for batch inference. It is recommended to manually replace it in the test data pipeline in your config file.
# 'data pipeline in your config file.', UserWarning)
# /usr/local/lib/python3.7/dist-packages/torch/nn/functional.py:718: UserWarning: Named tensors and all their associated APIs are an experimental feature and subject to change. Please do not use them for anything important until they are released as stable. (Triggered internally at /pytorch/c10/core/TensorImpl.h:1156.)
# return torch.max_pool2d(input, kernel_size, stride, padding, dilation, ceil_mode)
# /usr/local/lib/python3.7/dist-packages/mmdet-2.17.0-py3.7.egg/mmdet/core/anchor/anchor_generator.py:324: UserWarning: ``grid_anchors`` would be deprecated soon. Please use ``grid_priors``
# warnings.warn('``grid_anchors`` would be deprecated soon. '
# /usr/local/lib/python3.7/dist-packages/mmdet-2.17.0-py3.7.egg/mmdet/core/anchor/anchor_generator.py:361: UserWarning: ``single_level_grid_anchors`` would be deprecated soon. Please use ``single_level_grid_priors``
# '``single_level_grid_anchors`` would be deprecated soon. '
type(results), len(results)
# (list, 80)
# len이 80개인데, detected 가 80개가 아니라 cocodataset이 80개임
# results는 list형으로 coco class의 0부터 79까지 class_id별로 80개의 array를 가짐.
# 개별 array들은 각 클래스별로 5개의 값(좌표값과 class별로 confidence)을 가짐. 개별 class별로 여러개의 좌표를 가지면 여러개의 array가 생성됨.
# 좌표는 좌상단(xmin, ymin), 우하단(xmax, ymax) 기준.
# 개별 array의 shape는 (Detection된 object들의 수, 5(좌표와 confidence)) 임
results
class)id 0:'person', 1:'bicycle, 2:'car'
[array([[3.75348572e+02, 1.19171005e+02, 3.81950867e+02, 1.34460617e+02,
1.35454327e-01], # 좌표값 좌상단(xmin, ymin), 우하단(xmax, ymax), class confidence
[5.32362000e+02, 1.09554726e+02, 5.40526550e+02, 1.25222633e+02,
8.88783410e-02], # 좌표값 좌상단(xmin, ymin), 우하단(xmax, ymax), class confidence
[3.61124298e+02, 1.09049202e+02, 3.68625610e+02, 1.22483063e+02,
7.20723420e-02]], dtype=float32), # 좌표값 좌상단(xmin, ymin), 우하단(xmax, ymax), class confidence
# class id는 별도로 없고, results[0]이 0번임
# 내부에서 정규화를 해버림
array([], shape=(0, 5), dtype=float32), # 0번 class id는 detect가 안됬다.
array([[6.09650024e+02, 1.13805893e+02, 6.34511658e+02, 1.36951904e+02,
9.88766134e-01],
[4.81773712e+02, 1.10480980e+02, 5.22459717e+02, 1.30407104e+02,
9.87157285e-01],
[1.01822114e+00, 1.12144730e+02, 6.04374733e+01, 1.44173752e+02,
9.83206093e-01],
[2.94623718e+02, 1.17035240e+02, 3.78022705e+02, 1.50550873e+02,
9.71326768e-01],
[3.96328979e+02, 1.11203323e+02, 4.32490540e+02, 1.32729263e+02,
9.67802167e-01],
[5.90976257e+02, 1.10802658e+02, 6.15401794e+02, 1.26493553e+02,
9.59414959e-01],
[2.67582001e+02, 1.05686005e+02, 3.28818756e+02, 1.28226547e+02,
9.59253132e-01],
[1.66856735e+02, 1.08006607e+02, 2.19100693e+02, 1.40194809e+02,
9.56841350e-01],
[1.89769577e+02, 1.09801109e+02, 3.00310852e+02, 1.53781891e+02,
9.51012135e-01],
[4.29822540e+02, 1.05655380e+02, 4.82741516e+02, 1.32376724e+02,
9.45849955e-01],
[5.55000916e+02, 1.09785004e+02, 5.92761780e+02, 1.27808495e+02,
9.43992615e-01],
[5.96790352e+01, 9.31828003e+01, 8.34545441e+01, 1.06242912e+02,
9.33143973e-01],
[9.78446579e+01, 8.96542969e+01, 1.18172356e+02, 1.01011108e+02,
8.66323531e-01],
[1.43898987e+02, 9.61869888e+01, 1.64599792e+02, 1.04979256e+02,
8.26784551e-01],
[8.55894241e+01, 8.99445801e+01, 9.88920746e+01, 9.85285416e+01,
7.53480315e-01],
[9.78282700e+01, 9.07443695e+01, 1.10298050e+02, 9.97373276e+01,
7.16600597e-01],
[2.23579224e+02, 9.85184631e+01, 2.49845108e+02, 1.07509857e+02,
6.00782037e-01],
[1.68928635e+02, 9.59468994e+01, 1.82843445e+02, 1.05694962e+02,
5.91998756e-01],
[1.35021347e+02, 9.08739395e+01, 1.50607025e+02, 1.02798874e+02,
5.54030240e-01],
[0.00000000e+00, 1.11521950e+02, 1.45326691e+01, 1.25850288e+02,
5.43519914e-01],
[5.53896606e+02, 1.16170540e+02, 5.62602295e+02, 1.26390923e+02,
4.76758897e-01],
[3.75809753e+02, 1.19579056e+02, 3.82376495e+02, 1.32113892e+02,
4.61191744e-01],
[1.37924118e+02, 9.37975311e+01, 1.54497177e+02, 1.04659683e+02,
4.00998443e-01],
[5.55009033e+02, 1.10952698e+02, 5.74925659e+02, 1.26912033e+02,
3.43850523e-01],
[5.54043152e+02, 1.00959076e+02, 5.61297913e+02, 1.10927711e+02,
2.87963450e-01],
[6.14741028e+02, 1.01987068e+02, 6.35481628e+02, 1.12593704e+02,
2.61200219e-01],
[5.70760315e+02, 1.09679398e+02, 5.90286133e+02, 1.27248878e+02,
2.58404434e-01],
[4.78544116e-01, 1.11568169e+02, 2.25040989e+01, 1.42623535e+02,
2.56050110e-01],
[3.75093140e+02, 1.11696442e+02, 4.20536804e+02, 1.33691055e+02,
2.55963236e-01],
[2.62747284e+02, 1.07565620e+02, 3.26765930e+02, 1.43925293e+02,
2.09969625e-01],
[7.91312714e+01, 9.03788834e+01, 1.00247879e+02, 1.01080894e+02,
2.03962341e-01],
[6.09313477e+02, 1.13308510e+02, 6.25961975e+02, 1.25342514e+02,
1.97422847e-01],
[1.35304840e+02, 9.23771439e+01, 1.64080185e+02, 1.04992455e+02,
1.49973527e-01],
[6.73540573e+01, 8.85008087e+01, 8.29853592e+01, 9.73942108e+01,
1.48383990e-01],
[5.40852417e+02, 1.13848946e+02, 5.61855530e+02, 1.26198776e+02,
1.47629887e-01],
[3.51735046e+02, 1.09432655e+02, 4.39310089e+02, 1.34819733e+02,
1.41735107e-01],
[9.63179016e+01, 8.98780594e+01, 1.53287781e+02, 1.01776367e+02,
1.32707968e-01],
[4.54495049e+01, 1.17444977e+02, 6.18955803e+01, 1.44275055e+02,
1.25890508e-01],
[6.06407532e+02, 1.12215973e+02, 6.18935669e+02, 1.24957237e+02,
1.10722415e-01],
[1.02152626e+02, 9.36143646e+01, 1.41081863e+02, 1.01598961e+02,
8.13643038e-02],
[3.98364838e+02, 1.12081459e+02, 4.09389862e+02, 1.32897766e+02,
7.64543191e-02],
[5.39245911e+02, 1.12394836e+02, 5.48756714e+02, 1.21964462e+02,
7.32642636e-02],
[6.09156555e+02, 1.04017456e+02, 6.35472107e+02, 1.26777176e+02,
6.47417754e-02],
[3.75894284e+00, 9.85745239e+01, 7.45848312e+01, 1.35154999e+02,
6.32166639e-02],
[1.68166473e+02, 9.14260483e+01, 2.20303146e+02, 1.07955681e+02,
5.16179129e-02],
[7.09724045e+01, 9.02684860e+01, 1.05398132e+02, 1.03825508e+02,
5.15376776e-02]], dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([[1.8820007e+02, 1.0994706e+02, 3.0047137e+02, 1.5633583e+02,
9.7509645e-02],
[4.2774915e+02, 1.0511559e+02, 4.8345541e+02, 1.3294328e+02,
9.6882291e-02],
[2.9450479e+02, 1.1764229e+02, 3.7863284e+02, 1.5046356e+02,
7.4364766e-02]], dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([[2.1920888e+02, 1.7456262e+02, 4.6010886e+02, 3.7704660e+02,
9.7778010e-01],
[3.7206638e+02, 1.3631432e+02, 4.3219531e+02, 1.8717290e+02,
4.1699746e-01]], dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([[9.13259964e+01, 1.07155769e+02, 1.06029366e+02, 1.19777306e+02,
1.15152948e-01]], dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([[3.72651917e+02, 1.36143082e+02, 4.32053833e+02, 1.88446472e+02,
7.77875960e-01],
[2.18404114e+02, 1.75137848e+02, 4.62107605e+02, 3.65541260e+02,
1.01236075e-01]], dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32),
array([], shape=(0, 5), dtype=float32)]
요약
# 2차원 배열로 표현됨
# 사람, 자전거, 차,
results[0].shape, results[1].shape, results[2].shape, results[3].shape
# ((3, 5), (0, 5), (46, 5), (0, 5))
# 3건, 0건, 46건, 0건
결과 직접 확인
from mmdet.apis import show_result_pyplot
# inference 된 결과를 원본 이미지에 적용하여 새로운 image로 생성(bbox 처리된 image)
# Default로 score threshold가 0.3 이상인 Object들만 시각화 적용. show_result_pyplot은 model.show_result()를 호출.
show_result_pyplot(model, img, results)
# configs 파일로 모델을 만들었는데 모델 객체안의 변수 확인
model.__dict__
# 80개 class
{'CLASSES': ('person',
'bicycle',
'car',
'motorcycle',
'airplane',
'bus',
'train',
'truck',
'boat',
'traffic_light',
'fire_hydrant',
'stop_sign',
'parking_meter',
'bench',
'bird',
'cat',
'dog',
'horse',
'sheep',
'cow',
'elephant',
'bear',
'zebra',
'giraffe',
'backpack',
'umbrella',
'handbag',
'tie',
'suitcase',
'frisbee',
'skis',
'snowboard',
'sports_ball',
'kite',
'baseball_bat',
'baseball_glove',
'skateboard',
'surfboard',
'tennis_racket',
'bottle',
'wine_glass',
'cup',
'fork',
'knife',
'spoon',
'bowl',
'banana',
'apple',
'sandwich',
'orange',
'broccoli',
'carrot',
'hot_dog',
'pizza',
'donut',
'cake',
'chair',
'couch',
'potted_plant',
'bed',
'dining_table',
'toilet',
'tv',
'laptop',
'mouse',
'remote',
'keyboard',
'cell_phone',
'microwave',
'oven',
'toaster',
'sink',
'refrigerator',
'book',
'clock',
'vase',
'scissors',
'teddy_bear',
'hair_drier',
'toothbrush'),
'_modules': OrderedDict([('backbone', ResNet(
# 모듈은 pytorch, backbone : resnet
'cfg': Config (path: configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py)
#print(model.cfg) # 안이쁘게 나옴
print(model.cfg.pretty_text)
model = dict(
type='FasterRCNN',
backbone=dict(
type='ResNet',
depth=50,
num_stages=4,
out_indices=(0, 1, 2, 3),
frozen_stages=1,
norm_cfg=dict(type='BN', requires_grad=True),
norm_eval=True,
style='pytorch',
init_cfg=dict(type='Pretrained', checkpoint='torchvision://resnet50')),
neck=dict(
type='FPN',
in_channels=[256, 512, 1024, 2048],
out_channels=256,
num_outs=5),
rpn_head=dict(
type='RPNHead',
in_channels=256,
feat_channels=256,
anchor_generator=dict(
type='AnchorGenerator',
scales=[8],
ratios=[0.5, 1.0, 2.0],
strides=[4, 8, 16, 32, 64]),
bbox_coder=dict(
type='DeltaXYWHBBoxCoder',
target_means=[0.0, 0.0, 0.0, 0.0],
target_stds=[1.0, 1.0, 1.0, 1.0]),
loss_cls=dict(
type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),
loss_bbox=dict(type='L1Loss', loss_weight=1.0)),
roi_head=dict(
type='StandardRoIHead',
bbox_roi_extractor=dict(
type='SingleRoIExtractor',
roi_layer=dict(type='RoIAlign', output_size=7, sampling_ratio=0),
out_channels=256,
featmap_strides=[4, 8, 16, 32]),
bbox_head=dict(
type='Shared2FCBBoxHead',
in_channels=256,
fc_out_channels=1024,
roi_feat_size=7,
num_classes=80,
bbox_coder=dict(
type='DeltaXYWHBBoxCoder',
target_means=[0.0, 0.0, 0.0, 0.0],
target_stds=[0.1, 0.1, 0.2, 0.2]),
reg_class_agnostic=False,
loss_cls=dict(
type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),
loss_bbox=dict(type='L1Loss', loss_weight=1.0)),
train_cfg=None,
test_cfg=dict(
score_thr=0.05,
nms=dict(type='nms', iou_threshold=0.5),
max_per_img=100),
pretrained=None),
train_cfg=None,
test_cfg=dict(
rpn=dict(
nms_pre=1000,
max_per_img=1000,
nms=dict(type='nms', iou_threshold=0.7),
min_bbox_size=0),
rcnn=dict(
score_thr=0.05,
nms=dict(type='nms', iou_threshold=0.5),
max_per_img=100)),
pretrained=None)
dataset_type = 'CocoDataset'
data_root = 'data/coco/'
img_norm_cfg = dict(
mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
train_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='LoadAnnotations', with_bbox=True),
dict(type='Resize', img_scale=(1333, 800), keep_ratio=True),
dict(type='RandomFlip', flip_ratio=0.5),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='Pad', size_divisor=32),
dict(type='DefaultFormatBundle'),
dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])
]
test_pipeline = [
dict(type='LoadImageFromFile'),
dict(
type='MultiScaleFlipAug',
img_scale=(1333, 800),
flip=False,
transforms=[
dict(type='Resize', keep_ratio=True),
dict(type='RandomFlip'),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='Pad', size_divisor=32),
dict(type='ImageToTensor', keys=['img']),
dict(type='Collect', keys=['img'])
])
]
data = dict(
samples_per_gpu=2,
workers_per_gpu=2,
train=dict(
type='CocoDataset',
ann_file='data/coco/annotations/instances_train2017.json',
img_prefix='data/coco/train2017/',
pipeline=[
dict(type='LoadImageFromFile'),
dict(type='LoadAnnotations', with_bbox=True),
dict(type='Resize', img_scale=(1333, 800), keep_ratio=True),
dict(type='RandomFlip', flip_ratio=0.5),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='Pad', size_divisor=32),
dict(type='DefaultFormatBundle'),
dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])
]),
val=dict(
type='CocoDataset',
ann_file='data/coco/annotations/instances_val2017.json',
img_prefix='data/coco/val2017/',
pipeline=[
dict(type='LoadImageFromFile'),
dict(
type='MultiScaleFlipAug',
img_scale=(1333, 800),
flip=False,
transforms=[
dict(type='Resize', keep_ratio=True),
dict(type='RandomFlip'),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='Pad', size_divisor=32),
dict(type='ImageToTensor', keys=['img']),
dict(type='Collect', keys=['img'])
])
]),
test=dict(
type='CocoDataset',
ann_file='data/coco/annotations/instances_val2017.json',
img_prefix='data/coco/val2017/',
pipeline=[
dict(type='LoadImageFromFile'),
dict(
type='MultiScaleFlipAug',
img_scale=(1333, 800),
flip=False,
transforms=[
dict(type='Resize', keep_ratio=True),
dict(type='RandomFlip'),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='Pad', size_divisor=32),
dict(type='DefaultFormatBundle'),
dict(type='Collect', keys=['img'])
])
]))
evaluation = dict(interval=1, metric='bbox')
optimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001)
optimizer_config = dict(grad_clip=None)
lr_config = dict(
policy='step',
warmup='linear',
warmup_iters=500,
warmup_ratio=0.001,
step=[8, 11])
runner = dict(type='EpochBasedRunner', max_epochs=12)
checkpoint_config = dict(interval=1)
log_config = dict(interval=50, hooks=[dict(type='TextLoggerHook')])
custom_hooks = [dict(type='NumClassCheckHook')]
dist_params = dict(backend='nccl')
log_level = 'INFO'
load_from = None
resume_from = None
workflow = [('train', 1)]
import cv2
# RGB가 아닌 BGR로 입력
img_arr = cv2.imread('/content/mmdetection/demo/demo.jpg')
results = inference_detector(model, img_arr)
show_result_pyplot(model, img_arr, results)
# 0부터 순차적으로 클래스 매핑된 label 적용.
labels_to_names_seq = {0:'person',1:'bicycle',2:'car',3:'motorbike',4:'aeroplane',5:'bus',6:'train',7:'truck',8:'boat',9:'traffic light',10:'fire hydrant',
11:'stop sign',12:'parking meter',13:'bench',14:'bird',15:'cat',16:'dog',17:'horse',18:'sheep',19:'cow',20:'elephant',
21:'bear',22:'zebra',23:'giraffe',24:'backpack',25:'umbrella',26:'handbag',27:'tie',28:'suitcase',29:'frisbee',30:'skis',
31:'snowboard',32:'sports ball',33:'kite',34:'baseball bat',35:'baseball glove',36:'skateboard',37:'surfboard',38:'tennis racket',39:'bottle',40:'wine glass',
41:'cup',42:'fork',43:'knife',44:'spoon',45:'bowl',46:'banana',47:'apple',48:'sandwich',49:'orange',50:'broccoli',
51:'carrot',52:'hot dog',53:'pizza',54:'donut',55:'cake',56:'chair',57:'sofa',58:'pottedplant',59:'bed',60:'diningtable',
61:'toilet',62:'tvmonitor',63:'laptop',64:'mouse',65:'remote',66:'keyboard',67:'cell phone',68:'microwave',69:'oven',70:'toaster',
71:'sink',72:'refrigerator',73:'book',74:'clock',75:'vase',76:'scissors',77:'teddy bear',78:'hair drier',79:'toothbrush' }
labels_to_names = {1:'person',2:'bicycle',3:'car',4:'motorcycle',5:'airplane',6:'bus',7:'train',8:'truck',9:'boat',10:'traffic light',
11:'fire hydrant',12:'street sign',13:'stop sign',14:'parking meter',15:'bench',16:'bird',17:'cat',18:'dog',19:'horse',20:'sheep',
21:'cow',22:'elephant',23:'bear',24:'zebra',25:'giraffe',26:'hat',27:'backpack',28:'umbrella',29:'shoe',30:'eye glasses',
31:'handbag',32:'tie',33:'suitcase',34:'frisbee',35:'skis',36:'snowboard',37:'sports ball',38:'kite',39:'baseball bat',40:'baseball glove',
41:'skateboard',42:'surfboard',43:'tennis racket',44:'bottle',45:'plate',46:'wine glass',47:'cup',48:'fork',49:'knife',50:'spoon',
51:'bowl',52:'banana',53:'apple',54:'sandwich',55:'orange',56:'broccoli',57:'carrot',58:'hot dog',59:'pizza',60:'donut',
61:'cake',62:'chair',63:'couch',64:'potted plant',65:'bed',66:'mirror',67:'dining table',68:'window',69:'desk',70:'toilet',
71:'door',72:'tv',73:'laptop',74:'mouse',75:'remote',76:'keyboard',77:'cell phone',78:'microwave',79:'oven',80:'toaster',
81:'sink',82:'refrigerator',83:'blender',84:'book',85:'clock',86:'vase',87:'scissors',88:'teddy bear',89:'hair drier',90:'toothbrush',
91:'hair brush'}
import numpy as np
# np.where 사용법 예시.
arr1 = np.array([[3.75348572e+02, 1.19171005e+02, 3.81950867e+02, 1.34460617e+02,
1.35454759e-01],
[5.32362000e+02, 1.09554726e+02, 5.40526550e+02, 1.25222633e+02,
8.88786465e-01],
[3.61124298e+02, 1.09049202e+02, 3.68625610e+02, 1.22483063e+02,
7.20717013e-02]], dtype=np.float32)
print(arr1.shape)
arr1_filtered = arr1[np.where(arr1[:, 4] > 0.1)] # 0.1 보다 큰것만 저장
print('### arr1_filtered:', arr1_filtered, arr1_filtered.shape)
(3, 5) # 2차원으로
### arr1_filtered: [[3.75348572e+02 1.19171005e+02 3.81950867e+02 1.34460617e+02
1.35454759e-01]
[5.32362000e+02 1.09554726e+02 5.40526550e+02 1.25222633e+02
8.88786495e-01]] (2, 5)
np.where(arr1[:, 4] > 0.1) # row는 전부, 4:class confidence 가 0.1보다 큰 경우
# (array([0, 1]),)
# row 기준으로
# model과 원본 이미지 array, filtering할 기준 class confidence score를 인자로 가지는 inference 시각화용 함수 생성.
def get_detected_img(model, img_array, score_threshold=0.3, is_print=True):
# 인자로 들어온 image_array를 복사.
draw_img = img_array.copy()
bbox_color=(0, 255, 0)
text_color=(0, 0, 255)
# model과 image array를 입력 인자로 inference detection 수행하고 결과를 results로 받음.
# results는 80개의 2차원 array(shape=(오브젝트갯수, 5))를 가지는 list.
results = inference_detector(model, img_array)
# 80개의 array원소를 가지는 results 리스트를 loop를 돌면서 개별 2차원 array들을 추출하고 이를 기반으로 이미지 시각화
# results 리스트의 위치 index가 바로 COCO 매핑된 Class id. 여기서는 result_ind가 class id
# 개별 2차원 array에 오브젝트별 좌표와 class confidence score 값을 가짐.
for result_ind, result in enumerate(results):
# 개별 2차원 array의 row size가 0 이면 해당 Class id로 값이 없으므로 다음 loop로 진행.
if len(result) == 0:
continue
# 2차원 array에서 5번째 컬럼에 해당하는 값이 score threshold이며 이 값이 함수 인자로 들어온 score_threshold 보다 낮은 경우는 제외.
result_filtered = result[np.where(result[:, 4] > score_threshold)]
# 해당 클래스 별로 Detect된 여러개의 오브젝트 정보가 2차원 array에 담겨 있으며, 이 2차원 array를 row수만큼 iteration해서 개별 오브젝트의 좌표값 추출.
for i in range(len(result_filtered)):
# 좌상단, 우하단 좌표 추출.
left = int(result_filtered[i, 0])
top = int(result_filtered[i, 1])
right = int(result_filtered[i, 2])
bottom = int(result_filtered[i, 3])
caption = "{}: {:.4f}".format(labels_to_names_seq[result_ind], result_filtered[i, 4])
cv2.rectangle(draw_img, (left, top), (right, bottom), color=bbox_color, thickness=2)
cv2.putText(draw_img, caption, (int(left), int(top - 7)), cv2.FONT_HERSHEY_SIMPLEX, 0.37, text_color, 1)
if is_print:
print(caption)
return draw_img
import matplotlib.pyplot as plt
img_arr = cv2.imread('/content/mmdetection/demo/demo.jpg')
detected_img = get_detected_img(model, img_arr, score_threshold=0.3, is_print=True)
# detect 입력된 이미지는 bgr임. 이를 최종 출력시 rgb로 변환
detected_img = cv2.cvtColor(detected_img, cv2.COLOR_BGR2RGB)
plt.figure(figsize=(12, 12))
plt.imshow(detected_img)
/usr/local/lib/python3.7/dist-packages/mmdet-2.17.0-py3.7.egg/mmdet/core/anchor/anchor_generator.py:324: UserWarning: ``grid_anchors`` would be deprecated soon. Please use ``grid_priors``
warnings.warn('``grid_anchors`` would be deprecated soon. '
car: 0.9888
car: 0.9872
car: 0.9832
car: 0.9713
car: 0.9678
car: 0.9594
car: 0.9593
car: 0.9568
car: 0.9510
car: 0.9458
car: 0.9440
car: 0.9331
car: 0.8663
car: 0.8268
car: 0.7535
car: 0.7166
car: 0.6008
car: 0.5920
car: 0.5540
car: 0.5435
car: 0.4768
car: 0.4612
car: 0.4010
car: 0.3439
bench: 0.9778
bench: 0.4170
chair: 0.7779
/usr/local/lib/python3.7/dist-packages/mmdet-2.17.0-py3.7.egg/mmdet/core/anchor/anchor_generator.py:361: UserWarning: ``single_level_grid_anchors`` would be deprecated soon. Please use ``single_level_grid_priors``
'``single_level_grid_anchors`` would be deprecated soon. '
<matplotlib.image.AxesImage at 0x7f7f78bc4a50>
!mkdir data
!wget -O /content/data/beatles01.jpg https://raw.githubusercontent.com/chulminkw/DLCV/master/data/image/beatles01.jpg
!ls -lia /content/data/beatles01.jpg
img_arr = cv2.imread('/content/data/beatles01.jpg')
detected_img = get_detected_img(model, img_arr, score_threshold=0.5, is_print=True)
# detect 입력된 이미지는 bgr임. 이를 최종 출력시 rgb로 변환
detected_img = cv2.cvtColor(detected_img, cv2.COLOR_BGR2RGB)
plt.figure(figsize=(12, 12))
plt.imshow(detected_img)
/usr/local/lib/python3.7/dist-packages/mmdet-2.17.0-py3.7.egg/mmdet/core/anchor/anchor_generator.py:324: UserWarning: ``grid_anchors`` would be deprecated soon. Please use ``grid_priors``
warnings.warn('``grid_anchors`` would be deprecated soon. '
person: 0.9988
person: 0.9982
person: 0.9980
person: 0.9971
person: 0.9604
car: 0.9693
car: 0.9686
car: 0.9648
car: 0.9517
car: 0.9254
car: 0.9030
car: 0.8312
car: 0.8008
car: 0.7331
car: 0.6208
tie: 0.5924
/usr/local/lib/python3.7/dist-packages/mmdet-2.17.0-py3.7.egg/mmdet/core/anchor/anchor_generator.py:361: UserWarning: ``single_level_grid_anchors`` would be deprecated soon. Please use ``single_level_grid_priors``
'``single_level_grid_anchors`` would be deprecated soon. '
<matplotlib.image.AxesImage at 0x7f7f78bf2e50>
4-7. tiny kitti - dataset (0) | 2021.10.11 |
---|---|
4-6. faster-rcnn pretrained model로 video inference 실행 (0) | 2021.10.10 |
4-1~2. pytorch 기반 주요 object detection / segmentation 패키지 (0) | 2021.09.28 |
3-13. 모던 object Detection 모델 아키텍처 (0) | 2021.09.27 |
3-12. Video inference (0) | 2021.09.27 |
1998 - LeNet 5
2012 - AlexNet
- Gradient vanishin문제를 해결하는 ReLU를 사용 - LRN 사용 안했음
- Overlapping Pooling(영향력이 크진 않음)
- Dropout(Overfitting 방지)
2013 - ZFNet
- AlexNet을 Visualization통해 insight를 제공
- HyperParameter tuning 방법론 제시
- Network in Network
- 1x1 Convolution 도입 (1. 차원 조절 2. non-linear 특성 부여 3. fully connected 처럼 사용)
- Flatten 대신 사용하는 방법인 Global Average Pooling 도입
- 같은 형태를 반복하고 겹쳐서 사용하는 Stacking 도입
2014 - GoogLeNet v1 (1등)
- 1x1 convolution 활용
- Inception module stacking
- Global average pooling 활용
- VGG (2등)
2016 - GoogLeNet v4
ReLU와 같은 기법 덕에 Layer를 깊게 쌓을 수 있는 확신이 있었던 배경 때문에 Layer를 어떻게 깊게 쌓는지 여부가 중요한 포인트였다
1. 1x1 convolution
- 차원 축소 효과
- nonlinearity 특징 부여
2. Inception module
- 9개 inception module로 구성되어 있다
- Inception moddule은 Hebbian rule에 의해 영향력이 가장 큰 부분이 연결성이 강화된다(weight가 커진다)
- 실제 구현에서는 차원을 조절하여 inception module을 적용하였다
3. Global average pooling
4. Auxiliary classifier
- relu로 gradient vanishing 문제를 해결한듯 했으나 layer가 기존에 8 layer였던것에 비해 22 layer로 급격하게 늘었기 때문에 gradient vanishing 가능성이 생겼다
- 따라서 네트워크 중간에 auxiliary classifier를 추가하여 중간 중간 결과를 낸다
import tensorflow as tf
(X_train, y_train), (X_test, y_test) = tf.keras.datasets.cifar10.load_data()
# Inception module, naive version
input_ = tf.keras.Input((32,32,3))
conv1x1 = tf.keras.layers.Conv2D(3,1, padding='same', name='1x1')(input_)
conv3x3 = tf.keras.layers.Conv2D(3,3, padding='same', name='3x3')(input_)
conv5x5 = tf.keras.layers.Conv2D(3,3, padding='same', name='5x5')(input_)
maxpool = tf.keras.layers.MaxPool2D(3,1, padding='same', name='pool')(input_) # unoverlapping
concatenate = tf.keras.layers.Concatenate()([conv1x1,conv3x3,conv5x5,maxpool]) # 합치기 위해서 구조를 맞추어야 한다
model = tf.keras.models.Model(input_, concatenate)
model.summary()
# Model: "model_13"
# __________________________________________________________________________________________________
# Layer (type) Output Shape Param # Connected to
# ==================================================================================================
# input_24 (InputLayer) [(None, 32, 32, 3)] 0
# __________________________________________________________________________________________________
# 1x1 (Conv2D) (None, 32, 32, 3) 12 input_24[0][0]
# __________________________________________________________________________________________________
# 3x3 (Conv2D) (None, 32, 32, 3) 84 input_24[0][0]
# __________________________________________________________________________________________________
# 5x5 (Conv2D) (None, 32, 32, 3) 84 input_24[0][0]
# __________________________________________________________________________________________________
# pool (MaxPooling2D) (None, 32, 32, 3) 0 input_24[0][0]
# __________________________________________________________________________________________________
# concatenate_15 (Concatenate) (None, 32, 32, 12) 0 1x1[0][0]
# 3x3[0][0]
# 5x5[0][0]
# pool[0][0]
# ==================================================================================================
# Total params: 180
# Trainable params: 180
# Non-trainable params: 0
# __________________________________________________________________________________________________
tf.keras.utils.plot_model(model, show_shapes=True)
# Inception module with dimension reductions
input_ = tf.keras.Input((32,32,3))
conv1x1 = tf.keras.layers.Conv2D(3,1, padding='same', name='1x1')(input_)
conv1x1_reduc3x3 = tf.keras.layers.Conv2D(2,1, padding='same', name='1x1_3x3')(input_)
conv3x3 = tf.keras.layers.Conv2D(2,3, padding='same', name='3x3')(conv1x1_reduc3x3)
conv1x1_reduc5x5 = tf.keras.layers.Conv2D(2,1, padding='same', name='1x1_5x5')(input_)
conv5x5 = tf.keras.layers.Conv2D(2,3, padding='same', name='5x5')(conv1x1_reduc5x5)
maxpool = tf.keras.layers.MaxPool2D(2,1, padding='same', name='pool')(input_)
conv1x1_reduc_mp = tf.keras.layers.Conv2D(2,1, padding='same', name='1x1_pool')(maxpool)
concatenate = tf.keras.layers.Concatenate(axis=-1)([conv1x1,conv3x3,conv5x5,conv1x1_reduc_mp]) # 합치기 위해서 구조를 맞추어야 한다
# concatenate = tf.keras.layers.Concatenate([conv1x1,conv3x3,conv5x5,conv1x1_reduc_mp]) # 옵션을 주지 않을때
model = tf.keras.models.Model(input_, concatenate)
model.summary()
# Model: "model_14"
# __________________________________________________________________________________________________
# Layer (type) Output Shape Param # Connected to
# ==================================================================================================
# input_25 (InputLayer) [(None, 32, 32, 3)] 0
# __________________________________________________________________________________________________
# 1x1_3x3 (Conv2D) (None, 32, 32, 2) 8 input_25[0][0]
# __________________________________________________________________________________________________
# 1x1_5x5 (Conv2D) (None, 32, 32, 2) 8 input_25[0][0]
# __________________________________________________________________________________________________
# pool (MaxPooling2D) (None, 32, 32, 3) 0 input_25[0][0]
# __________________________________________________________________________________________________
# 1x1 (Conv2D) (None, 32, 32, 3) 12 input_25[0][0]
# __________________________________________________________________________________________________
# 3x3 (Conv2D) (None, 32, 32, 2) 38 1x1_3x3[0][0]
# __________________________________________________________________________________________________
# 5x5 (Conv2D) (None, 32, 32, 2) 38 1x1_5x5[0][0]
# __________________________________________________________________________________________________
# 1x1_pool (Conv2D) (None, 32, 32, 2) 8 pool[0][0]
# __________________________________________________________________________________________________
# concatenate_16 (Concatenate) (None, 32, 32, 9) 0 1x1[0][0]
# 3x3[0][0]
# 5x5[0][0]
# 1x1_pool[0][0]
# ==================================================================================================
# Total params: 112
# Trainable params: 112
# Non-trainable params: 0
# __________________________________________________________________________________________________
tf.keras.utils.plot_model(model, show_shapes=True, rankdir="BT", show_dtype=True) # wide하게 분포되어 있기 때문에 parameter operator가 엄청 많다 / 이중에서 영향력 있는 것만 강한 연결성을 띄게 된다
in3 = tf.keras.applications.InceptionV3()
tf.keras.utils.plot_model(in3)
Very Deep Convolutional Networks for large-scale image recognition
Layer가 깊어지면 깊어질 수 록 성능이 좋아진다
Abliation study 방식으로 모델 성능을 비교한다
1. AlexNet vs AlexNet + LRN
- LRN 기법은 성능 개선은 없고 메모리 사용량 및 연산 시간만 늘어났기에 사용을 하지 않는다
2. AlexNet vs AlexNet + conv layer 2개 추가
- 성능 좋아짐
3. AlexNet + conv layer 2개 vs AlexNet + conv layer 2개 + 1x1 convolution 3개
- Nonlinearity만 추가 시켜 성능향상을 하는지 확인 => activation이 더 많아서 성능 더 좋아짐 (UAT)
4. AlexNet + conv layer 2개 + 1x1 convolution 3개 vs AlexNet + conv layer 5개
- 성능 좋아짐
5. AlexNet + conv layer 5개 vs AlexNet + conv layer 8개
- 성능 좋아짐
결국 Layer가 늘어나면 늘어날 수록 성능이 좋아졌다
model을 불러와 사용하는 두 가지 방식
1. applications => Computer vision 분야에서 지원되는 모델을 지원한다
2. tensorflow hub
import tensorflow as tf
vgg16 = tf.keras.applications.VGG16() # ImageNet 대회서 2등, 학습된 모델을 그대로 사용할 수 있다
vgg16.summary()
# Model: "vgg16"
# _________________________________________________________________
# Layer (type) Output Shape Param #
# =================================================================
# input_2 (InputLayer) [(None, 224, 224, 3)] 0
# _________________________________________________________________
# block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
# _________________________________________________________________
# block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
# _________________________________________________________________
# block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
# _________________________________________________________________
# block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
# _________________________________________________________________
# block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
# _________________________________________________________________
# block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
# _________________________________________________________________
# block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
# _________________________________________________________________
# block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
# _________________________________________________________________
# block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
# _________________________________________________________________
# block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
# _________________________________________________________________
# block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
# _________________________________________________________________
# block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
# _________________________________________________________________
# block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
# _________________________________________________________________
# block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
# _________________________________________________________________
# block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
# _________________________________________________________________
# block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
# _________________________________________________________________
# block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
# _________________________________________________________________
# block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
# _________________________________________________________________
# flatten (Flatten) (None, 25088) 0
# _________________________________________________________________
# fc1 (Dense) (None, 4096) 102764544
# _________________________________________________________________
# fc2 (Dense) (None, 4096) 16781312
# _________________________________________________________________
# predictions (Dense) (None, 1000) 4097000
# =================================================================
# Total params: 138,357,544
# Trainable params: 138,357,544
# Non-trainable params: 0
# _________________________________________________________________
vgg16.weights
vgg16.__class__
# keras.engine.functional.Functional
(X_train, y_train), (X_test, y_test) = tf.keras.datasets.cifar10.load_data()
input_ = tf.keras.Input((32,32,3))
x = tf.keras.layers.Conv2D(2,5)(input_) # filter 2개 5x5
model = tf.keras.models.Model(input_, x)
model.summary()
# Model: "model"
# _________________________________________________________________
# Layer (type) Output Shape Param #
# =================================================================
# input_4 (InputLayer) [(None, 32, 32, 3)] 0
# _________________________________________________________________
# conv2d (Conv2D) (None, 28, 28, 2) 152
# =================================================================
# Total params: 152
# Trainable params: 152
# Non-trainable params: 0
# _________________________________________________________________
input_ = tf.keras.Input((32,32,3))
x = tf.keras.layers.Conv2D(2,3)(input_)
x = tf.keras.layers.Conv2D(2,3)(x)
model = tf.keras.models.Model(input_, x)
model.summary() # 3x3이 더 좋다 / 5x5일 때와 shape은 같지만 activation을 여러개 사용했고 파라미터 수가 줄어들었기 때문에 성능이 더 좋아졌다
# Model: "model_15"
# _________________________________________________________________
# Layer (type) Output Shape Param #
# =================================================================
# input_27 (InputLayer) [(None, 32, 32, 3)] 0
# _________________________________________________________________
# conv2d_221 (Conv2D) (None, 30, 30, 2) 56
# _________________________________________________________________
# conv2d_222 (Conv2D) (None, 28, 28, 2) 38
# =================================================================
# Total params: 94
# Trainable params: 94
# Non-trainable params: 0
# _________________________________________________________________
input_ = tf.keras.Input((32,32,3))
x = tf.keras.layers.Conv2D(2,3)(input_)
x = tf.keras.layers.Conv2D(2,3)(x)
x = tf.keras.layers.Conv2D(2,3)(x)
model = tf.keras.models.Model(input_, x)
model.summary() # 3x3으로 더 큰 receptive field를 대체 할 수 있다
# Model: "model_24"
# _________________________________________________________________
# Layer (type) Output Shape Param #
# =================================================================
# input_36 (InputLayer) [(None, 32, 32, 3)] 0
# _________________________________________________________________
# conv2d_243 (Conv2D) (None, 30, 30, 2) 56
# _________________________________________________________________
# conv2d_244 (Conv2D) (None, 28, 28, 2) 38
# _________________________________________________________________
# conv2d_245 (Conv2D) (None, 26, 26, 2) 38
# =================================================================
# Total params: 132
# Trainable params: 132
# Non-trainable params: 0
# _________________________________________________________________
보통 첫번째 layer는 5x5 또는 7x7 filter를 사용하고
(처음부터 3x3을 사용하면 메모리를 너무 많이차지 하기 때문에 오히려 성능 저하가 될 수 있다)
그 다음 layer 부터는 3x3을 사용하면 성능이 좋다
ResNet은 인간을 뛰어넘은 첫번째 모델
Residual => 실제값 - 예측값 (잔차)
layer가 56개로 깊어지면서 gradient vanishing문제가 다시 떠오르기 시작했다
(relu로 해결되지 못하는 문제가 발생) underfitting
처음에 학습했던 것들을 점차 잊게되면서 목표로 부터 멀어지게 되는 현상이 생겼다
그래서 해결책으로 Short cut 즉, residual block을 도입하게 되었다
LSTM에서 아이디어를 얻어 자신의 값을 더함으로써 값을 유지시키고 목표를 잃지 않고 지속적으로 학습하게 된다
기존의 신경망은 입력값 x를 타겟값 y로 매핑하는 함수 H(x)를 얻는 것이 목적이었다.
그러나 ResNet은 F(x) + x를 최소화하는 것을 목적으로 한다.
x는 현시점에서 변할 수 없는 값이므로 F(x)를 0에 가깝게 만드는 것이 목적이 된다.
F(x)가 0이 되면 출력과 입력이 모두 x로 같아지게 된다.
F(x) = H(x) - x이므로 F(x)를 최소로 해준다는 것은 H(x) - x를 최소로 해주는 것과 동일한 의미를 지닌다.
여기서 H(x) - x를 잔차(residual)라고 한다.
즉, 잔차를 최소로 해주는 것이므로 ResNet이란 이름이 붙게 된다.
Batch Normalization 사용 => underfitting을 막아주면서 dropout을 사용하지 않고 좋은 성능을 얻게 되었다
vgg19와 34-layer plain을 비교했을 때 34-layer는 가장 앞 layer에서 7x7 filter를 적용했고 레이어 수를 두 배 가까이 늘렸다
그리고 맨마지막에 flatten을 쓰지 않고 average pooling을 사용했더니 34-layer가 성능이 더 좋았다
더 나아가 34-layer에서 residual block을 추가한 결과 추가하지 않은 것보다 오차율이 감소한 것을 확인할 수 있었다
Residual block과 Batch Normalization의 조합으로 훨씬 더 깊은 layer가 가능해졌다
결국 총 152 layer를 쌓을 수 있게 되었다
22일차 - 논문 수업 (Learning Technique / numerical stability) (0) | 2021.10.15 |
---|---|
21일차 - 논문 수업 (CNN / Data Augmentation) (0) | 2021.10.15 |
19일차 - 논문 수업 (CNN) (0) | 2021.10.08 |
18일차 - 논문 수업 (CNN) (0) | 2021.10.08 |
17일차 - 논문 수업 (CNN) (0) | 2021.10.04 |
CNN을 제대로 이해하기 위한 논문
CNN을 시각화 하여 왜 성능이 향상되었는지를 탐구하는 논문
과거의 관점으로 AlexNet에 대한 '통찰'과 '진단'을 제공한다
Convolutional layer를 통과하고나서 Max pooling을 거칠때 가장 영향력 있는 값들로 축약되기 때문에 큰 특징만 남게 된다
따라서 반대로 pooling을 거치기 전으로 복원시킨다면 큰 특징만 남아 있기 때문에 Detail한 특징들은 사라지게 될 것이다
AlexNet의 네트워크 구조대로 통과시킨 데이터들을 각 레이어 별로 복원시키게 되면
가장 중요한 특징들만 남도록 복원된다는 것을 시각적으로 확인 할 수 있다
시각화된 결과를 보면 AlexNet의 구조는 처음 레이어에서 간단한 특징들을 뽑아내다가
레이어가 깊어지면 깊어질 수록 '복잡한 특징'을 구분할 수 있도록 학습이 되는 것을 알 수 있다
기존 AlexNet의 첫번째 Layer에서 filter 11x11, stride 4를 filter 7x7, stride 2로 바꾸었다
두번째 layer에서는 stride 1, zero-padding 2에서 stride 2로 바꾸었다
=> 기존에는 filter가 컸기 때문에 작은 것들의 특징을 잘 못잡는다는 문제가 있었다
결과 => 파라미터가 줄어들었고, 좀 더 디테일한 특징을 알아낼 수 있도록 학습하게되었다
receptive field를 대신할 수 있다 @@@ 의미 확인
일부분을 가림으로써 어떤 부분이 가장 영향력이 있는지를 확률적으로 계산하였다 (abliation study)
특정 부분을 가렸을 때 가장 성능이 안좋다면 그 부분은 가장 영향력이 있는 부분인 것이다 (파란색 부분이 가장 영향력 있는 부분)
a와 c는 AlexNet b와 d는 ZFNet
Layer 1
a 그림에서는 dead feature가 꽤 있고 좀 더 흐릿하게 구분된 반면
c 그림에서는 dead feature가 굉장히 많이 줄고 특징이 좀 더 선명하게 구분되었다
filter사이즈와 stride를 줄임으로써 좀 더 특징을 잘 구분할 수 있게 학습이되었다고 할 수 있다
Layer 2
c 그림에서 보면 빈 공간이 많고 aliasing(계단현상)이 발견된 반면
d 그림에서는 빈 공간이 적고 특징이 더 선명하게 잘 구분되도록 학습이 되었다
네트워크 안에 네트워크를 넣는 방식
convolution layer사이에 mlp가 있다 (사실상 1x1 convolution을 사용한 것)
import tensorflow as tf
(X_train, y_train), (X_test, y_test) = tf.keras.datasets.mnist.load_data()
X_train = X_train.reshape(-1,28,28,1)/255
# AlexNet
input_ = tf.keras.Input((224,224,3))
x = tf.keras.layers.Conv2D(96,11,4)(input_)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Conv2D(256, 5, padding='same')(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.MaxPool2D(3,2)(x)
x = tf.keras.layers.Conv2D(384,3)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.MaxPool2D(3,2)(x)
x = tf.keras.layers.Conv2D(384,3)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Conv2D(256, 3)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.MaxPool2D(3,2)(x)
x = tf.keras.layers.Flatten()(x) # 일렬로 만들어 지기 때문에 위치 정보를 잃고 학습할 weight가 많이 생긴다 (FC만 썼을때 위치정보를 잃는다)
x = tf.keras.layers.Dense(4096)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Dropout(0.5)(x)
x = tf.keras.layers.Dense(4096, kernel_initializer=tf.keras.initializers.Constant(1))(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Dropout(0.5)(x)
x = tf.keras.layers.Dense(1000, activation='softmax')(x)
model = tf.keras.models.Model(input_,x)
model.summary()
# Model: "model_1"
# _________________________________________________________________
# Layer (type) Output Shape Param #
# =================================================================
# input_2 (InputLayer) [(None, 224, 224, 3)] 0
# _________________________________________________________________
# conv2d_5 (Conv2D) (None, 54, 54, 96) 34944
# _________________________________________________________________
# re_lu_6 (ReLU) (None, 54, 54, 96) 0
# _________________________________________________________________
# conv2d_6 (Conv2D) (None, 54, 54, 256) 614656
# _________________________________________________________________
# re_lu_7 (ReLU) (None, 54, 54, 256) 0
# _________________________________________________________________
# max_pooling2d_2 (MaxPooling2 (None, 26, 26, 256) 0
# _________________________________________________________________
# conv2d_7 (Conv2D) (None, 24, 24, 384) 885120
# _________________________________________________________________
# re_lu_8 (ReLU) (None, 24, 24, 384) 0
# _________________________________________________________________
# max_pooling2d_3 (MaxPooling2 (None, 11, 11, 384) 0
# _________________________________________________________________
# conv2d_8 (Conv2D) (None, 9, 9, 384) 1327488
# _________________________________________________________________
# re_lu_9 (ReLU) (None, 9, 9, 384) 0
# _________________________________________________________________
# conv2d_9 (Conv2D) (None, 7, 7, 256) 884992
# _________________________________________________________________
# re_lu_10 (ReLU) (None, 7, 7, 256) 0
# _________________________________________________________________
# max_pooling2d_4 (MaxPooling2 (None, 3, 3, 256) 0
# _________________________________________________________________
# flatten_1 (Flatten) (None, 2304) 0
# _________________________________________________________________
# dense_3 (Dense) (None, 4096) 9441280
# _________________________________________________________________
# re_lu_11 (ReLU) (None, 4096) 0
# _________________________________________________________________
# dropout_2 (Dropout) (None, 4096) 0
# _________________________________________________________________
# dense_4 (Dense) (None, 4096) 16781312
# _________________________________________________________________
# re_lu_12 (ReLU) (None, 4096) 0
# _________________________________________________________________
# dropout_3 (Dropout) (None, 4096) 0
# _________________________________________________________________
# dense_5 (Dense) (None, 1000) 4097000
# =================================================================
# Total params: 34,066,792
# Trainable params: 34,066,792
# Non-trainable params: 0
# _________________________________________________________________
# AlexNet Flatten x / Global average pooling
input_ = tf.keras.Input((224,224,3))
x = tf.keras.layers.Conv2D(96,11,4)(input_)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Conv2D(256, 5, padding='same')(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.MaxPool2D(3,2)(x)
x = tf.keras.layers.Conv2D(384,3)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.MaxPool2D(3,2)(x)
x = tf.keras.layers.Conv2D(384,3)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Conv2D(256, 3)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.MaxPool2D(3,2)(x)
x = tf.keras.layers.Conv2D(1000, 3)(x) # 1x1 convolution
x = tf.keras.layers.GlobalAveragePooling2D()(x) # 1차원으로 바뀌었기 때문에 Flatten과 똑같다. 하지만 Flatten보다 Parameter를 훨씬 줄일 수 있다
x = tf.keras.layers.Dense(1000)(x)
model = tf.keras.models.Model(input_,x)
model.summary()
# Model: "model_6"
# _________________________________________________________________
# Layer (type) Output Shape Param #
# =================================================================
# input_8 (InputLayer) [(None, 224, 224, 3)] 0
# _________________________________________________________________
# conv2d_35 (Conv2D) (None, 54, 54, 96) 34944
# _________________________________________________________________
# re_lu_42 (ReLU) (None, 54, 54, 96) 0
# _________________________________________________________________
# conv2d_36 (Conv2D) (None, 54, 54, 256) 614656
# _________________________________________________________________
# re_lu_43 (ReLU) (None, 54, 54, 256) 0
# _________________________________________________________________
# max_pooling2d_20 (MaxPooling (None, 26, 26, 256) 0
# _________________________________________________________________
# conv2d_37 (Conv2D) (None, 24, 24, 384) 885120
# _________________________________________________________________
# re_lu_44 (ReLU) (None, 24, 24, 384) 0
# _________________________________________________________________
# max_pooling2d_21 (MaxPooling (None, 11, 11, 384) 0
# _________________________________________________________________
# conv2d_38 (Conv2D) (None, 9, 9, 384) 1327488
# _________________________________________________________________
# re_lu_45 (ReLU) (None, 9, 9, 384) 0
# _________________________________________________________________
# conv2d_39 (Conv2D) (None, 7, 7, 256) 884992
# _________________________________________________________________
# re_lu_46 (ReLU) (None, 7, 7, 256) 0
# _________________________________________________________________
# max_pooling2d_22 (MaxPooling (None, 3, 3, 256) 0
# _________________________________________________________________
# conv2d_40 (Conv2D) (None, 1, 1, 1000) 2305000
# _________________________________________________________________
# global_average_pooling2d_2 ( (None, 1000) 0
# _________________________________________________________________
# dense_13 (Dense) (None, 1000) 1001000
# =================================================================
# Total params: 7,053,200
# Trainable params: 7,053,200
# Non-trainable params: 0
# _________________________________________________________________
Flatten은 원본 데이터 그대로 1차원으로 변화 시키지만 GAP은 최종결과에서 평균을 내어 하나의 값으로 바꾸고 그 형태가 1차원으로 변화된다
GAP는 전체 값 중에서 noise나 outlier등 학습이 안된 것들을 뭉뚱그리기 때문에 오히려 성능이 향상 되는 경우가 있다
GAP는 전체를 반영하기 때문에 Flatten한 것 보다 값을 더 잘 반영 하는 경우가 있지만
weight가 줄어들기 때문에 하나의 관점보다 여러개의 관점으로 파악하는 경우가 성능이 좋은 경우가 있을 수 있다
따라서 경우에 따라서 결정해야 할 문제이다
Hyperparameter처럼 데이터에 따라서 직접 정해줘야 한다
Grouped Convolution은 입력 값의 채널들을 여러 개의 그룹으로 나누어 독립적으로 Convolution 연산을 수행하는 방식이다.
모델이 복잡할때 parameter를 줄이기 위해서 사용하는 경우가 있다
Point-wise Convolution
1. 1x1의 depth에 따라서 차원이 바뀐다
2. Non-linear 특징을 부여한다
3. Fully connected 처럼 사용한다
1. Network in Network (1x1 convolution)
2. Stacking
3. Global average pooling
GoogLeNet은 위 3가지 내용을 참고하여 만들어졌다
21일차 - 논문 수업 (CNN / Data Augmentation) (0) | 2021.10.15 |
---|---|
20일차 - 논문 수업 (CNN) (0) | 2021.10.08 |
18일차 - 논문 수업 (CNN) (0) | 2021.10.08 |
17일차 - 논문 수업 (CNN) (0) | 2021.10.04 |
16일차 - 논문 수업 (CNN) (0) | 2021.10.04 |
import tensorflow as tf
input_ = tf.keras.Input(shape=(32,32,1))
x = tf.keras.layers.Conv2D(6, 5, activation='tanh')(input_) # filter 개수, filter 크기 / stride는 생략되었기 때문에 1이라 가정한다 / padding: valid
x = tf.keras.layers.AvgPool2D(2)(x) # 기본적으로 non-overlapping 방식이다
x = tf.keras.layers.Conv2D(16, 5, activation='tanh')(x)
x = tf.keras.layers.MaxPool2D(6, 5)(x)
x = tf.keras.layers.Flatten()(x)
x = tf.keras.layers.Dense(120, activation='tanh')(x)
x = tf.keras.layers.Dense(84, activation='tanh')(x)
x = tf.keras.layers.Dense(10, activation='softmax')(x)
model = tf.keras.models.Model(input_, x)
# pooling 사용했을 때
model.summary()
# Model: "model_1"
# _________________________________________________________________
# Layer (type) Output Shape Param #
# =================================================================
# input_3 (InputLayer) [(None, 32, 32, 1)] 0
# _________________________________________________________________
# conv2d_1 (Conv2D) (None, 28, 28, 6) 156
# _________________________________________________________________
# average_pooling2d (AveragePo (None, 14, 14, 6) 0
# _________________________________________________________________
# conv2d_2 (Conv2D) (None, 10, 10, 16) 2416
# _________________________________________________________________
# max_pooling2d (MaxPooling2D) (None, 1, 1, 16) 0
# _________________________________________________________________
# flatten (Flatten) (None, 16) 0
# _________________________________________________________________
# dense (Dense) (None, 120) 2040
# _________________________________________________________________
# dense_1 (Dense) (None, 84) 10164
# _________________________________________________________________
# dense_2 (Dense) (None, 10) 850
# =================================================================
# Total params: 15,626
# Trainable params: 15,626
# Non-trainable params: 0
# _________________________________________________________________
# pooling 사용하지 않았을 때
model.summary()
# Model: "model_3"
# _________________________________________________________________
# Layer (type) Output Shape Param #
# =================================================================
# input_5 (InputLayer) [(None, 32, 32, 1)] 0
# _________________________________________________________________
# conv2d_5 (Conv2D) (None, 28, 28, 6) 156
# _________________________________________________________________
# conv2d_6 (Conv2D) (None, 24, 24, 16) 2416
# _________________________________________________________________
# flatten_2 (Flatten) (None, 9216) 0
# _________________________________________________________________
# dense_6 (Dense) (None, 120) 1106040
# _________________________________________________________________
# dense_7 (Dense) (None, 84) 10164
# _________________________________________________________________
# dense_8 (Dense) (None, 10) 850
# =================================================================
# Total params: 1,119,626
# Trainable params: 1,119,626
# Non-trainable params: 0
# _________________________________________________________________
ImageNet LSVRC 대회에서 ImageNet 데이터를 사용한 CNN
ReLU는 Sigmoid와 tanh가 갖는 Gradient Vanishing 문제를 해결하기 위한 함수이다
ReLU는 sigmoid, tanh 함수보다 학습이 빠르고, 연산 비용이 적고, 구현이 매우 간단하다
Dying relu는 모든 0이하의 입력에 대해서 미분 값이 0이 되어 가중치에 곱해지면서 해당 노드가 통째로 죽어버리는 현상을 말한다
이러한 단점을 보완한 reaky relu가 있다
layer가 깊어질 수록 값의 범위가 매번 바뀌고 최소값으로 수렴이 안되는 underfitting이 발생한다
이런 경우를 방지하기 위해서 값의 범위를 일정하게 맞춰주는 방법이 바로 normalization이다
대표적인 정규화 방법 두 가지
1. Min-Max Normalization (최소-최대 정규화)
- 최소값은 0, 최대값은 1로, 그리고 다른 값들은 0과 1 사이의 값으로 변환하는 방식
- (data - MIN) / (MAX-MIN) 2. Z-Score Normalization (Z-점수 정규화)
- 평균은 0, 표준편차는 1인 정규 분포를 그리도록 데이터의 분포를 바꾸는 방식
- 이상치(outlier) 문제를 피하는 데이터 정규화 전략-
- (data - 평균) / 표준편차
1. overlapping pooling
- 겹쳐가며 pooling을 하는 방법
- 성능에 크게 영향을 미치는 방법은 아니다
2. non overlapping pooling
- 겹치지 않고 pooling을 하는 방법
1. parameter 줄여주기 때문에 연산량을 줄여준다
2. invariance한 속성을 더해준다
Overfitting을 줄이기 위한 방법으로써 이미지 데이터를 변형해서 학습 데이터의 수를 늘리는 방법이다
이미지 데이터를 좌우반전, 상하반전, 회전, 자르기 등을 하여 학습하지 않은 데이터를 대처할 수 있는 일반적인 모델을 만들어주는 데에 효과적인 방법이다
Dropout은 특정 확률로 hidden layer의 node 출력값을 0으로 설정하는 방법이다 이렇게 dropout된 node들은 foward, backward propagation에 관여를 하지 않는다 dropout이 사용된 NN는 입력이 주어질 때마다 달라진 신경망 구조를 거치게 되고 이는 노드간의 의존성을 약화시켜 가장 영향력 있는 노드의 연결성이 강화되는 방식으로 학습을 하게된다 따라서 성능은 비슷하지만 연산 복잡도를 줄이면서 overfitting 문제를 해결하는 방법이 될 수 있다 ※ Fully connected layer 다음에 Dropuout을 사용한다
Ensemble기법을 사용하고 pre-trained 모델인 경우에 에러율이 더 낮았다
※ CNNs는 Boosting기법(Ensemble)을 사용한 방법
논문 구현
# 평균은 0, 표준분포는 0.01인 정규분포 값으로 가중치를 초기화 한다
bias = tf.keras.initializers.Constant(1) # relu 때문에 초기화 값을 1로 지정한다 (음수가 들어가면 dying relu현상이 발생하기 때문)
input_ = tf.keras.Input((224,224,3))
x = tf.keras.layers.Conv2D(96,5,4)(input_)
x = tf.keras.layers.MaxPool2D(3,2)(x) # overlapping pooling
x = tf.keras.layers.Conv2D(256,3, padding='same', bias_initializer=bias)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.MaxPool2D(3,2)(x)
x = tf.keras.layers.Conv2D(384,3, padding='same', bias_initializer='ones')(x) # ones 단축키는 버전에따라 지원하지 않을 수 있다 -
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Conv2D(384,3, padding='same', bias_initializer=bias)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Conv2D(256,3, padding='same', bias_initializer=bias)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Flatten()(x)
x = tf.keras.layers.Dense(4096, bias_initializer=bias)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Dropout(0.5)(x)
x = tf.keras.layers.Dense(4096, bias_initializer=bias)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Dropout(0.5)(x)
x = tf.keras.layers.Dense(1000, bias_initializer=bias, activation='softmax')(x)
model = tf.keras.models.Model(input_,x) # tensorflow from_logit
model.summary()
# Model: "model_3"
# _________________________________________________________________
# Layer (type) Output Shape Param #
# =================================================================
# input_4 (InputLayer) [(None, 224, 224, 3)] 0
# _________________________________________________________________
# conv2d_15 (Conv2D) (None, 55, 55, 96) 7296
# _________________________________________________________________
# max_pooling2d_6 (MaxPooling2 (None, 27, 27, 96) 0
# _________________________________________________________________
# conv2d_16 (Conv2D) (None, 27, 27, 256) 221440
# _________________________________________________________________
# re_lu_18 (ReLU) (None, 27, 27, 256) 0
# _________________________________________________________________
# max_pooling2d_7 (MaxPooling2 (None, 13, 13, 256) 0
# _________________________________________________________________
# conv2d_17 (Conv2D) (None, 13, 13, 384) 885120
# _________________________________________________________________
# re_lu_19 (ReLU) (None, 13, 13, 384) 0
# _________________________________________________________________
# conv2d_18 (Conv2D) (None, 13, 13, 384) 1327488
# _________________________________________________________________
# re_lu_20 (ReLU) (None, 13, 13, 384) 0
# _________________________________________________________________
# conv2d_19 (Conv2D) (None, 13, 13, 256) 884992
# _________________________________________________________________
# re_lu_21 (ReLU) (None, 13, 13, 256) 0
# _________________________________________________________________
# flatten_3 (Flatten) (None, 43264) 0
# _________________________________________________________________
# dense_9 (Dense) (None, 4096) 177213440
# _________________________________________________________________
# re_lu_22 (ReLU) (None, 4096) 0
# _________________________________________________________________
# dropout_4 (Dropout) (None, 4096) 0
# _________________________________________________________________
# dense_10 (Dense) (None, 4096) 16781312
# _________________________________________________________________
# re_lu_23 (ReLU) (None, 4096) 0
# _________________________________________________________________
# dropout_5 (Dropout) (None, 4096) 0
# _________________________________________________________________
# dense_11 (Dense) (None, 10) 40970
# =================================================================
# Total params: 197,362,058
# Trainable params: 197,362,058
# Non-trainable params: 0
# _________________________________________________________________
loss function 사용하는 3가지 방법
1. 객체지향 => 옵션 사용 가능
2. 함수형 => 옵션 사용 가능하지만 parital을 사용해야 한다 (Higer order function)
3. 함수형 단축 => 옵션 사용 불가
label encoding 방식에 따라서 loss function 방식도 달라져야 한다
- one-hot encoding (Multi label 일때)
- sparse label encoding (Multi label 아닐때) => Sparse가 붙은 loss function 사용
model.compile(loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False))
tf.keras.utils.to_categorical # label에서 one-hot으로 바꿔준다
# <function tensorflow.python.keras.utils.np_utils.to_categorical(y, num_classes=None, dtype='float32')>
20일차 - 논문 수업 (CNN) (0) | 2021.10.08 |
---|---|
19일차 - 논문 수업 (CNN) (0) | 2021.10.08 |
17일차 - 논문 수업 (CNN) (0) | 2021.10.04 |
16일차 - 논문 수업 (CNN) (0) | 2021.10.04 |
15일차 - CNN (0) | 2021.10.04 |