画像処理で遊べるデモサイト「IP World」

## はじめに
画像処理(Image Processing)で手軽に遊べるデモサイトをFlaskで作りました。

<img width=400 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431306/e2116533-86cc-83be-342e-46995979577b.gif>

画像処理の基本的なアルゴリズムを実装しているので、画像処理を今まで触った事がないという人は、良かったら触ってみて下さい。スマホでも遊べます。

↓スマホでの表示
<img width=400 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431306/445790e3-48ad-4a82-713f-4fa361af5b20.png>

■デモサイト
[IP World](https://jw-automation.com/ipworld)

■環境
Python, AWS(Lightsail), Flask, Docker

## デモ一覧
デモの一覧は、以下の通りです。

|#|タイトル|内容|
|:-|:-|:-|
|1|Binarization|画像の二値化(大津法, スライダーによる閾値変更)|
|2|Edge Detection|フィルタ処理によるエッジ検出|
|3|Dilate Erode|領域の膨張・縮小処理|
|4|Open Close|オープニング・クロージング処理|
|5|Thinning|細線化処理|
|6|Labeling|オブジェクトのラベリング処理|
|7|High Contrast|ヒストグラム平坦化による高コントラスト化|
|8|Denoise|メディアンフィルタによるノイズ除去|
|9|Unsharp Masking|先鋭化処理|
|10|Area Fitting|領域に対する矩形のフィッティング処理|

以下、個別に簡単なデモで紹介して行きます。

## 1. Binarization
こちらは、画像の二値化処理です。
いわずとしれた大津法を初期値として、閾値を0~255までスライダーで動かせるようにしています。

<img width=400 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431306/e2116533-86cc-83be-342e-46995979577b.gif>

10パターン程画像を用意しているので、スライダーで閾値を動かして色々と遊んでみて下さい。

## 2. Edge Detection
こちらは、微分フィルタを利用したエッジ検出処理です。
画像内のエッジ成分(輝度変化の大きい箇所)を抽出します。

<img width=400 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431306/08b066b5-6ecd-8609-bed5-593ba2a3c54d.gif>

フィルタ/処理は以下の6種類で、各ボタンで切り替えができます。
- Prewitt-h：Prewittフィルタ(水平方向)
- Prewitt-v：Prewittフィルタ(垂直方向)
- Sobel-h：Sobelフィルタ(水平方向) 
- Sobel-h：Sobelフィルタ(垂直方向)
- Laplacian：Laplacianフィルタ(2次微分)
- Canny：Canny法

最初の4つは一次微分フィルタであるため、輝度勾配がなだらかに抽出されていますが、二次微分フィルタのLaplacianでは、細かいエッジ成分が抽出されているのがわかると思います(一方で細かいノイズ成分も強調される)。

Canny法はフィルタではなく、細線化と閾値判定を含むエッジ検出用の処理なので、他のフィルタ処理に比べて、エッジ成分が明確に抽出されている事がわかります。

## 3. Dilate Erode
こちらは二値化画像における、領域の膨張(Dilate), 縮小(Erode)処理です。

<img width=400 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431306/713db017-c728-0cdf-cac5-faec272030c9.gif>

大津法で元画像を二値化した画像に対し、「Dilation」を押すと黒いピクセルの領域が膨張し、「Erosion」を押せば領域が縮小して行きます。

ボタンの押下に応じて処理が走るので、連続して押したり、交互に押したりと、画像がどのように変化するのか試してみて頂ければと思います。

## 4. Open Close
こちらも処理自体は膨張・縮小処理ですが、膨張と縮小を複数回繰り返す事で穴埋めやノイズ除去を目的としたOpening, Closing処理です。

<img width=400 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431306/5313fd99-b0de-250b-ac07-b9b1d01b587f.gif>

- Opening：複数回の縮小処理 ⇒ 複数回の膨張処理
- Closing：複数回の膨張処理 ⇒ 複数回の縮小処理

Openingは先に縮小処理をするので、ノイズや小さい領域を除去する効果があります。一方Closingは、膨張処理を先に実施するため、領域内の穴を埋めるような動きをします。

処理の繰り返しは、それぞれ3回ずつに設定しています。

## 5. Thinning
こちらは二値画像の細線化処理です。

<img width=400 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431306/cd117ef2-cd80-a077-b69f-e1c69ac8bea3.gif>

先ほどまでの縮小処理は、画素の外側を削って行く処理でしたが、こちらは、領域の中心の1画素分だけを残すように線を細くする処理になります。

アルファベットのようなケースでは、アルファベットの形状を構成する骨格の要素を抽出できている事がわかると思います。

## 6. Labeling
こちらは二値化画像において、連続した領域にラベルを付けて行くラベリング処理になります。

<img width=400 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431306/099258bc-046d-968a-f2e7-0f6ced020548.gif>

ピクセルが連続した領域に同一のラベルを振るため、独立したオブジェクトの個数を抽出する事ができます。

今回は元画像にそのままラベリング処理を適用していますが、膨張・縮小処理と組み合わせ、ノイズや穴を埋めた上でこのラベリング処理を施す事で、より綺麗にラベルを振ることができます。

## 7. High Contrast
こちらはヒストグラム平坦化を使った高コントラスト化処理になります。

<img width=400 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431306/35669ac7-b2e0-6f69-9b8a-d1d85545eca6.gif>

元画像は低輝度領域に画素値が集中しており、コントラストが低い状態のため、RGB空間で画素値が一定に分布するように(ヒストグラムが平坦になるように)処理し、コントラストを上げています。

RGBそれぞれでヒストグラム平坦化をかけると全体の色味が崩れるため、RGB空間全体でヒストグラム平坦化をかけています。

パッと見では暗くて何も見えない画像でも、実はこれだけの情報を持っている(綺麗に再構成できる)というのは面白いですね。

写真を撮った時に、やたらと暗くなってしまったからと言って、諦めなくても良いかもしれません。

## 8. Denoise
こちらはメディアンフィルタを使ったノイズ除去処理です。

<img width=400 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431306/884fc9c7-28c0-2ad8-4e09-973fb1ba6121.gif>

各画素値を、対象の画素を含む周辺9画素の中央値(メディアン)で置き換える事によって、ごま塩型のノイズを除去する事ができます。

シンプルな処理でノイズが除去できる一方、全画素を周辺画素の中央値で置き換えてしまうため、全体的に少しぼやけた画像になってしまっているのも見て取れるかと思います。

## 9. Unsharp Masking
こちらは画像のボヤけた輪郭を強調する先鋭化処理(アンシャープマスク処理)です。

<img width=400 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431306/f112f2d8-0eea-7d34-599c-6e911364499f.gif>

元画像を平滑化した画像と元画像の差分要素を求め、この差分を元画像に加算する事で、輝度変化のある箇所を強調する処理になります。

先鋭化処理によって、ぼやけた元画像がくっきりとした画像になっている事がわかると思います。

## 10. Area Fitting
こちらは二値画像の各領域に対するフィッティング処理です。
矩形や円をフィッティングさせる事で、領域の大まかなサイズを抽出する事ができます。

<img width=400 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431306/20434388-e8a2-7025-2afc-92f5fe1ab5d7.gif>

フィッティングは以下の4種類です。
- Rect：外接矩形(回転なし)
- Rotate：外接矩形(回転あり)
- Circle：外接円
- Ellipse：楕円フィッティング

それぞれ対象領域に合わせて、矩形や円がフィッティングされている事がわかるかと思います。

ざっくりのサイズであれば外結矩形、対象が種や細胞のような形状の場合は、楕円フィッティングが良さそうですね。

## まとめ
いかがだったでしょうか。

ちょっとした復習と備忘も兼ねて作ってみましたが、画像処理に触って楽しんで頂けたのであれば幸いです。

機械学習の労力の8割がデータ収集と前処理と言われるように、画像においても前処理観点での画像処理は重要な上、そもそも、機械学習を使わず画像処理だけで落とせればベストではあるので、画像処理も高いレベルで使いこなせるようになって行きたいですね。

■参考
Qiita記載記事
・[AIで遊べるデモサイト「AI World2」](https://qiita.com/jw-automation/items/3d8e8510f22ae72e3d2e)
・[AIで遊べるデモサイト「AI World」](https://qiita.com/jw-automation/items/5cbb1c1cad08010dd823)
・[Deep Metric Learning](https://qiita.com/jw-automation/items/7bbe1c872fcec7fa6c1d)
・[Deep Learning for Image Denoising](https://qiita.com/jw-automation/items/f942ea0c6a02e8e50fa2)
・[ホテル暮らしはクラウドである](https://qiita.com/jw-automation/items/2fcd6f6e15e470196646)
・[AIの実業務適用に必須なHITLという考え方と、HITLを加速させるAI×RPA](https://qiita.com/jw-automation/items/0fc9c1b9764233975ab9)
・[RPAの推進に必須なRPAOpsという考え方](https://qiita.com/jw-automation/items/53c45b7dfc7a5865c5ff)
・[VBAが組める人ならRPAは簡単に作れるという罠](https://qiita.com/jw-automation/items/38c28016bf5162e76c59)

個人ブログ
・[キャリア・フレームワークなど](https://jw-automation.com/blog)