File size: 14,148 Bytes
51887be
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35931a6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51887be
 
 
 
 
 
 
 
 
 
 
 
 
35931a6
 
 
 
 
 
 
 
 
 
 
51887be
 
 
 
 
 
 
 
 
 
 
 
 
 
35931a6
 
 
 
 
 
 
 
51887be
 
 
74e1e24
51887be
 
 
b7cb74f
35931a6
b7cb74f
 
 
51887be
74e1e24
b7cb74f
51887be
 
 
74e1e24
51887be
 
 
35931a6
74e1e24
35931a6
74e1e24
35931a6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b7cb74f
35931a6
 
 
 
 
 
 
 
51887be
 
 
 
b7cb74f
51887be
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b7cb74f
51887be
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35931a6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51887be
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5581923
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
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, "", ""