0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RON-V #22 — 倒木・落下物・路面損傷を画像AIで検出する:Roboflow / Kaggle / YOLO11

0
Last updated at Posted at 2026-10-11

2026-10-11 更新

RON-Vへ画像AIを追加し、車載カメラ画像から 倒木・路上の落下物 / 瓦礫・路面の穴・陥没・道路冠水・煙 を候補として検出し、さらに画像全体を clear / low_visibility に分類できるようにしました。

この記事では検出対象、AI構築の考え方、学習・評価・実機配置の進め方を説明します。コマンドと再学習手順は #22補足 にまとめました。

RON-V 連載リンク
← 前の記事:#21 — AtomS3RのCAN・IMU・Shutdown制御
→ 次の記事:#22補足 — Kaggle学習・再学習の備忘録

はじめに — 今回できるようになったこと

RON-VではUSBカメラ(Logicool C270)で保存した道路画像に対し、次の状態を画像AIで判定します。

状況 AIの出力 使用モデル
倒木 fallen_tree のBBox road-v02
路上の落下物・瓦礫・枝など road_debris のBBox road-v02
路面の穴・陥没 pothole のBBox road-v02
道路冠水 flood のBBox flood-v05
煙 smoke のBBox smoke-v01
視界不良 clear / low_visibility の画像分類 visibility-v02

路面の「凹凸」は、ここでは pothole として学習した穴・陥没を指します。すべての段差や起伏を検出できるという意味ではありません。
倒木が通行を妨げるか、冠水が何cmあるか、といった判断までは行いません。画像と位置・時刻を残し、人が後から異常候補を確認することが目的です。

物体検出モデルでは、単に「ある / ない」だけでなく、画像のどこに対象があるかをBBoxで返します。

例えばroad-v02では、

fallen_tree  0.65
road_debris  0.31
pothole      0.88

のように、クラス名・confidence・位置を取得できます。

一方、visibility-v02は物体の位置ではなく、画像全体を、

clear
low_visibility

のどちらかへ分類します。

これらは自動運転の安全判断そのものではなく、RON-Vが記録した画像へ「道路異常候補」を付加するための補助判定です。

1. どうやって検出できるようにしたか

先に「道路で何を見つけたいか」と「必要な出力」を決めました。倒木や落下物には位置が必要なので物体検出、視界には画像全体の状態が必要なので画像分類を選びます。

道路障害物・冠水・煙は教師データと誤検出の傾向が異なり、視界はタスク自体が異なります。4モデルに分けることで、冠水だけ再学習する、モデルごとに閾値を調整する、といった更新ができます。道路障害物の3クラスは同じ場面の位置検出なので1モデルで扱います。

担当を次のように分けました。

場所・処理 役割
Roboflow 既存のラベル付きデータセットを取得
GitHub vision/ クラス変換・データ構築・学習呼出しを管理
Kaggle GPU YOLO11n / YOLO11n-clsを学習・評価
ONNX変換 Pi側の入力・出力仕様へ合わせる
Raspberry Pi 5 イベント画像をONNX Runtimeで推論

進め方は、対象とラベルを決める → データを整える → 学習 → 実画像で評価 → 別の教師画像で改善 → 再評価 → ONNX変換 → 実機確認です。
最初から数千枚へ自分でBBoxを付けるのではなく、既存データで最初のモデルを作り、C270の実画像で弱点を探します。

2. 道路障害物 — Roboflowから3クラスを抽出

道路障害物モデルの出発点として、Roboflow Universeの road-obstacle-detection を使用しました。

取得元: road-obstacle-detection Version 3

取得元はLaasyaのObject Detectionデータセットです。利用条件はデータセットのversionとともに記録し、モデルの配布条件とは分けて確認します。

RON-Vで取り込んだVersion 3の data.yaml は5クラスでした。

0: Pothole - v1 raw
1: barrier
2: fallen_tree
3: road_debris
4: traffic_cone

このうちRON-Vで直接使いたい3クラスだけを抽出しました。

fallen_tree
road_debris
pothole

再マッピングは次です。

new 0 = fallen_tree  <- old 2
new 1 = road_debris  <- old 3
new 2 = pothole      <- old 0

