Simulinkでの画像オブジェクト検出について

# この記事で書いていること
この記事では、Simulinkを使って画像のディープラーニングのオブジェクト検出のモデルの構築方法についてTipsを書いています。公式文書ではわかりづらいことや可変長サイズの出力を扱うためのSimulinkの癖について理解しておく必要があり、つまずきやすいところかと思います。
# 環境
下のモデルを動かすためには、最低下記構成が必要です。
R2024bの
- MATLAB
- Image Processing Toolbox
- Computer Vision Toolbox
- Deep Learning Toolbox

※それ以前のバージョンでも使えますが、確認しているバージョンが上記です。
# 完成形
モデル構築の完成形を書きますと下記のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202697/c4227038-2422-d493-3e74-246189971309.png)

中身は、
1. Image From Fileブロックで画像を読込み（ここは画像が読み込まれればなんでもいいです）。
2. オブジェクト検出はDeep Learning Object Detectorブロックを使います。
3. 出てきた出力をMATLAB Functionブロックでフィルタリングして、必要なクラスの検出だけを取り出します。
4. その後は、後続の処理に繋げていけばいいのですが、ここでは可視化をしています。Draw Shapesで検出した矩形を元画像に書き込みますが、Draw Shapesブロックでは整数入力のようなのでuint16にBounding Boxの座標をキャストしています。

Tipsのポイントとしては、フィルタリングのところです。そのほかの部分はブロックが用意されており、適当に入力すればできると思いますので、ここでは割愛します。

フィルタリングの部分ですが、通常の使い方ではオブジェクト検出から出てきた出力はいくつかのクラスを含んでおり、その中から所望のクラスだけを取り出す、というのは良くある操作かと思います。
にもかかわらず、現状Deep Learning Object Detectorブロックではそのようなフィルタリングまではカバーしていないため、自分で書く必要があります。そのような独自の処理はMATLAB Functionブロック使うケース多いと思うのですが、ここにつまずきポイントがたくさん仕込まれています。

# フィルタリングのためのMATLAB Functionブロックの書き方
結論、下のようになります。
```MATLAB
function [bboxes_person, isDetected] = filter_detections(boundingBoxes, labels)

    % Check which labels correspond to persons
    isPerson = labels == objectDetector_labels.person_label;

    % If any person is detected, extract their bounding boxes
    if any(isPerson)
        bboxes_person = boundingBoxes(isPerson, :);
        isDetected = true;
    else
        % If no person is detected, return an empty array
        bboxes_person = zeros(0, 4, 'single');
        isDetected = false;
    end
end
```

Deep Leanring Object Detectorブロックから出てきたLabelはobjectDetector_labelsという謎の列挙型の変数配列になっているようです。その中から、例えばpersonクラスを抜き出すためには上記コードのようにXXXX_label、と後ろに_labelを付けてあげる必要があります。labels == 'person'とかやっても動いてくれません。これがわからずうまくフィルタリングできずに結構な時間さまよいました。この記事で一番伝えたいことはここです。
isDetectedはあってもなくても大丈夫です。

# モデルパラメータ設定
上のMATLAB Functionを動かすためには、上記だけでは不十分です。Simulinkはコンパイルして動かします。可変サイズの配列には特別にケアが必要です。通常一つの画像からオブジェクトがいくつ検出されるかは不定なので、Bounding Boxやラベルは可変サイズと考えられます。Deep Learning Object Detectorブロックでは、下のように、そのサイズを設定しておけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202697/17bd8c9e-ed6d-1b5f-35d6-b0c41dc187aa.png)
フィルタリングした後のbboxes_personの長さも不定なので考えられる最大長のサイズに設定しておく必要があります。これには、モデルエクスプローラーで変数のサイズを直接指定する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202697/bc9d3f5a-42a6-c311-3f75-3cd92549dddd.png)
からの
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202697/d8dcec90-1a8b-7417-f4d8-1ef20fc61794.png)
です。
[10,4]としているのが最大サイズとなっています。10が検出の個数、4はBounding Boxの左上のX＆Y座標、幅、高さの4つです。10の部分は入力する画像ごとに変わってくると思うので、適当に変えてください。また、可変サイズにチェック入れるのを忘れずに。。。

# コード生成について
最後にもう一つ注意点があります。
MATLAB Coder Interface for Deep Learningがインストールされていると、Deep Learning Object Detectorブロックをコード生成しようとします。その際、コンパイラはvisual C++ 2019をお使いください。MinGWだと蹴られます。MinGWしか使えないという場合は、上記アドオンをアンインストールするとインタプリタ実行してくれました。

# 終わりに
以上でTips紹介終わりです。MATLAB使いが、Simulinkを使う際にはいくつか注意点があります。気を付けつつ、ぜひ快適なMATLABライフをお過ごしください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202697/6ba8cb4b-718f-a6e4-c8db-fd8e3c8f31fd.png)