#1. 프로젝트 소개
프로젝트 진행 과정 중, AI 팀원이 따로 없어 백엔드를 맡은 필자가 AI 레포를 따로 만들어
기존 백엔드(django)와 AI(FastAPI)를 연동했다.
상용화된 LLM 모델(예. GPT / Gemini)를 사용하지 않은 이유는, AI가 해야 하는 역할이 다음과 같기 때문이다.
프로젝트에서 AI 모델이 분석해야 하는 것
1. 사진의 배경 장소 구분 (이 사진은 경복궁에서 찍은 사진인가? 한강에서 찍은 사진인가? 에 대한 판단)
2. 사진 속 인물의 포즈 구분 (사진 속 인물은 어떠한 포즈를 하고 있는가? 브이? 하트?)
3. 기타 조건 들..
이 조건을 만족해야했다.
유저가 사진을 찍거나 불러와 그에 대한 판단을 하는 것이 이 프로젝트의 주요 기능이다.
그러나, GPT나 Gemini에게 사진 자체를 넘겨 위 조건들에 대한 판단을 맡기기엔 비용 문제가 있었다.
고로, 오픈소스로 공개된 AI 모델을 자체적으로 구동하여 모델의 응답 값을 튜닝 해 기능을 구현하기로 했다.
#2. 모델 선정 과정
현 시점 (7/13) 선정한 모델은 CLIP와 Media PIPE 두 개의 모델이다.
CLIP은 Open AI에서 개발한 텍스트-이미지 멀티 모달 모델로, 장소 판단을 위해 선정했다.
비슷한 모델로 BLIP/BLIP-2 모델이 있었지만, 모델 자체가 매우 무겁고, GPU 없이는 원활한 구동이 되지 않을 것이라 판단했다.
(성능 자체는 BLIP/BLIP-2이 더 좋다고 한다.)
Media PIPE는 구글에서 개발한 모델로, 포즈 판단을 위해 선정했다.
표정 감지, Face mesh 등 다양한 기능을 제공하는데,
이 프로젝트에서는 "Pose"를 통해 손 부분을 크롭하고 -> "hands"를 통해 그 모양을 구분했다.
#3 모델 구현 과정
내가 사용한 두 모델은 이미 학습이 완료된 상태의 AI이기에 추가 학습 없이 레그를 띄워 기능을 구현했다.
(개발환경: Pycharm / FastAPI)
## 디렉토리 구조
1. 장소 판단 관련 폴더
-> location
2. 손 포즈 판단 관련 폴더
-> hands
Deulsseokz_AI/
├── hands/
│ ├── __init__.py
│ ├── detector.py
│ ├── pose.py
│ ├── utils.py
│ └── main.py
│
├── location/
│ ├── __init__.py
│ ├── clip_model.py ◀︎ CLIP 로딩 및 예측 함수
│ └── analyze.py ◀︎ FastAPI 경로 처리용
다음과 같이 정리할 수 있다.
구현 코드는 깃허브 레포지터리에서 확인할 수 있다.
공식 문서를 활용해 개발
https://github.com/openai/CLIP?tab=readme-ov-file
#3-1. 모델 튜닝 중 트러블 슈팅
CLIP 모델의 장소 판단 기준 및 과정은 다음과 같다.
1. 사전학습 (Pretrained on large-scale image-text pairs) CLIP은 OpenAI에서 4억 쌍 이상의 이미지-텍스트 쌍으로 사전학습됨. 예: 이미지 = 에펠탑 사진 / 텍스트 = "Eiffel Tower" 이런 식의 쌍을 수백만 개 학습함.
2. 이미지와 텍스트를 같은 임베딩 공간으로 매핑 입력 이미지
→ Vision Transformer 또는 ResNet
→ 이미지 임베딩 생성 입력 텍스트
→ Transformer 기반 텍스트 인코더
→ 텍스트 임베딩 생성 이 두 임베딩을 비교하여 유사도(similarity)를 측정
3. 장소 판단 예를 들어 후보 텍스트: ["N서울타워", "광화문", "경복궁"] 입력 이미지와 각 텍스트의 임베딩 간 코사인 유사도를 계산 유사도가 가장 높은 텍스트를 예측 결과로 반환
후보 텍스트 입력을 초기에는,
candidates = ["N서울타워", "광화문", "롯데타워", "한강공원", "경복궁"]
다음과 같이 한국어로 작성했다. 정확도가 낮아 위와 같은 판단 기준을 고려해 장소명을 영어로 바꾸었다.
candidates = ["N Seoul Tower", "Gyeongbokgung Palace", "Han River Park"]
그 결과 정확도가 매우 향상되었다.
#4. django 모델과 연동
AI 모델 서버를 먼저 돌린 후, 장고 모델 서버를 돌린 후 요청 및 반환을 통해 결과 값을 전달받았다.
이 또한 깃허브 레포에서 코드 확인..
과정은 다음과 같다.
[사용자 업로드 이미지]
↓
[ Django View (REST API) ]
↓
[ MediaPipe 판단: 포즈 추출 → 손 방향 계산 ]
↓
[ CLIP 판단: 장소 유사도 판단 ("남산타워" 등) ]
↓
[ 조건 만족 여부 → JSON 응답 ]
기존 데이터베이스에 저장된 조건 정보 (ex. [Han River Park] 한강에서 사진을 찍습니다.)에서 키워드를 추출해, 모델이 반환한 값을 비교해 도전의 성공 여부를 비교해야 한다.
#5. 테스트
테스트 이미지 (한강에서 브이하고 있는 사진)
1. 장소 판단
2. 포즈 판단
3. 장고 연결 결과값
{
"isSuccess": true,
"code": "COMMON200",
"message": "성공입니다.",
"result": {
"pose_analysis": {
"results": [
{
"pose": "V sign",
"fingers": {
"index": true,
"middle": true,
"ring": false,
"pinky": false
}
}
]
},
"location_prediction": {
"location": "Han River Park",
"confidence": 0.6373350024223328
}
}
}
아직 기능 구현을 완성한 게 아니라, 모델 연동만 한 값이라 응답이 오히려 직관적이다..
이제 구현하러 가야지