この3クラスを1つのYOLOモデルで同時に検出します。

3. Kaggleで学習用データを再構築

Roboflow Version 3をYOLO形式でKaggleへ取り込み、RON-V用データセットへ変換しました。

split images fallen_tree road_debris pothole
train 883 310 507 1256
valid 183 34 66 330
test 115 28 49 153

追加前のVersion 3抽出結果は合計1,181画像です。

クラスの列はBBox数です。元データにはDetection形式とSegmentation形式が混在していたため、polygonをBBoxへ変換し、YOLO Detectionの5列形式へ正規化しました。

invalid labels : 0
corrupt images : 0

4. road-v02 — 倒木の教師データを補って学習する

最終的な道路データには fallen-trees-detection Version 1 も加え、倒木の教師データを補いました。

構築時の記録は合計1,500画像(train 1,143 / valid 213 / test 144)。前節の1,181画像は追加前のVersion 3抽出結果です。画像数とBBox数を区別し、元画像のsplitを保ち、重複を除外します。

学習は yolo11n.pt から50 epoch、入力640、batch 16で行います。データを増やして再学習することと、前の best.pt を初期重みにして追加学習することは別です。この道路用スクリプトは前者です。

Kaggleの指標だけで採用せず、C270画像で倒木の見逃し、道路脇の小物体への反応、穴の検出を確認しました。最終モデルは fallen_tree / road_debris / pothole の3クラスです。

5. Flood — 濡れた道路と冠水を分ける

冠水検出では、単に「水の画像」を集めればよいわけではありませんでした。

誤検出しやすかったのは、

  • 濡れたアスファルト
  • 雨天道路
  • 水面反射
  • 夜間ライト反射

です。

そこで、これらをnegative / hard negativeとして追加し、通常の濡れた道路と、冠水候補を分ける方向で調整しました。

最終モデルは flood-v05 です。

validation:

Precision : 1.000
Recall    : 0.866
mAP50     : 0.875
mAP50-95  : 0.673

独立test 65枚を conf=0.50 で評価した結果:

TP = 7
FN = 0
FP = 0
TN = 58

C270評価9枚でもfalse positiveは0でした。これは画像単位の候補有無の結果で、BBoxの位置精度を含むmAPとは分けて読みます。正例7枚の小さいテストであり、一般の道路画像でも誤検出がゼロになる保証ではありません。

6. Smoke — 煙を1クラスで検出

煙は Roboflow RF100 smoke Version 1 を教師データに、YOLO11nを1クラスのObject Detectionへ学習しました。煙という出力だけで火災原因を判断するものではありません。

class : smoke

validation:

Precision : 0.978
Recall    : 0.912
mAP50     : 0.970
mAP50-95  : 0.721

最終モデルは smoke-v01、初期confidenceは 0.20 です。

7. Visibility — 視界不良は画像全体を分類

視界不良は画像全体の分類にしました。PHD Project Version 5 の Fog を low_visibility、Normal / Cloudy / Sunny を clear へまとめ、YOLO11n-clsを学習します。主に霧に似た見え方が出発点です。雨・雪・逆光・夜間をすべて同じ精度で扱えるとは確認していません。

clear
low_visibility

通常道路の誤判定を減らすため、別の道路画像を clear として追加しました。道路障害物の有無と、視界の良し悪しは別の意味です。

最終モデル visibility-v02 の独立test 160枚:

accuracy : 0.9812

low_visibility:

precision : 0.9487
recall    : 0.9737
F1        : 0.9610

8. hard negativeで精度を上げる

今回の学習で効果が大きかったのは、単純に正例を増やすことより、何を誤検出しているかを確認することでした。

改善は次の順序で行います。

  1. 実画像で見逃しと誤検出を確認する。
  2. 道路という運用場面に合う別の画像を集め、人が対象の有無とラベルを確認する。
  3. trainへ追加して再学習する。
  4. 固定した評価条件で、誤検出が減り、見逃しが増えていないかを確認する。

物体検出のnegativeは、対象がないことを確認した画像と空のラベルです。対象が写っている画像のラベルを消すと、誤った教師データになります。

