【個人メモ】リアルタイム計測＆判定　オフライン画像処理検査システムの仕様整理


ほぼ個人的なメモ
どのような経緯で開発に至ったかを簡単にまとめる.

なお、普通の開発と比べると、かなりガチ構成で複雑なのもあって、
納品までの区切りとして、簡単でもいいので目次としてまとめたい気持ちが強い

# 開発構想

顧客から、「従来の長物の検査を行う画像処理のアルゴリズムをリアルタイムで計測するシステムを作ってほしい」という要望があった。

ローラに生地が挟まっていて、ちょうど光っている部分から鉛直上方向に平行光を照射、その像をラインカメラ(※写真に出てないけど)で撮像するといったもの。
生地には随所に穴や傷などが空いていて、LEDから透過光学系で直接カメラに画像としてその特徴が表れる。その評価値をリアルタイムで計測する。

右側と左側にモータが付いており、これが巻き戻し機構と送り機構に対応する。

![imagea001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281173/2955574f-8532-2ec5-fe87-718e4f849a08.jpeg)

生地は上記の前に、たるみを取り除くために、九十九折りにしてから、巻き戻し機構に巻き付ける。

![imageb001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281173/22525911-c3c9-25db-19d6-741eeed90f14.jpeg)


カメラの分解能はおよそ1µm、サンプルの長さは4m。
全体で処理する画素数は最大4000000画素で、カメラのチャネル数は16384。
従って、1回の測定あたり**64GB近くのデータ**を取得、判定する必要がある。

# システム構成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281173/fc92d4f5-80fb-63fc-290d-a2bf0b928afb.png)


## 言語

C++でアルゴリズムと機器制御、
C#(.NET Core 5~6)でバックエンド、
ASP.NET MVC Coreの枠組みを利用して同時にフロントエンドを実現する。

### ASP.NET MVC Core 5を採用した理由

- Visual Studio 2019 ProfessionalをIDEとして採用していて、アルゴリズム開発も同様におこなっていた。そのため、移行しやすい。
- アルゴリズムにもリアルタイム性が要求されるため、通常のWindowsアプリではGUIの描画などで制御やアルゴリズムの動きを阻害する危険性があると考えた。　→　サーブレットを適用した最大の理由
- 試作機なので、LTSではないCore 5でも十分だと判断。いずれCore 6でやれるやろ、という気持ちもある。

### サーブレットを採用したことでの恩恵

- HTML5やajaxが使える関係でUIがすごくリッチになった。特にDataTablesライブラリがすごい輝いている
- アプリを１から実行しなくても、フロントエンドのデバッグが開発者モードで容易にできる
- Windowsアプリでありがちな「５秒経つとアプリが停止した動きをする」みたいな特殊な挙動がない
- データベースがEF Code Firstを採用したおかげですごく使いやすくなった（当初使う予定がなかったので、すごい効いている）。
- HTMLがあるのでそこでヘルプを書けば、マニュアル替わりに活用できる。仕事一つ減った。

### 逆にサーブレットを使ってつらかったこと

- セキュリティ対策。かつてのJavaのサンドボックス機構を彷彿とさせるかのようにローカルファイルの保存は一苦労させられる
- ASP.NETはIISを使って実行したが、Windows認証によるアクセス権問題がすごく大変だった。 →[IIS公開時の課題の例](https://qiita.com/belre/items/65422a8ee154476fd99b)
- IISに対してCPU占有率が過剰になると、ブラウザ側の動きが止まってしまう件について。CPUで丸々計算していると、突然動かなくなることもしばしば。個人的には、エッジコンピューティング用のフレームワークを採用する方が今回の方針には合っていると思う。**（おすすめ教えて！！）**
- 他のローカルアプリを並行して実行する場合に、スマホみたいにアプリを自動で開いてくれるみたいなのを実装したかった。でも時間や知識がなくて今回は断念。

### C++で実装してすごく勉強になったこと

- **std::atomicが神過ぎる**。アルゴリズムを実行するときに、最適化-O2(Releaseモード)での性能の担保が必要で、気づかないところでコードの最適化が行なわれている危険があった。std::atomicがあるだけで、排他制御やデバイス制御で最適化されてしまう変数を随所に抑えることが出来るのがすごくうれしかった。~~Volatileは死んだのだ~~
- **デバイスの制御権限**を与える処理を内部で与える必要があって、その仕組みを色々考える必要があってすごく大変だった。どうしたらそういうクラスやインタフェースを定義できるか、色々考えるのは勉強になった。今回はそのあたりはすべて自作。
- アルゴリズム自体は単純だが1回あたりの**データ量**が恐ろしく、ローカル画像保存するだけであっという間に1TBに達する。また、それを一時的に確保するための**Non-Paged Memory**の取り扱い方も学ぶ必要があって、それをうまく活用できたからこそ、高速なリアルタイムを実現できたといえる
- **Resharper**がすごい役に立った。IDE補助は、Visual Studioでも不足な点が多くて・・・。　特に、ネーミング統一をするためにCtrl+Rを押して変数名やクラス名をリネームできる機能がすごく使いやすかった。
- C#に準拠したログを残す方法にすることでログ出力を標準化するようにした。 →[C++でNLogのラッパーを作る](https://qiita.com/belre/items/9703b38d28469b4ce49e)。これも結構役に立つ（今回はスタンドアロンでしか使わんので、セキュリティへの考慮はあまりないけど）

### 機械の分野で勉強になったこと

- 生地は巻き取り続けると、生地の厚みによってはモータにすごい太さで巻き取られることがある。そのため、長く巻き続けると、カメラで撮像する場所での送り速度が上がってしまうのだ。撮像信号や生地にかかる応力の安定化のため、フィードバック制御を組んだが、ここで組んだ**PI制御**の考え方は結構面白かった。
- 空気圧によって駆動部を移動させたり、磁気ステージを使って物を動かしたりするなど、色々な部品の使い方を知る必要があって、とても面白かった。
- モータはステッピングモータを採用。この際に、加速度制御に関して色々吟味しないとカメラがきちっと撮像してくれないので、そのあたりの考察を色々する必要もあった。
- システムタイマを導入することで制御の安定化を図った。本来なら、もっと高速性が必要なのでPCだと限界があるのだが、それでも極端にリアルタイム性が必要なところが数少なかったのは思う。特に、エンコーダ信号を一定の時間間隔で拾うために、**50msぴったりで制御する**のは、システムタイマのおかげで実現できたといえる

# 記事のまとめ

今後、知識として補充すべき部分や、IoT分野などに応用できそうな技術について、ここを更新してどんどん追加する予定

## 制御

https://qiita.com/belre/items/aec2ccb757b9a18397c6

https://qiita.com/belre/items/62d2c60682a6d59ba823

## C++コーディング技術

https://qiita.com/belre/items/2e505c8b6717572ddbe3

## C++⇔C#ラッパー

https://qiita.com/belre/items/ea4a3212e8d7aa8829dd

https://qiita.com/belre/items/9703b38d28469b4ce49e

## Emulatorモード

https://qiita.com/belre/items/341c756b7ba89d4f0b6c


## ASP.NET MVC, Entity Framework, IIS

https://qiita.com/belre/items/e43a535c6a08bc519ee1

https://qiita.com/belre/items/65422a8ee154476fd99b