#!/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()