flood-v05は38枚のhard negative候補からtrain側28枚だけを使い、追加98ファイルを生成しました。元のvalid / test分割を保ち、C270評価9枚と自宅内ベンチ画像は学習へ入れていません。

区分 役割
train 重みを学習する
valid / val 学習中にモデルを選ぶ
test 固定条件で性能を確認する
C270評価 車載カメラとの見え方の違いを確認する

同一画像や加工画像を別splitへ移さないようにします。C270評価を繰り返して開発上の判断に使ったため、採用後の性能評価には新しい走行画像も必要です。
confidenceはモデル間で同じ意味の確率として比較せず、モデルごとに閾値を決めます。

9. ONNXへ変換してRaspberry Pi 5へ

学習済みモデルはRaspberry Pi 5で実行するためONNXへ変換しました。

road-v02.onnx
flood-v05.onnx
smoke-v01.onnx
visibility-v02.onnx

採用した best.pt をONNXへ変換し、入力サイズ・出力shape・クラス順・前処理をPi側と合わせます。モデル本体は現状runtime ZIPとして別管理しています。

FloodについてはPyTorch版とONNX版をtest + C270の合計74枚で比較し、候補有無の判定不一致0を確認しました。この結果は全4モデルの同等性を確認した意味ではありません。再学習・再変換したモデルでも比較し直します。

10. 同じAIを動かし、再学習できるために残す情報

同じAIを動かすにはソースコードに加えてモデル本体が必要です。再学習には元データ、分割、学習条件、学習用の .pt も必要です。

  • GitHubのcommit、実行コマンド、Python / package / GPU。
  • 元モデル、データのworkspace / project / version、出典と利用条件。
  • クラス順、split、manifest、hard negativeの選び方。
  • args.yaml、results.csv、best.pt、ONNX、SHA256。
  • Pi側の入力サイズ・前処理・閾値・配置先・動作確認方法。

Notebookを実行の入口とし、処理本体はGitHubに残します。Kaggleの一時領域が消える前に学習結果を保存します。学習結果ZIPに画像が含まれていなければ、それだけではデータを復元できません。

道路・煙・視界の再構築スクリプトは vision/ にあります。冠水の最終データ作成セルは、確認できた記録には全文がなく、GitHubにも未収録です。#22補足 に実行できる範囲と必要な保存物を明記しました。

ONNXは、学習済みAIモデルを保存するファイル形式です。ONNXに変換しても、それだけで自由に配布できるようになるわけではありません。

GitHubでモデル本体を公開する前に、学習の出発点に使ったYOLO11などの元モデルと、学習に使った画像データについて、それぞれの利用条件を確認します。出典の表示、ライセンス文の添付、関連するソースコードの公開など、求められる条件があれば、それを満たしてから配布します。

例えば、設定ファイルに学習画像のライセンスとして CC BY 4.0 と書いてあっても、それだけではYOLO11側の利用条件まで確認したことにはなりません。設定ファイルの記述が正しいかも、画像の取得元の説明と照合します。つまり、「学習に使えるか」と「作ったモデルをどの条件で配布できるか」の両方を確認する、という意味です。

確認先: Ultralyticsのライセンス案内 / Roboflowの利用規約。

11. 最終的に採用した4モデル

profile 何を見るか task Raspberry Pi側の初期閾値
road-v02 倒木 / 路上落下物 / 路面の穴・陥没 detection 0.20
flood-v05 道路冠水 detection 0.50
smoke-v01 煙 detection 0.20
visibility-v02 clear / low_visibility classification top-1

road-v02の最終validation:

Precision : 0.726
Recall    : 0.616
mAP50     : 0.683
mAP50-95  : 0.370

fallen_tree mAP50 : 0.657
road_debris mAP50 : 0.620
pothole     mAP50 : 0.772

これでRON-Vは、電波・位置・車両情報だけでなく、イベント発生時の道路画像へ、

倒木
落下物 / 瓦礫
路面損傷
冠水
煙
視界不良

という追加情報を付けられるようになりました。

RON-VではBUTTON / SHOCKで保存した event.jpg に4モデルを適用し、結果を vision_result.json へ残します。

次の RON-V #23 では、この4モデルをRaspberry Pi 5上で動かし、AtomS3RのBUTTON / SHOCKから自動推論する実装を扱います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?