import os import json import random from PIL import Image # 물리적 특성 매핑 데이터 경로 SHAPE_TRAITS_PATH = "data/trait_mappings/shape_traits.json" COLOR_TRAITS_PATH = "data/trait_mappings/color_traits.json" MATERIAL_TRAITS_PATH = "data/trait_mappings/material_traits.json" def load_trait_mappings(): """물리적 특성-성격 매핑 데이터 로드""" # 파일이 없으면 기본 매핑 생성 if not os.path.exists(SHAPE_TRAITS_PATH): try: os.makedirs(os.path.dirname(SHAPE_TRAITS_PATH), exist_ok=True) default_shape_traits = { "곡선형": { "온기": (60, 80), "친화성": (60, 80), "창의성": (50, 70) }, "직선형": { "능력": (60, 80), "신뢰성": (60, 80) }, "대칭형": { "신뢰성": (70, 90), "능력": (60, 80) }, "비대칭형": { "창의성": (70, 90), "유머감각": (60, 80) }, "단순형": { "능력": (60, 80), "신뢰성": (50, 70) }, "복잡형": { "창의성": (70, 90), "능력": (60, 80) } } with open(SHAPE_TRAITS_PATH, 'w', encoding='utf-8') as f: json.dump(default_shape_traits, f, ensure_ascii=False, indent=2) except Exception as e: print(f"형태-특성 매핑 파일 생성 오류: {str(e)}") print("기본값을 사용합니다.") default_shape_traits = { "곡선형": {"온기": (60, 80), "친화성": (60, 80)}, "직선형": {"능력": (60, 80), "신뢰성": (60, 80)}, "대칭형": {"신뢰성": (70, 90)}, "비대칭형": {"창의성": (70, 90)}, "단순형": {"능력": (60, 80)}, "복잡형": {"창의성": (70, 90)} } # 색상 매핑 if not os.path.exists(COLOR_TRAITS_PATH): try: os.makedirs(os.path.dirname(COLOR_TRAITS_PATH), exist_ok=True) default_color_traits = { "밝은": { "온기": (60, 80), "친화성": (60, 80) }, "어두운": { "신뢰성": (60, 80), "창의성": (60, 80) }, "따뜻한": { "온기": (70, 90), "친화성": (60, 80) }, "차가운": { "신뢰성": (60, 80), "능력": (60, 80) }, "화려한": { "창의성": (70, 90), "유머감각": (60, 80) }, "단색": { "신뢰성": (60, 80), "능력": (50, 70) } } with open(COLOR_TRAITS_PATH, 'w', encoding='utf-8') as f: json.dump(default_color_traits, f, ensure_ascii=False, indent=2) except Exception as e: print(f"색상-특성 매핑 파일 생성 오류: {str(e)}") print("기본값을 사용합니다.") default_color_traits = { "밝은": {"온기": (60, 80)}, "어두운": {"신뢰성": (60, 80)}, "따뜻한": {"온기": (70, 90)}, "차가운": {"능력": (60, 80)}, "화려한": {"창의성": (70, 90)}, "단색": {"신뢰성": (60, 80)} } # 재질 매핑 if not os.path.exists(MATERIAL_TRAITS_PATH): try: os.makedirs(os.path.dirname(MATERIAL_TRAITS_PATH), exist_ok=True) default_material_traits = { "나무": { "온기": (60, 80), "신뢰성": (60, 80) }, "금속": { "능력": (70, 90), "신뢰성": (60, 80) }, "유리": { "신뢰성": (60, 80), "친화성": (40, 60) }, "가죽": { "온기": (60, 80), "신뢰성": (70, 90) }, "플라스틱": { "능력": (50, 70), "창의성": (50, 70) }, "천": { "온기": (70, 90), "친화성": (60, 80) }, "종이": { "창의성": (60, 80), "온기": (50, 70) } } with open(MATERIAL_TRAITS_PATH, 'w', encoding='utf-8') as f: json.dump(default_material_traits, f, ensure_ascii=False, indent=2) except Exception as e: print(f"재질-특성 매핑 파일 생성 오류: {str(e)}") print("기본값을 사용합니다.") default_material_traits = { "나무": {"온기": (60, 80)}, "금속": {"능력": (70, 90)}, "유리": {"친화성": (40, 60)}, "가죽": {"신뢰성": (70, 90)}, "플라스틱": {"창의성": (50, 70)}, "천": {"친화성": (60, 80)}, "종이": {"창의성": (60, 80)} } # 매핑 데이터 로드 shape_traits = {} color_traits = {} material_traits = {} try: if os.path.exists(SHAPE_TRAITS_PATH): with open(SHAPE_TRAITS_PATH, 'r', encoding='utf-8') as f: shape_traits = json.load(f) else: shape_traits = default_shape_traits if os.path.exists(COLOR_TRAITS_PATH): with open(COLOR_TRAITS_PATH, 'r', encoding='utf-8') as f: color_traits = json.load(f) else: color_traits = default_color_traits if os.path.exists(MATERIAL_TRAITS_PATH): with open(MATERIAL_TRAITS_PATH, 'r', encoding='utf-8') as f: material_traits = json.load(f) else: material_traits = default_material_traits return { "shape": shape_traits, "color": color_traits, "material": material_traits } except Exception as e: print(f"트레이트 매핑 로드 오류: {str(e)}") # 기본 매핑 제공 default_mappings = { "shape": default_shape_traits if 'default_shape_traits' in locals() else { "곡선형": {"온기": (60, 80)}, "직선형": {"능력": (60, 80)}, }, "color": default_color_traits if 'default_color_traits' in locals() else { "밝은": {"온기": (60, 80)}, "어두운": {"신뢰성": (60, 80)}, }, "material": default_material_traits if 'default_material_traits' in locals() else { "나무": {"온기": (60, 80)}, "금속": {"능력": (70, 90)}, } } return default_mappings def analyze_image(image_path): """ 이미지를 분석하여 물리적 특성과 그에 따른 성격 특성을 반환합니다. Args: image_path: 파일 경로 문자열 또는 File 컴포넌트 출력 객체 Returns: 이미지 분석 결과와 추천 특성값 """ if image_path is None: print("이미지가 없습니다.") return {}, 50, 50, 50, 50, 50, 50, "", "" try: print(f"이미지 분석 시작: {image_path}") # 이미지 로드 시도 try: # 파일 경로 처리 - 다양한 형식 지원 if isinstance(image_path, str): # 문자열 경로 img = Image.open(image_path) print(f"문자열 경로에서 이미지 로드 성공: {img.format}, {img.size}, {img.mode}") elif isinstance(image_path, dict): # File 컴포넌트에서 반환된 딕셔너리 처리 if 'path' in image_path: # 일반적인 File 컴포넌트 출력 형식 img = Image.open(image_path['path']) print(f"File 컴포넌트(path 키)에서 이미지 로드 성공: {img.format}, {img.size}, {img.mode}") elif 'name' in image_path: # 일부 환경에서는 name 키를 사용할 수 있음 img = Image.open(image_path['name']) print(f"File 컴포넌트(name 키)에서 이미지 로드 성공: {img.format}, {img.size}, {img.mode}") else: # 알 수 없는 딕셔너리 형식 print(f"지원되지 않는 딕셔너리 형식: {image_path.keys()}") raise ValueError(f"지원하지 않는 이미지 딕셔너리 형식: {list(image_path.keys())}") elif hasattr(image_path, 'name'): # 파일 객체 형식 img = Image.open(image_path.name) print(f"파일 객체에서 이미지 로드 성공: {img.format}, {img.size}, {img.mode}") else: # PIL Image 객체인지 확인 if hasattr(image_path, 'format') and hasattr(image_path, 'mode'): img = image_path print(f"PIL Image 객체 직접 사용: {img.format}, {img.size}, {img.mode}") else: # 기타 타입 처리 print(f"지원되지 않는 이미지 데이터 타입: {type(image_path)}") raise ValueError(f"지원하지 않는 이미지 형식: {type(image_path)}") except Exception as img_error: print(f"이미지 로드 실패: {str(img_error)}") return {}, 50, 50, 50, 50, 50, 50, "", "" # 분석 로직 (더미 데이터 생성) physical_features = { "shape": random.choice(["곡선형", "직선형", "대칭형", "비대칭형", "단순형", "복잡형"]), "color": random.choice(["밝은", "어두운", "따뜻한", "차가운", "화려한", "단색"]), "material": random.choice(["나무", "금속", "유리", "가죽", "플라스틱", "천", "종이"]) } # 물체 유형 추정 object_types = ["전자기기", "가구", "주방용품", "의류/액세서리", "책/문구류", "음악 기구", "장난감", "기타"] estimated_type = random.choice(object_types) # 물체 설명 생성 shape_desc = physical_features["shape"] color_desc = physical_features["color"] material_desc = physical_features["material"] object_description = f"{color_desc} 색조의 {shape_desc} {material_desc} 물체입니다." # 성격 특성 매핑 로드 trait_mappings = load_trait_mappings() if trait_mappings: # 기본 특성 값 traits = { "온기": 50, "능력": 50, "신뢰성": 50, "친화성": 50, "창의성": 50, "유머감각": 50 } # 형태 기반 성격 특성 적용 shape = physical_features["shape"] if shape in trait_mappings["shape"]: for trait, value_range in trait_mappings["shape"][shape].items(): traits[trait] = random.randint(value_range[0], value_range[1]) # 색상 기반 성격 특성 적용 color = physical_features["color"] if color in trait_mappings["color"]: for trait, value_range in trait_mappings["color"][color].items(): # 이미 형태에서 설정한 값과 평균 if trait in traits: traits[trait] = (traits[trait] + random.randint(value_range[0], value_range[1])) // 2 # 재질 기반 성격 특성 적용 material = physical_features["material"] if material in trait_mappings["material"]: for trait, value_range in trait_mappings["material"][material].items(): # 이미 설정한 값과 평균 if trait in traits: traits[trait] = (traits[trait] + random.randint(value_range[0], value_range[1])) // 2 # 분석 결과 반환 analysis_result = { "physical_features": physical_features, "estimated_type": estimated_type, "description": object_description, "suggested_traits": traits } print(f"이미지 분석 완료: {estimated_type}") return ( analysis_result, traits["온기"], traits["능력"], traits["신뢰성"], traits["친화성"], traits["창의성"], traits["유머감각"], estimated_type, object_description ) # 트레이트 매핑이 없는 경우 기본값 반환 return { "physical_features": physical_features, "estimated_type": estimated_type, "description": object_description, }, 50, 50, 50, 50, 50, 50, estimated_type, object_description except Exception as e: print(f"이미지 분석 중 오류 발생: {str(e)}") return {}, 50, 50, 50, 50, 50, 50, "", ""