import json import numpy as np from PIL import Image import subprocess import sys import logging import gradio as gr from typing import Tuple, Dict, Optional import tempfile import os def install(package): subprocess.check_call([sys.executable, "-m", "pip", "install", package]) # 依存関係のインストール install("opencv-python-headless") install("moondream") install("openai") import cv2 import moondream as md from openai import OpenAI class PrivacyProtector: def __init__(self, moondream_api_key, deepseek_api_key): self.moon_model = md.vl(api_key=moondream_api_key) self.deepseek_client = OpenAI( api_key=deepseek_api_key, base_url="https://api.deepseek.com" ) def analyze_risk(self, image_path): """画像のリスク分析を行う""" try: pil_image = Image.open(image_path) cv_image = cv2.imread(image_path) if cv_image is None: raise ValueError("画像の読み込みに失敗しました") encoded_image = self.moon_model.encode_image(pil_image) caption = self.moon_model.caption(encoded_image)["caption"] analysis_prompt = f""" 以下の画像説明を基に個人情報漏洩リスクを分析し、厳密にJSON形式で返答してください: {{ "risk_level": "high|medium|low", "risk_reason": "リスクの具体的理由", "objects_to_remove": ["消去すべきオブジェクトリスト"] }} 画像説明: {caption} """ response = self.deepseek_client.chat.completions.create( model="deepseek-chat", messages=[ {"role": "system", "content": "あなたは優秀なセキュリティ分析AIです。"}, {"role": "user", "content": analysis_prompt} ], temperature=0.3, response_format={"type": "json_object"} ) result = json.loads(response.choices[0].message.content) return pil_image, cv_image, result except Exception as e: logging.error(f"リスク分析エラー: {str(e)}") raise def remove_objects(self, pil_image, cv_image, objects_to_remove): """オブジェクト検出と消去処理""" try: mask = np.zeros(cv_image.shape[:2], dtype=np.uint8) h, w = cv_image.shape[:2] for obj_name in objects_to_remove: detection = self.moon_model.detect(pil_image, obj_name) for obj in detection["objects"]: x_min = int(obj['x_min'] * w) y_min = int(obj['y_min'] * h) x_max = int(obj['x_max'] * w) y_max = int(obj['y_max'] * h) cv2.rectangle(mask, (x_min, y_min), (x_max, y_max), 255, -1) inpainted = cv2.inpaint(cv_image, mask, 3, cv2.INPAINT_TELEA) return inpainted except Exception as e: logging.error(f"オブジェクト削除エラー: {str(e)}") raise def process_image(self, image_path): """画像処理フロー全体""" try: pil_img, cv_img, result = self.analyze_risk(image_path) if result['risk_level'] != 'low': cleaned = self.remove_objects(pil_img, cv_img, result['objects_to_remove']) return cleaned, result return cv_img, result except Exception as e: logging.error(f"画像処理エラー: {str(e)}") raise def gradio_process(input_image): try: # 一時ファイルの処理 with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp_file: input_path = tmp_file.name cv2.imwrite(input_path, cv2.cvtColor(input_image, cv2.COLOR_RGB2BGR)) # 環境変数の安全な取得 protector = PrivacyProtector( moondream_api_key=os.environ.get('MOONDREAM'), deepseek_api_key=os.environ.get('DEEPSEEK') ) # 画像処理実行 processed_image, result = protector.process_image(input_path) # 結果の整形 output_image = cv2.cvtColor(processed_image, cv2.COLOR_BGR2RGB) info_html = f"""
生成キャプション: {result.get('caption', '')}
リスクレベル: {result['risk_level'].upper()}
理由: {result['risk_reason']}
消去対象: {', '.join(result['objects_to_remove'])}