# 케라스 세션 초기화tf.keras.backend.clear_session()
fromtensorflow.keras.applications.mobilenet_v3importpreprocess_inputimportosimportjsonimportcv2importnumpyasnpfromtensorflow.keras.utilsimportto_categorical# 이미지 로드 및 전처리 함수defload_and_preprocess_image(image_path, target_size=(224, 224)):
image=cv2.imread(image_path)
ifimageisNone:
print(f"에러: 이미지를 불러올 수 없습니다. 이미지 경로: {image_path}")
returnNoneimage=cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image=cv2.resize(image, target_size)
returnimage.astype(np.float32)
# 데이터 Generator 함수defdata_generator(annotation_file, image_directory, batch_size=32):
withopen(annotation_file, 'r') asf:
data=json.load(f)
images_paths= []
labels= []
forentryindata["annotations"]:
image_id=entry["image_id"]
image_filename=data["images"][image_id]["file_name"]
image_path=os.path.join(image_directory, image_filename)
images_paths.append(image_path)
labels.append(entry["category_id"])
num_samples=len(images_paths)
whileTrue:
foroffsetinrange(0, num_samples, batch_size):
batch_images= []
batch_labels= []
batch_paths=images_paths[offset:offset+batch_size]
batch_labels=labels[offset:offset+batch_size]
forimage_pathinbatch_paths:
image=load_and_preprocess_image(image_path)
ifimageisnotNone:
batch_images.append(image)
ifbatch_images:
batch_images=np.array(batch_images)
batch_labels=to_categorical(batch_labels, num_classes=len(data["categories"]))
yieldbatch_images, batch_labels# 데이터 로딩 및 전처리annotation_file="/content/drive/MyDrive/DataV9/train/_annotations.coco.json"image_directory="/content/drive/MyDrive/DataV9/train/train"batch_size=32data_gen=data_generator(annotation_file, image_directory, batch_size=batch_size)
4) 모델 정의
fromtensorflow.keras.layersimportGlobalAveragePooling2D# 데이터 로딩 및 전처리 함수defload_data(annotation_file, image_directory, batch_size=32):
returnimages, labels# images와 labels 반환# 데이터 로딩annotation_file="/content/drive/MyDrive/DataV9/train/_annotations.coco.json"# 이미지 경로는 개인에 맞춰 수정image_directory="/content/drive/MyDrive/DataV9/train/train"batch_size=10images, labels=load_data(annotation_file, image_directory, batch_size=batch_size)
# 모델 구성base_model=MobileNetV3Small(weights='imagenet',
include_top=False,
input_shape=(224, 224, 3))
model=Sequential()
model.add(base_model)
model.add(GlobalAveragePooling2D()) # 메모리 효율을 위해 Global Average Pooling 레이어 사용model.add(Dense(256, activation='relu'))
model.add(Dense(128, activation='relu'))
model.add(Dense(3, activation='softmax'))
# 모델 컴파일model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
# 텐서보드 로그 디렉토리 지정log_dir="logs/weights_visualization"# 텐서보드 콜백 설정tensorboard_callback=tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)
importnumpyasnpfromtensorflow.keras.utilsimportto_categorical# 이미지 데이터를 numpy 배열로 변환images=np.array(images)
# 라벨을 one-hot 인코딩 된 텐서 형태로 변환labels=to_categorical(labels, num_classes=len(coco_data["categories"]))
5) 모델 학습
# 모델 학습num_epochs=70batch_size=10# 메모리 효율을 위해 작은 배치 크기 사용model.fit(images, labels, epochs=num_epochs, batch_size=batch_size, callbacks=[tensorboard_callback])
6) 모델 저장
# 모델 저장model.save("/content/drive/MyDrive/saved_model/trained_model(MobileNetV3).h5")
7) 텐서보드 모델학습현황 확인
%load_exttensorboard%tensorboard--logdirlogs/weights_visualization# 학습 로그가 있는 디렉토리 경로 지정
8) 모델 분류 테스트
# 모델이 분류하고있는지 정상작동 확인debug_images=images[:15] # 2개 이미지 선택. 수정가능debug_predictions=model.predict(debug_images)
foriinrange(len(debug_images)):
true_label=np.argmax(labels[i])
predicted_label=np.argmax(debug_predictions[i])
print(f"True Label: {true_label}, Predicted Label: {predicted_label}, Probabilities: {debug_predictions[i]}")
9) 테스트
fromtensorflow.keras.applications.mobilenet_v3importpreprocess_inputfromgoogle.colab.patchesimportcv2_imshowimportjsonimportcv2importnumpyasnpfromtensorflow.keras.modelsimportload_model# 테스트 데이터 JSON 파일 로드withopen("/content/drive/MyDrive/DataV9/test/_annotations.coco.json", 'r') asf:
test_coco_data=json.load(f)
# 테스트 이미지 경로test_image_directory="/content/drive/MyDrive/DataV9/test/test"# 저장된 모델 로드 (MobileNetV3)loaded_model=load_model("/content/drive/MyDrive/saved_model/trained_model(MobileNetV3).h5")
# JSON 파일 내 categories에서 클래스 라벨 정보 추출# 클래스 레이블 0 은 분류에 무의미한 정보이므로 제외class_labels_json= {
category["id"]: category["name"]
forcategoryintest_coco_data["categories"]
ifcategory["id"] !=0# "id"가 0인 경우는 제외
}
# 정확도 계산을 위한 변수 초기화total_images=len(test_coco_data["images"])
correct_predictions=0# 테스트 이미지에 대한 예측과 정확도 계산forentryintest_coco_data["annotations"]:
image_id=entry["image_id"]
image_filename=test_coco_data["images"][image_id]["file_name"]
image_path=os.path.join(test_image_directory, image_filename)
# 이미지 로드 및 전처리original_image=cv2.imread(image_path)
iforiginal_imageisNone:
print(f"에러: 이미지를 불러올 수 없습니다. 이미지 경로: {image_path}")
continueoriginal_image=cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB)
image=cv2.resize(original_image, (224, 224))
image=preprocess_input(image.astype(np.float32))
# 모델 예측predictions=loaded_model.predict(np.expand_dims(image, axis=0))[0]
# 예측 결과와 실제 레이블 비교하여 정확도 확인true_label=entry["category_id"]
predicted_label=np.argmax(predictions)
# 클래스 라벨 가져오기true_label_name=class_labels_json[true_label]
predicted_label_name=class_labels_json[predicted_label]
# 0에 해당하는 클래스 라벨 제외하고 출력iftrue_label!=0:
print(f"True Label: {true_label_name}, Predicted Label: {predicted_label_name}")
# 바운딩 박스 차이 및 신뢰도 출력forlabel_id, probinenumerate(predictions):
iflabel_id!=0: # 클래스 라벨이 0이 아닌 경우에만 출력label_name=class_labels_json.get(label_id, "Unknown")
print(f"{label_name}: {prob*100:.2f}%")
# 예측에 실패한 경우 이미지 출력iftrue_label!=predicted_label:
print("예측 실패한 이미지 출력")
cv2_imshow(original_image)
Helmet detection(ResNet152)
1. 개발환경
1) 사용한 OS
- posix
2) 파이썬 버전
- 3.10.12
3) 설치한 라이브러리
- os, json, cv2, numpy, tensorflow
2. 실행방법
1) 데이터 로드 및 전처리
!pipinstalltensorflowopencv-python
2) 라이브러리 선언
importosimportjsonimportcv2importnumpyasnpfromtensorflow.keras.applications.resnetimportResNet152, preprocess_inputfromtensorflow.keras.layersimportDense, Flattenfromtensorflow.keras.modelsimportModelfromtensorflow.keras.utilsimportto_categorical# RestNet50# 모델 변경시 사용importosimportjsonimportcv2importnumpyasnpfromtensorflow.keras.applications.resnetimportResNet50, preprocess_inputfromtensorflow.keras.layersimportDense, Flattenfromtensorflow.keras.modelsimportModelfromtensorflow.keras.utilsimportto_categorical
3) 데이터 전처리
# train JSON 파일 로드withopen("/content/drive/MyDrive/DataV9/train/_annotations.coco.json", 'r') asf: # 모든 데이터 경로는 개인에 맞춰 수정coco_data=json.load(f)
# train 이미지 디렉토리 경로image_directory="/content/drive/MyDrive/DataV9/train/train"# 이미지 및 라벨 데이터 로딩 및 전처리images= []
labels= []
forentryincoco_data["annotations"]:
image_id=entry["image_id"]
image_filename=coco_data["images"][image_id]["file_name"]
image_path=os.path.join(image_directory, image_filename)
image=cv2.imread(image_path)
ifimageisNone:
print(f"에러: 이미지 {image_id}를 불러올 수 없습니다. 이미지 경로: {image_path}")
continueimage=cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image=cv2.resize(image, (224, 224))
image=preprocess_input(image.astype(np.float32))
label=entry["category_id"]
labels.append(label)
images.append(image)
# images를 numpy 배열로 변환하여 저장np.save('saved_images.npy', np.array(images))
images=np.array(images)
labels=to_categorical(labels, num_classes=len(coco_data["categories"]))
# 모델 학습num_epochs=200batch_size=50model.fit(images, labels, epochs=num_epochs, batch_size=batch_size, callbacks=[tensorboard_callback])
6) 모델 저장
# 모델 저장
model.save("/content/drive/MyDrive/saved_model/trained_model(resnet152).h5")
7) 텐서보드 모델학습현황 확인
%load_exttensorboard%tensorboard--logdirlogs/weights_visualization# 학습 로그가 있는 디렉토리 경로 지정
8) 모델 분류테스트기
# 모델이 분류하고있는지 정상작동 확인debug_images=images[:2] # 2개 이미지 선택. 수정가능debug_predictions=model.predict(debug_images)
foriinrange(len(debug_images)):
true_label=np.argmax(labels[i])
predicted_label=np.argmax(debug_predictions[i])
print(f"True Label: {true_label}, Predicted Label: {predicted_label}, Probabilities: {debug_predictions[i]}")
9) 테스트
fromgoogle.colab.patchesimportcv2_imshowimportjsonimportcv2importnumpyasnpfromtensorflow.keras.modelsimportload_model# 테스트 데이터셋 JSON 파일 로드withopen("/content/drive/MyDrive/data_forResnet/test/_annotations.coco.json", 'r') asf:
test_coco_data=json.load(f)
# 테스트 이미지 디렉토리 경로test_image_directory="/content/drive/MyDrive/data_forResnet/test/test/"# 저장된 모델 로드loaded_model=load_model("/content/drive/MyDrive/saved_model/trained_model.h5")
# JSON 파일 내 categories에서 클래스 라벨 정보 추출class_labels_json= {
category["id"]: category["name"]
forcategoryintest_coco_data["categories"]
ifcategory["id"] !=0# "id"가 0인 경우는 제외
}
# 정확도 계산을 위한 변수 초기화total_images=len(test_coco_data["images"])
correct_predictions=0# 테스트 이미지에 대한 예측과 정확도 계산forentryintest_coco_data["annotations"]:
image_id=entry["image_id"]
image_filename=test_coco_data["images"][image_id]["file_name"]
image_path=test_image_directory+image_filename# 이미지 로드 및 전처리original_image=cv2.imread(image_path)
original_image=cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB)
image=cv2.resize(original_image, (224, 224))
image=preprocess_input(image.astype(np.float32))
# 모델 예측predictions=loaded_model.predict(np.expand_dims(image, axis=0))[0]
# 예측 결과와 실제 레이블 비교하여 정확도 확인true_label=entry["category_id"]
predicted_label=np.argmax(predictions)
# 클래스 라벨 가져오기true_label_name=class_labels_json[true_label]
predicted_label_name=class_labels_json[predicted_label]
# 0에 해당하는 클래스 라벨 제외하고 출력iftrue_label!=0:
print(f"True Label: {true_label_name}, Predicted Label: {predicted_label_name}")
# 바운딩 박스 차이 및 신뢰도 출력forlabel_id, probinenumerate(predictions):
iflabel_id!=0: # 클래스 라벨이 0이 아닌 경우에만 출력label_name=class_labels_json.get(label_id, "Unknown")
print(f"{label_name}: {prob*100:.2f}%")
# 예측에 실패한 경우 이미지 출력iftrue_label!=predicted_label:
print("예측 실패한 이미지 출력")
cv2_imshow(original_image)