本記事はQiita Advent Calender 2025 わたなべの15日目です!
15日目は、私渡邊が作成します!
本日は話題の熊さんと仲良くなるための記事を執筆します。
![]()
ある日♪街の中♪くまさんに♪出会った♪
熊さんを検知するAIカメラを作ろう!
今年の漢字にもなった「熊」
皆さん仲良くなりたいですよね。
ということで、熊さんが現れたら通知してくれるAIカメラを作って、出現したら会いに行こうと思います!
私は小売業の企業に勤めておりますので、以前お客さまを分析するAIカメラを作った際は、カスタマーアナライザーと名付けました。差し詰め今回は熊さんアナライザーといったところでしょうか。
真相
東北の店舗に熊が出てシャレにならんので、出現に合わせて適切な防護体制、避難誘導をとれるようにリアルタイムに熊を検知するAIカメラを実装していきます。
一旦GitHubにあった学習データを利用
都合よく熊さんを学習してるモデルなんかないよなあ・・・
と思っていたら普通にありました。さすがのOSS文化ですね。
Hugging Faceも探してみましたが、Google Colabのファイルがついており、サクッと実行できそうだったこちらのGitHub Repositoryをお借りすることにしました。
こちら私が実行したGoogle ColabのJupyterです。
お借りしたリポジトリそのままでは動かず。
1. torchのバージョンダウン
!pip uninstall -y torch torchvision torchaudio
!pip install torch==2.5.1 torchvision==0.20.1 torchaudio==2.5.1
ultralytics周りでエラーが出てしまったので、バージョンを下げました。
ultralytics / YOLOv8 は PyTorch 2.5 前提
weights_only=False がデフォルト
セキュリティ設計変更前
✔ 世界中の YOLO ユーザーがこの方法を取っています
と、チャッピーに言われ、本当か?
と思いましたが、まずは動かすことが最優先だったのでひとまず従いました。
2. pathの修正
- !git clone https://github.com/danort92/Bear-Detection.git
+ !git clone https://github.com/danort92/Bear-Detector.git
%cd Bear-Detector
ここ以外にもちょくちょくBear-Detectionとパスを指定しておりエラーの出る箇所があるので、都度直していきましょう。
3. opencv-python周りの修正
diff --git a/process_video_with_yolo.py b/process_video_with_yolo.py
index 1111111..2222222 100644
--- a/process_video_with_yolo.py
+++ b/process_video_with_yolo.py
@@ -1,9 +1,12 @@
-def process_video_with_yolo(video_path, model, output_path=None):
+def process_video_with_yolo(video_path, model, output_path=None, conf_thres=0.01):
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
print(f"Error opening video file: {video_path}")
return
+ # Video properties
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS)
@@ -15,26 +18,44 @@ def process_video_with_yolo(video_path, model, output_path=None):
output_path,
cv2.VideoWriter_fourcc(*'mp4v'),
fps,
(frame_width, frame_height)
)
- while cap.isOpened():
+ frame_idx = 0
+ while True:
ret, frame = cap.read()
- if not ret:
- break
+ if not ret:
+ print("Video finished")
+ break
+
+ frame_idx += 1
+ if frame_idx % 300 == 0:
+ print(f"Processed {frame_idx} frames")
- frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
- results = model.predict(frame_rgb, verbose=False)
+ # YOLO inference
+ results = model.predict(frame, conf=conf_thres, verbose=False)
if len(results[0].boxes) > 0:
- print("Bear detected!")
+ print("Bear detected!")
- for bbox in results[0].boxes.xyxy:
- x1, y1, x2, y2 = map(int, bbox)
+ for box in results[0].boxes:
+ x1, y1, x2, y2 = map(int, box.xyxy[0])
+ conf = float(box.conf[0])
+ cls = int(box.cls[0])
+
+ label = f"Bear {conf:.2f}"
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
- cv2.putText(frame, 'Predicted BB', (x1, y1 - 10),
- cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
+ cv2.putText(
+ frame,
+ label,
+ (x1, y1 - 8),
+ cv2.FONT_HERSHEY_SIMPLEX,
+ 0.5,
+ (0, 255, 0),
+ 2
+ )
if output_path:
out.write(frame)
cap.release()
if output_path:
out.release()
- cv2.destroyAllWindows()
cv2.destroyAllWindows()はColabで実行するとエラー出ます。
その他、thresholdを指定できるようにしてみたり、進行状況が見えるようにしてみました。
モデルの検証
まずは確実に反応してもらうためのポジティブな映像データを用意します。
![]()
まあ、ふつうこんな感じでのそのそ歩くのイメージしますよね
最近youtube shortなんかでよく流れてくるsora様に熊さんの動画を作ってもらいました
![]()
誤検出ちょくちょくしてるのは
conf_thres=0.01なんかにしてるせいですね。
こんな値で実行してるあたりで結末が見えてしまいますが
実際の映像で試してみる
はい、こんなことがありました。
![]()
一応速度2倍にしています。
とはいえ、皆さんのイメージする熊さんのスピードとは全く異なるのではないでしょうか?
まず1回目。
conf_thres=0.2で試してみるも全く検出されず。
まあ、ここまでは想定内。
次、最悪害獣として検出さえしてくれればよいと思い、conf_thres=0.01で実行。
うおおおおお!!!!!
![]()
はい、終了
普通に誤検知ですね
あとは、店内に侵入した映像にも試してみましたが検出されませんでしたね。
しっかりと店舗にくる熊さんを検知するためには、実際に店舗でとられた画像を利用して転移学習する必要がありそうです。
チャッピーに方針を相談したところ
* Backbone を freeze して head だけ学習
* imgsz を上げて小物体特化
* hard example mining
という方向でファインチューニングすることがよさそうとのことでした。
熊さんアナライザーへの道はまだまだ長い。。。
お客さまの属性よりはるかに難しい印象です。
どうも、世間の熊さんのイメージと実際に侵入してくる熊さんとの差異があるため、それなりに学習させなければならない感じですね。
また、既設の防犯カメラは基本的に熊さんのためのものではないので、画角的な問題と被写界深度の問題がかなり大きい印象ですね。
![]()
高所作業時にはヘルメットをつけましょうね♪
防犯用途だと、後々見返す設計で、死角がないように安めのカメラを複数台つけることが多い印象。一方、熊さんをリアルタイムにバッチリ検出するためには侵入が想定される経路の手前から奥までバチッとピントを合わせることが重要です。
logicoolの1,900円webカメラで十分検出できたお客さまの属性とは大違いですね。
引き続き、頑張っていきます。







