persona / modules /image_analyzer.py
haepa_mac
🚀 향상된 통합 시스템 구현: 사용자 조정값이 127개 변수에 실제 반영되는 완전한 통합 알고리즘
a83437e
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
🔍 간단한 이미지 분석기
이미지에서 기본적인 시각적 특성을 추출하는 모듈
기능:
1. 🎨 색상 분석 (주요 색상 추출)
2. 📏 크기 추정
3. 🏷️ 객체 타입 추정 (확장자 기반)
4. 📄 기본 설명 생성
"""
import os
from PIL import Image
import random
from typing import Dict, List, Any
class ImageAnalyzer:
"""간단한 이미지 분석기"""
def __init__(self):
"""초기화"""
self.color_names = {
"red": ["빨강", "빨간색", "적색"],
"blue": ["파랑", "파란색", "청색"],
"green": ["초록", "녹색", "그린"],
"yellow": ["노랑", "노란색", "황색"],
"black": ["검정", "검은색", "흑색"],
"white": ["하양", "흰색", "백색"],
"gray": ["회색", "그레이"],
"brown": ["갈색", "브라운"],
"orange": ["주황", "오렌지색"],
"purple": ["보라", "보라색", "자주색"],
"pink": ["분홍", "핑크색"],
"silver": ["은색", "실버"],
"gold": ["금색", "골드"]
}
self.object_types = [
"스마트폰", "노트북", "태블릿", "이어폰", "헤드폰", "스피커",
"마우스", "키보드", "시계", "안경", "가방", "지갑", "열쇠",
"컵", "머그컵", "펜", "연필", "책", "노트", "다이어리",
"인형", "쿠션", "베개", "담요", "램프", "화분", "액자",
"카메라", "게임기", "리모컨", "충전기", "케이블", "보조배터리"
]
self.materials = [
"플라스틱", "금속", "유리", "가죽", "원목", "섬유", "실리콘",
"고무", "세라믹", "종이", "카드보드", "스테인리스", "알루미늄"
]
def analyze_image(self, image_path: str) -> Dict[str, Any]:
"""
이미지 분석 수행
Args:
image_path: 이미지 파일 경로
Returns:
분석 결과 딕셔너리
"""
try:
if not os.path.exists(image_path):
return self._get_default_analysis("파일이 존재하지 않습니다.")
# 이미지 로드
with Image.open(image_path) as img:
# 기본 정보 추출
width, height = img.size
file_size = os.path.getsize(image_path)
# 색상 분석 (간단한 방식)
colors = self._analyze_colors(img)
# 크기 추정
size_category = self._estimate_size(width, height, file_size)
# 객체 타입 추정 (파일명 기반 + 랜덤)
object_type = self._estimate_object_type(image_path)
# 재질 추정 (랜덤 선택)
materials = self._estimate_materials()
# 상태 추정
condition = random.choice(["새것", "양호", "보통", "사용감 있음"])
# 설명 생성
description = self._generate_description(object_type, colors, size_category, condition)
return {
"object_type": object_type,
"colors": colors,
"materials": materials,
"size": size_category,
"condition": condition,
"description": description,
"image_info": {
"width": width,
"height": height,
"file_size": file_size,
"format": img.format
}
}
except Exception as e:
print(f"❌ 이미지 분석 중 오류: {e}")
return self._get_default_analysis(f"분석 오류: {str(e)}")
def _analyze_colors(self, img: Image.Image) -> List[str]:
"""간단한 색상 분석"""
try:
# 이미지를 축소해서 처리 속도 향상
img_small = img.resize((50, 50))
img_rgb = img_small.convert('RGB')
# 픽셀 색상 샘플링
colors = []
width, height = img_small.size
# 9개 지점에서 색상 샘플링
sample_points = [
(width//4, height//4), (width//2, height//4), (3*width//4, height//4),
(width//4, height//2), (width//2, height//2), (3*width//4, height//2),
(width//4, 3*height//4), (width//2, 3*height//4), (3*width//4, 3*height//4)
]
for x, y in sample_points:
r, g, b = img_rgb.getpixel((x, y))
color_name = self._rgb_to_color_name(r, g, b)
if color_name not in colors:
colors.append(color_name)
# 최대 3개 색상만 반환
return colors[:3] if colors else ["회색"]
except Exception as e:
print(f"색상 분석 오류: {e}")
return random.sample(list(self.color_names.keys()), 2)
def _rgb_to_color_name(self, r: int, g: int, b: int) -> str:
"""RGB 값을 색상 이름으로 변환"""
# 밝기 계산
brightness = (r + g + b) / 3
# 흑백 판단
if brightness < 50:
return "black"
elif brightness > 200:
return "white"
elif abs(r - g) < 30 and abs(g - b) < 30 and abs(r - b) < 30:
return "gray"
# 색상 판단 (간단한 방식)
if r > g + 30 and r > b + 30:
if g > 100:
return "orange"
else:
return "red"
elif g > r + 30 and g > b + 30:
return "green"
elif b > r + 30 and b > g + 30:
if r > 100:
return "purple"
else:
return "blue"
elif r > 150 and g > 150 and b < 100:
return "yellow"
elif r > 150 and g < 100 and b > 150:
return "purple"
elif r > 100 and g > 100 and b > 150:
return "pink"
elif r > 130 and g > 100 and b < 80:
return "brown"
else:
return random.choice(["gray", "silver", "gold"])
def _estimate_size(self, width: int, height: int, file_size: int) -> str:
"""크기 추정"""
# 해상도 기반 크기 추정
total_pixels = width * height
if total_pixels < 100000: # 약 300x300 미만
return "작은"
elif total_pixels < 500000: # 약 700x700 미만
return "보통"
elif total_pixels < 2000000: # 약 1400x1400 미만
return "큰"
else:
return "매우 큰"
def _estimate_object_type(self, image_path: str) -> str:
"""객체 타입 추정"""
filename = os.path.basename(image_path).lower()
# 파일명에서 키워드 추출
for obj_type in self.object_types:
if any(keyword in filename for keyword in [obj_type, obj_type.lower()]):
return obj_type
# 일반적인 키워드 매칭
keyword_mapping = {
"phone": "스마트폰", "mobile": "스마트폰", "iphone": "스마트폰", "samsung": "스마트폰",
"laptop": "노트북", "computer": "노트북", "macbook": "노트북", "notebook": "노트북",
"tablet": "태블릿", "ipad": "태블릿",
"headphone": "헤드폰", "earphone": "이어폰", "earbuds": "이어폰",
"speaker": "스피커", "audio": "스피커",
"mouse": "마우스", "keyboard": "키보드",
"watch": "시계", "clock": "시계",
"bag": "가방", "backpack": "가방",
"cup": "컵", "mug": "머그컵",
"book": "책", "note": "노트",
"camera": "카메라", "photo": "카메라",
"game": "게임기", "console": "게임기",
"lamp": "램프", "light": "램프",
"plant": "화분", "flower": "화분"
}
for keyword, obj_type in keyword_mapping.items():
if keyword in filename:
return obj_type
# 기본값: 랜덤 선택
return random.choice(self.object_types)
def _estimate_materials(self) -> List[str]:
"""재질 추정 (랜덤)"""
num_materials = random.randint(1, 3)
return random.sample(self.materials, num_materials)
def _generate_description(self, object_type: str, colors: List[str], size: str, condition: str) -> str:
"""설명 생성"""
color_desc = ", ".join(colors)
descriptions = [
f"{color_desc} 색상의 {size} {object_type}입니다. 상태는 {condition}해 보입니다.",
f"{size} 크기의 {object_type}로, {color_desc} 톤이 특징적입니다. {condition} 상태입니다.",
f"{condition} 상태의 {object_type}입니다. {color_desc} 색상이 인상적이며 {size} 사이즈입니다.",
f"이 {object_type}{color_desc} 색조로 되어 있고, {size} 크기에 {condition} 상태를 보입니다."
]
return random.choice(descriptions)
def _get_default_analysis(self, error_msg: str = "") -> Dict[str, Any]:
"""기본 분석 결과 반환"""
return {
"object_type": random.choice(self.object_types),
"colors": random.sample(list(self.color_names.keys()), 2),
"materials": random.sample(self.materials, 2),
"size": random.choice(["작은", "보통", "큰"]),
"condition": random.choice(["양호", "보통"]),
"description": f"이미지 분석에 실패했지만 기본적인 물건으로 추정됩니다. {error_msg}",
"image_info": {
"width": 0,
"height": 0,
"file_size": 0,
"format": "Unknown"
}
}
# 테스트 함수
def test_image_analyzer():
"""이미지 분석기 테스트"""
print("🔍 이미지 분석기 테스트")
print("=" * 40)
analyzer = ImageAnalyzer()
# 더미 분석 테스트
result = analyzer._get_default_analysis("테스트")
print(f"📊 테스트 결과:")
print(f" 객체 타입: {result['object_type']}")
print(f" 색상: {result['colors']}")
print(f" 재질: {result['materials']}")
print(f" 크기: {result['size']}")
print(f" 상태: {result['condition']}")
print(f" 설명: {result['description']}")
if __name__ == "__main__":
test_image_analyzer()