OpenCV, YOLO 기반 로고 탐지 + 매장 안내 GUI를 구현한 프로젝트
이 프로그램은 OpenCV와 YOLO를 이용하여 브랜드들의 로고를 인식하여
지도상에서 해당 브랜드의 매장 혹은 사용자의 위치를 표시해주는 프로그램입니다.
이 프로젝트에서는 하남 스타필드 매장 구조와 입점한 브랜드들을 이용했습니다.
본 프로젝트는 백화점 등 대형 매장에서 안내데스크를 거치지 않고 고객이 원하는 브랜드 매장이나 현재 위치을 쉽게 찾아주는 시스템입니다.
사용자가 촬영한 이미지나 영상 혹은 카메라를 통해 로고를 인식시키면
시스템이 이를 실시간으로 브랜드들로 인식하고 현재 위치 및 해당 브랜드 매장 위치를 안내합니다.
- YOLOv8은 다양한 크기의 모델(n/s/m/l/x)을 제공하며, 본 프로젝트에서는 YOLOv8s를 선택했습니다.
모델 | 장점 | 단점 |
---|---|---|
YOLOv8n | 가장 빠름, 가벼움 | 정확도 낮음 |
YOLOv8s | 속도와 정확도의 균형 | 실시간 탐지에 적합 |
YOLOv8m/l/x | 정확도 높음 | 추론 속도 느림, 리소스 요구 높음 |
YOLOv8s는 실내 환경에서도 빠르고 정확한 탐지를 지원하여 선택했습니다.
-
40개 브랜드 로고에 대해 300장씩 합성 이미지 생성 (총 12000장)
-
데이터 증강법 (data augmentation)
- 원본 이미지에서 특징적인 부분 추출
- 추출한 이미지를 homography 를 이용하여상하좌우 왜곡
- 추출 이미지와 왜곡 이미지를 다양한 배경과 합성 (매장, 거리, 테이블 등)
- 랜덤 회전(±15°), 확대(1.3–1.5배) 등 적용
원본 | 추출 |
---|---|
![]() |
![]() |
왜곡 | 합성 |
---|---|
![]() |
![]() |
def apply_perspective(img, direction, ratio):
# direction(top/bottom/left/right)에 따라 원근 변형 좌표 설정
M = cv2.getPerspectiveTransform(src, dst) # 변환 행렬 계산
return cv2.warpPerspective(img, M, (w, h)) # 원근 변형 적용
def generate():
for logo_path in logo_paths:
cleaned = clean_image(logo_path) # 메타데이터 제거 및 RGBA 변환
for direction in DIRECTIONS:
warped = apply_perspective(logo, direction, ratio)
cv2.imwrite(..., warped) # 왜곡된 이미지 저장
def rotate_image_no_crop(img, angle):
# 이미지 회전 시 잘리지 않도록 크기 확장 후 회전 적용
return cv2.warpAffine(img, M, (new_w, new_h))
def place_logo_on_background(bg, logo):
# 로고를 배경 위 무작위 위치에 합성
# YOLO 형식 라벨 (x_center, y_center, width, height) 반환
return composite, (x, y, w, h)
def generate():
for cls_name in class_to_images:
for i in range(num_per_class):
logo = rotate_image_no_crop(...)
comp, label = place_logo_on_background(...)
cv2.imwrite(...); write YOLO label to .txt # 이미지 저장 및 라벨 작성
- YOLOv8s 모델 초기화:
YOLO('yolov8s.pt')
- 입력 해상도: 640x640
- 에폭 수: 100
- 검증용 데이터: 클래스별 학습 이미지의 10~20%의 새로운 합성 이미지 생성해서 사용용
- 실제 영상으로 일반화 성능 테스트 수행
- YOLO 학습 명령어
yolo task=detect mode=train model=yolov8s.pt data=dataset/data.yaml epochs=100 imgsz=640
- 일부 클래스가 실제 환경에서 탐지 성능 저하 → 클래스별 파인튜닝 수행
- 기존 모델 유지한 채 문제 클래스만 실제 로고로 재학습
- 합성 + 실제 샘플 혼합으로 일반화 성능 개선
- 추후 새로운 브랜드 학습시 유용
- 촬영한 이미지나 비디오 혹은 실시간 카메라에서 브랜드 로고 탐지
- YOLOv8s 추론 결과 → 탐지된 클래스 ID 획득
- Tkinter GUI와 연동하여 로고 인식 결과 전송
- 실제 매장 지도를 고정 해상도 (예: 2400x800) 격자로 단순화 및 픽셀화
- 각 셀(픽셀)은 해당 위치의 의미를 가지는 색상으로 채워짐
- 이 격자는
NumPy 배열
로 처리되어 추후 경로 탐색 알고리즘에 사용될 예정
원본 | 단순화 |
---|---|
![]() |
![]() |
# 빨간색 마스크 (입구 표시 색)
lower_red = np.array([0, 0, 200])
upper_red = np.array([50, 50, 255])
mask = cv2.inRange(img, lower_red, upper_red)
# 외곽선 중심 좌표 계산
for cnt in contours:
M = cv2.moments(cnt)
cx = int(M["m10"] / M["m00"])
cy = int(M["m01"] / M["m00"])
entrance_points.append((cx, cy)
# y좌표 우선 내림차순 정렬 → Gate 번호와 연결
entrance_points.sort(key=lambda pt: (-pt[1], -pt[0]))
# 좌표 파일 저장
with open("entrance_coordinates.txt", "w") as f:
for i, (x, y) in enumerate(entrance_points, 1):
f.write(f"{i}: ({x}, {y})\n")
의미 | 색상 코드 (BGR) | 설명 |
---|---|---|
통로 (이동 불가) | (255, 255, 255) | 흰색 – 각 브랜드 매장이 위치한 셀 |
벽 또는 장애물 | (0, 0, 0) | 검정 – 경로 불가 영역 |
매장 영역 | (175, 175, 175) | 회색 – 사용자가 자유롭게 이동 가능한 공간 |
매장 입구 | (0, 0, 255) | 빨강 – 각 매장의 입구 |
에스컬레이터 | (0, 255, 0) | 초록 – 다른층으로 이동하기 위한 공간 |
- 지도 이미지를 불러와
cv2.resize()
로 축소 → 격자로 변환 - 각 픽셀 색상을 기준으로 의미를 판별하여
2D 행렬(map_array)
생성
- GUI에서의 시각적 안내와
- 추후 경로 탐색 알고리즘에서 구분을 위해 사용하기 위함
map.cell
과class.cell
을 이용한 브랜드 ↔ 매장 ↔ 입구 정보 매핑- Tkinter로 제작된 GUI 상에 타원 영역으로 매장 표시
- map.py와 gate.py를 통해 각 매장의 입구 좌표와 번호 획득 및 사용
- 탐지된 브랜드 → 해당 매장 위치로 자동 포커스
# 입구 방향에서 어느정도 떨어진 지점인 **앵커**를 이용해서 위치계산 및 표시 했습니다.
def shifted_anchor(x, y, direction="down"):
# 입구 방향에 따라 위치를 약간 바깥으로 이동시켜 기준점 설정
offsets = {"down": 80, "up": 80, "left": 40, "right": 40}
return ... # 방향별 보정 좌표 반환
# 여러 입구 좌표 → 방향 보정 → 평균 좌표 계산
coords = [shifted_anchor(x, y, direction) for num in anchor_nums]
avg_x = sum(set(x for x, _) in coords) // len(set(x for x, _) in coords)
avg_y = sum(set(y for _, y) in coords) // len(set(y for _, y) in coords)
├── TermProject/
│ ├── codes/
│ | ├── main.py
│ | ├── YOLO_LOGO_img.py
│ | ├── way.py
│ | └── ...
│ ├── images/
│ | ├── starfield 1F.png
│ | ├── title.png
│ | └── logo/
| | ├── adidas1.png
| | ├── starbucks.png
| | └── ...
| ├── cells/
│ | ├── class.cell
│ | └── map.cell
| ├── txts/
│ | ├── entrance_coordinates.txt
│ | └── map_array.npy
│ └── best.pt
분야 | 기술 스택 |
---|---|
객체 탐지 | YOLOv8 (Ultralytics), OpenCV |
데이터 증강 | Python, NumPy, 이미지 왜곡/합성, YOLO 라벨 자동화 |
GUI 구현 | Tkinter, OpenCV 기반 이미지 매핑 |
데이터 처리 | Pandas, Excel(.cell) 기반 입구/브랜드 매핑 |
- 총 40개 가량의 브랜드 로고에 대해 인식 성공 (합성 + 실제 촬영 데이터 기준)
- 테스트 영상 내에서도 탐지된 브랜드의 매장 위치를 GUI 상에서 정확하게 포인팅
- 여러 브랜드들을 인식했을 경우 각 매장의 앵커 좌표를 계산하여 현재 위치 표시 구현 성공
- 📷 지속적인 Fine-Tuning → 탐지 정확도 향상 예정
- 🏬 200개 가량의 브랜드까지 클래스 확장 및 2F, 3F 등 다른 층도 확장 예정
- 📱 원하는 매장으로 길찾기 내비게이션 기능 구현 예정