🎯 はじめに
「AIで遊び心あるイベントをやってみたい」
そんな思いつきから始まった、ベストスマイル賞自動採点システム。
恒例の社内ゴルフコンペで、参加者全員写真を撮影。
そこからAIが“最もいい笑顔”をスコア化し、自動で表彰スライドを作る。
──そんな試みを OCI Data Science を使って実現しました。
この記事では、
- なぜこれをやろうと思ったのか(背景)
- OCI Data Scienceをどう使ったのか
- 実際に動かしたコード
- 結果と得られた知見
をまとめています。
💡 ベストスマイル賞を作った経緯
毎年のコンペで恒例の表彰は「ベスグロ賞」「ドラコン賞」「ニアピン賞」。
そこに「ちょっとAIっぽい賞を加えたい」と考えたのがきっかけです。
- テーマ:楽しさ × データ × テクノロジー
-
狙い:
- イベントを盛り上げる
- AIを“身近で使える技術”として体験してもらう
- OCI Data Scienceの実践活用を試す
結果、写真から笑顔をスコアリングして、AIが優勝者を決めるというアイデアに着地しました。
AIでベストスマイルを採点する。
ChatGPTなどに代表される出来上がったツールを使うのも良いのですが、万が一に備えて完全ローカルでやろうと。
なにより、、おもしろそう!!
🧠 使用技術とアーキテクチャ
● 使用サービス
| サービス | 用途 |
|---|---|
| OCI Data Science | Notebook環境の構築・実行 |
| TensorFlow / DeepFace | 顔検出と笑顔スコア算出 |
| Matplotlib / Pandas | スコアの可視化・集計 |
| python-pptx | 表彰スライドの自動生成 |
● 処理の流れ
- 各組の集合写真(例:8組×4名=32名)をアップロード
- Notebookで一括実行
- DeepFaceで顔と感情(特に“happy”)を検出
- スコアをCSV出力
- 最高スコアを自動判定し、PowerPointに結果を書き出し
OCI DataScienceプロジェクトを作成(OCI側の準備)
プロジェクトを作成する。
プロジェクトの作成を押下
プロジェクト名を入れて、作成を押下
NoteBookを作成する
ノートブック・セッションの作成を押下
シェイプの選択
NoteBookの中でPip Installやモデルのダウンロードが必要なことと、
8チーム一括分析するためのパワーを確保するので
CPUリソース・NW帯域確保のため、今回は4OCPUとしました。
入力したら作成
NoteBookを開く
開くを押下
Karnelを選択する
今回はPython3(ipkarnel)を選択します。
Create NoteBookを押下
以下が開いたらOCI DataScienceの準備完了!
🧩 コード解説(NoteBook上の準備)
1️⃣ セットアップ
!pip install tensorflow==2.15.0 deepface==0.0.93 tf-keras==2.15.1 \
opencv-python-headless==4.11.0.86 matplotlib pandas python-pptx
以下のライブラリの依存関係の警告がでますが今回はスルーします。
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
oci-cli 3.66.2 requires click==8.0.4, but you have click 8.3.0 which is incompatible.
また、現在のNoteBookのバージョンだと、cv2を手動インストールする必要があるので、
以下で対策します。
!pip uninstall -y opencv-python opencv-contrib-python opencv-python-headless
!pip install opencv-python-headless==4.11.0.86
実行後、Karnel 再起動
import cv2
print("✅ OpenCV version:", cv2.__version__)
以下が出ればOK!
✅ OpenCV version: 4.11.0
最後に写真をアップロードするフォルダ「photo」を作成しておきましょう。
これで準備完了です!
2️⃣ AI分析とスコア集計
import os, glob, cv2, pandas as pd, matplotlib.pyplot as plt
from deepface import DeepFace
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
# ===== 環境設定 =====
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"
PHOTO_DIR = "/home/datascience/photo"
OUTPUT_CSV = os.path.join(PHOTO_DIR, "smile_scores_all.csv")
OUTPUT_PPTX = os.path.join(PHOTO_DIR, "smile_award_overall.pptx")
NAMES = ["Aさん", "Bさん", "Cさん", "Dさん"]
all_results = []
image_files = sorted(glob.glob(f"{PHOTO_DIR}/*.jpeg"))
for image_path in image_files:
group_name = os.path.splitext(os.path.basename(image_path))[0]
print(f"\n📸 分析中: {group_name}")
try:
detections = DeepFace.extract_faces(
img_path=image_path,
detector_backend="retinaface",
enforce_detection=False
)
except Exception as e:
print(f"⚠️ 顔検出に失敗: {e}")
continue
faces_sorted = sorted(detections, key=lambda f: f["facial_area"]["x"], reverse=True)
for i, face_data in enumerate(faces_sorted[:4]):
face_img = (face_data["face"] * 255).astype("uint8")
temp_path = os.path.join(PHOTO_DIR, f"temp_face_{group_name}_{i}.jpg")
cv2.imwrite(temp_path, cv2.cvtColor(face_img, cv2.COLOR_RGB2BGR))
area = face_data["facial_area"]["w"] * face_data["facial_area"]["h"]
try:
analysis = DeepFace.analyze(
img_path=temp_path,
actions=["emotion"],
detector_backend="retinaface",
enforce_detection=False
)
emotions = analysis[0]["emotion"]
happy_score = round(emotions.get("happy", 0.0), 2)
except Exception as e:
print(f"⚠️ {group_name} の {NAMES[i]} の分析に失敗: {e}")
happy_score = 0.0
all_results.append({
"組": group_name,
"名前": f"{group_name}_{NAMES[i]}",
"笑顔スコア": happy_score,
"顔面積": area
})
# ===== 集約・同点対応 =====
summary_df = pd.DataFrame(all_results)
summary_df = summary_df.sort_values(
by=["笑顔スコア", "顔面積"], ascending=[False, False]
).reset_index(drop=True)
top_score = summary_df.iloc[0]["笑顔スコア"]
tied = summary_df[summary_df["笑顔スコア"] == top_score]
if len(tied) > 1:
winner = tied.sort_values(by="顔面積", ascending=False).iloc[0]
print(f"🤝 同点ですが、顔面積が広い {winner['名前']} さんを総合優勝に決定!({winner['笑顔スコア']}点)")
else:
winner = summary_df.iloc[0]
print(f"🏆 総合ベストスマイル賞:{winner['名前']} さん!({winner['笑顔スコア']}点)")
plt.figure(figsize=(10,6))
plt.bar(summary_df["名前"], summary_df["笑顔スコア"], color="orange")
plt.title("総合ベストスマイルスコアランキング(全8組32名)", fontsize=14)
plt.ylabel("笑顔スコア(happy%)")
plt.xticks(rotation=45, ha="right")
plt.tight_layout()
plt.show()
summary_df.to_csv(OUTPUT_CSV, index=False, encoding="utf-8-sig")
print(f"\n✅ すべての結果を保存しました: {OUTPUT_CSV}")
prs = Presentation()
slide_layout = prs.slide_layouts[5]
slide = prs.slides.add_slide(slide_layout)
title = slide.shapes.title
title.text = "🏆 総合ベストスマイル賞発表"
p = slide.shapes.add_textbox(Inches(1), Inches(2), Inches(8), Inches(2))
tf = p.text_frame
tf.text = f"総合優勝:{winner['名前']} さん\n笑顔スコア:{winner['笑顔スコア']}点"
tf.paragraphs[0].font.size = Pt(28)
tf.paragraphs[0].font.bold = True
tf.paragraphs[0].font.color.rgb = RGBColor(255, 140, 0)
prs.save(OUTPUT_PPTX)
print(f"🎉 総合表彰スライドを保存しました: {OUTPUT_PPTX}")
セットアップが完了し、コードが用意できたら画像をphotoフォルダにアップして準備完了です。
📈 結果と反応
実際に出力されたスコアランキング👇
今回は、NoteBook上で結果をグラフで可視化する仕組みと、スコアを把握するために分析結果をCSV出力するようにしました!
グラフから高得点者が多いことがわかります。素敵です☺️
詳細なスコアの確認のためCSVの中身を確認します。
100点満点の方が4名いらっしゃいますが、今回は同点だった場合を考慮して
笑顔の面積が広い方に加点するような仕組みを実装しています。
優勝は OUT_Team3のDさんでした!ベストスマイル賞おめでとうございます!
PPTスライドも自動生成され、
表彰式では「AIが決めたスマイル賞」として大盛り上がり!
🗣️ 所感と学び
- OCI Data Scienceはセットアップが簡単で、数分で動作環境が整う
- DeepFaceは軽量で精度も高く、笑顔スコア用途には最適
- AI活用は「業務効率化」だけでなく「体験を豊かにするツール」にも使える
特に印象的だったのは、
“AIが自分の笑顔を採点してくれる”
という仕掛けが、参加者全員の関心を引き、
AI=身近で楽しいもの として浸透したことです。
🚀 まとめ
| 観点 | ポイント |
|---|---|
| 技術的要素 | DeepFace(感情分類)+ TensorFlow |
| インフラ | OCI Data Science + Object Storage |
| 成果物 | CSVランキング + PowerPoint自動生成 |
| 成果 | AI表彰で社内イベントを盛り上げた 🎉 |
🔗 次の展開
次は「ベストドレッサー賞」もAIで判定予定。
服の色彩・コントラスト・明度をスコア化して、
“最もスタイリッシュな人”を選ぶAIを構築中です。
OCIの機能で簡単にAIの取り組みが実装できました。
他のユースケースも実装可能と思います。
ぜひ実践のご参考にしていただければと思います!















