画像分析ツールの実装
「エージェントの核となる画像分析ツールを実装しよう。」
田中VPoEが説明する。
「分類モデルの推論、Grad-CAMによる判断根拠の可視化、そしてVLMによる所見生成。この3つを一つのツールにまとめる。」
画像分類ツール
from langchain_core.tools import tool
import torch
from torchvision import transforms, models
from PIL import Image
class ImageClassifier:
"""画像分類器"""
def __init__(self, model_path, class_names):
self.model = models.resnet50(pretrained=False)
self.model.fc = torch.nn.Linear(2048, len(class_names))
self.model.load_state_dict(torch.load(model_path))
self.model.eval()
self.class_names = class_names
self.transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
])
def predict(self, image_path):
"""画像を分類"""
image = Image.open(image_path).convert('RGB')
tensor = self.transform(image).unsqueeze(0)
with torch.no_grad():
outputs = self.model(tensor)
probs = torch.softmax(outputs, dim=1)
top_prob, top_idx = torch.max(probs, dim=1)
return {
'class': self.class_names[top_idx.item()],
'confidence': round(top_prob.item(), 3),
'all_probs': {
name: round(probs[0][i].item(), 4)
for i, name in enumerate(self.class_names)
},
}
@tool
def classify_image(image_path: str) -> dict:
"""画像を分類し、Grad-CAM付きの結果を返す"""
result = classifier.predict(image_path)
grad_cam_path = generate_grad_cam(image_path, classifier.model)
result['grad_cam_path'] = grad_cam_path
return result
Grad-CAM可視化
import numpy as np
import cv2
def generate_grad_cam(image_path, model, target_layer='layer4'):
"""Grad-CAMによる注目領域の可視化"""
from pytorch_grad_cam import GradCAM
from pytorch_grad_cam.utils.image import show_cam_on_image
target_layers = [getattr(model, target_layer)[-1]]
cam = GradCAM(model=model, target_layers=target_layers)
image = Image.open(image_path).convert('RGB')
transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
])
input_tensor = transform(image).unsqueeze(0)
grayscale_cam = cam(input_tensor=input_tensor)
grayscale_cam = grayscale_cam[0, :]
# 元画像にヒートマップを重畳
rgb_img = np.array(image.resize((224, 224))) / 255.0
visualization = show_cam_on_image(rgb_img, grayscale_cam, use_rgb=True)
output_path = image_path.replace('.jpg', '_gradcam.jpg')
cv2.imwrite(output_path, cv2.cvtColor(visualization, cv2.COLOR_RGB2BGR))
return output_path
VLMによる所見生成ツール
@tool
def generate_findings(image_path: str, classification: dict) -> str:
"""VLMで画像の所見を生成する"""
import base64
with open(image_path, "rb") as f:
image_data = base64.b64encode(f.read()).decode()
prompt = f"""
この画像を分析し、以下の形式で所見を生成してください。
分類結果: {classification['class']}(確信度: {classification['confidence']})
## 出力形式
1. 観察所見: 画像に見られる特徴を客観的に記述
2. 異常箇所: 異常が認められる場合、その位置と特徴
3. 重症度評価: 軽度/中度/重度
4. 追加検査: 推奨される追加検査や確認事項
※ 確信度が低い場合は明確に不確実性を記載してください。
"""
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o", temperature=0)
messages = [
{"role": "user", "content": [
{"type": "text", "text": prompt},
{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{image_data}"}},
]}
]
response = llm.invoke(messages)
return response.content
まとめ
| 項目 | ポイント |
|---|---|
| 画像分類 | ResNet + Softmax確率で分類 |
| Grad-CAM | 判断根拠をヒートマップで可視化 |
| VLM所見 | GPT-4oで構造化された所見を生成 |
| 統合 | 分類結果をVLMのコンテキストとして活用 |
チェックリスト
- 画像分類ツールを実装できる
- Grad-CAMの生成と解釈ができる
- VLMを使った所見生成を実装できる
- 分類結果とVLM所見の統合方法を理解した
次のステップへ
画像分析ツールを実装した。次は所見生成の高度化を学ぼう。
推定読了時間: 30分