SeiyaCM/KandenAiHackathonPosture2
Viewer • Updated • 52.5k • 953
English Summary A ResNet18-based posture classifier that detects four sitting postures of engineers (good, slouch, chin rest, stretch) for real-time fatigue monitoring. Trained on 52,500 synthetic images generated with Stable Diffusion + ControlNet, achieving 97.33 % validation accuracy with zero false positives on slouch detection. Exported as a lightweight ONNX model (~42 MB) for edge deployment on DGX Spark.
本モデルは、空間AIブレイン プロジェクトの一部として開発された、エンジニアの座り姿勢をリアルタイムに分類する画像分類モデルです。Webカメラ映像から以下の4つの姿勢を検出し、疲労度のスコアリングに活用されます。
| クラスID | クラス名 | 説明 | 疲労マッピング |
|---|---|---|---|
| 0 | good |
正しい姿勢で作業中 | 0.0(疲労なし) |
| 1 | slouch |
猫背で前傾した疲労姿勢 | 0.7(高疲労) |
| 2 | chin_rest |
頬杖をつく(ストレス・集中力低下) | 0.9(非常に高疲労) |
| 3 | stretch |
ストレッチ・伸び(休憩・回復行動) | 0.3(軽度) |
torchvision.models.resnet18)nn.Linear(512, 4) に置換| 指標 | 値 |
|---|---|
| 検証精度 (Validation Accuracy) | 97.33 % |
| 猫背 (slouch) 誤検知率 | **0 %**(False Positive ゼロ) |
| 名前 | 形状 | 型 | 説明 |
|---|---|---|---|
image |
(batch, 3, 224, 224) |
float32 | RGB画像。ImageNet正規化済み |
前処理パイプライン:
(pixel - mean) / std| 名前 | 形状 | 型 | 説明 |
|---|---|---|---|
logits |
(batch, 4) |
float32 | 各クラスのロジット値。softmax で確率に変換 |
import numpy as np
import onnxruntime as ort
import cv2
# モデルのロード
session = ort.InferenceSession("posture_classifier.onnx")
# 前処理
MEAN = np.array([0.485, 0.456, 0.406], dtype=np.float32).reshape(3, 1, 1)
STD = np.array([0.229, 0.224, 0.225], dtype=np.float32).reshape(3, 1, 1)
CLASSES = ["good", "slouch", "chin_rest", "stretch"]
def preprocess(bgr_frame):
rgb = cv2.cvtColor(bgr_frame, cv2.COLOR_BGR2RGB)
resized = cv2.resize(rgb, (224, 224))
tensor = resized.astype(np.float32) / 255.0
tensor = tensor.transpose(2, 0, 1) # HWC → CHW
tensor = (tensor - MEAN) / STD
return tensor[np.newaxis, ...] # (1, 3, 224, 224)
# 推論
frame = cv2.imread("test_image.jpg")
input_tensor = preprocess(frame)
logits = session.run(["logits"], {"image": input_tensor})[0]
# Softmax → クラス予測
exp = np.exp(logits - np.max(logits, axis=-1, keepdims=True))
probs = exp / exp.sum(axis=-1, keepdims=True)
class_idx = int(np.argmax(probs[0]))
print(f"Predicted: {CLASSES[class_idx]} ({probs[0][class_idx]:.2%})")
Apache License 2.0
@misc{kanden_posture_model_2025,
title = {Posture Classifier: ResNet18-based Engineer Fatigue Posture Detection},
author = {Team NANIWA-Factory},
year = {2025},
url = {https://huggingface.co/SeiyaCM/KandenAiHackathonPostureModel},
note = {Kanden AI Hackathon — Space AI Brain Project}
}