Spaces:
Sleeping
Sleeping
| 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, "", "" |