あなたに次の選択肢を用意するサイト
Thoth Coworker
~ プログラミングの次++ ~
For
新社会人 / 新学生 / 新院生 / 新研究者
カテゴリ
Webで画像のエッジ抽出してみる
Facebookシェア Twitterツイート LINEで送る
P
ポイント
Webで画像のエッジ抽出してみる
Webでお手軽に画像のエッジ抽出をしてみるための記事
  • Point 1
    Webブラウザでエッジ抽出
    ブラウザ上で簡単に画像処理が可能です.今回は画像の輪郭線を強調するエッジ抽出を行います.
  • Point 2
    OpenCV.jsを使用
    WebAssemblyを使用したOpenCV.jsを用いて高速な処理を行います.
P
ステップ概要
Webで画像のエッジ抽出してみる
エッジ抽出をする実装をする
PythonでWebサーバを立ち上げてWebエッジ抽出を実行します.
画像の読み込み部分の実装について解説します
画像の処理部分の実装について解説します
先ほどはあらかじめファイルを指定していましたが、今回はファイルを選ぶようにします.
Step
1
Web上で動くエッジ抽出を実装する
今回はOpenCV.jsのCannyによるエッジ抽出のチュートリアルを参考にしています.
: ブラウザで開く
https://docs.opencv.org/3.4/js_canny.html
または、Cannyの解説付きが良ければ
: ブラウザで開く
https://docs.opencv.org/3.4/d7/de1/tutorial_js_canny.html
を参照ください.

下記のようなフォルダ構成になるようにセットアップしていきます.
Folder : Web画像エッジ抽出プログラムのフォルダ
index.html
opencv.js
images/
index.png
上記のOpenCV.jsは下記より取得ください.
: ブラウザで開く
https://docs.opencv.org/master/opencv.js
画像はどのような画像でもいいので準備してindex.pngとしてください.
: ブラウザで開く
https://raw.githubusercontent.com/opencv/opencv/master/samples/data/pic3.png
それでは早速OpenCV.jsによるWebでのエッジ抽出のプログラムを書いてみます.
HTML : 指定した画像のエッジ抽出を行うプログラム
index.html
    
<html>
  <head>
    <script src="opencv.js" id="opencv-script" async type="text/javascript"></script>
  </head>
  <body>
    <canvas style="border: 1px solid black;" id="canvasInput"></canvas>
    <script type="text/javascript">
      let img = new Image();
      img.src = "images/index.png";

      function canny(){
	  let src = cv.imread(img);
	  let dst = new cv.Mat();
	  cv.cvtColor(src, src, cv.COLOR_RGB2GRAY, 0);
	  cv.Canny(src, dst, 50, 100, 3, false);
	  cv.imshow('canvasInput', dst);
	  src.delete();
	  dst.delete();
      }
      
      document.getElementById("opencv-script").addEventListener('load', () => {
	  if (cv.getBuildInformation)
          {
	      canny();
	  }else{
              cv['onRuntimeInitialized'] = canny;// WASM
	  }
      });      
    </script>
  </body>
</html>
    
  
Step
2
Webエッジ抽出を実行してみる
先ほどのindex.htmlのフォルダと同じところでPythonのWebサーバを暫定で立ち上げます.
(Step5のサンプルはWebサーバが必要ないですが、Step1のこのサンプルはimagesの画像をWebサーバで送らないとCORSエラーが発生します.)
Bash : PythonでWebサーバを立てる
    
      python3 -m http.server 8000 
    
  
Pythonを使って簡単にWebサーバを立てました.
Webサーバを立てる方法について、詳しくは「とりあえずWebサーバを立ててみる」をご参照ください.
とりあえずサーバを自分のパソコンで立ててみる
自分のパソコンにとりあえずシンプルなWebサーバを立ててみるためのページです.
リンク
Webサーバが立ち上がってそうなら、下記のURLを開いてください.
: ブラウザで開く
http://localhost:8000/index.html
下記のような画面になるはずです.
実行結果画面
Step
3
コード解説:画像の読み込み
画像の読み込みの部分について確認します.
    
      let img = new Image();
      img.src = "images/index.png";

      function canny(){
	  let src = cv.imread(img);
          //...
      }
      
      document.getElementById("opencv-script").addEventListener('load', () => {
	  if (cv.getBuildInformation)
          {
	      canny();
	  }else{
              cv['onRuntimeInitialized'] = canny;// WASM
	  }
      });      
    
  
まず、Image要素をnewして作ります.そしてimages/index.pngを読み込むように指定しています.opencvのスクリプトをaddEventListenerのloadで待機していますが、OpenCVのライブラリの読み込みと初期化に時間を要するためです.OpenCV.jsの準備ができた後にメインの処理であるcannyが実行されるようにonRuntimeInitializedのコールバックに指定しています.

canny関数の中ではcv.imreadを用いてimgタグの画像を読み込んでOpenCVで使えるようにして、Srcに代入しています.これで読み込みは完了です.
Step
4
コード解説:画像の処理
それでは本編のCanny関数についてです.
    
	  let src = cv.imread(img);
	  //出力用の画像を準備
	  let dst = new cv.Mat();
	  //カラー画像をグレー画像に変換
	  cv.cvtColor(src, src, cv.COLOR_RGB2GRAY, 0);
	  //Canny関数を用いて入力で与えたsrcに対してエッジ抽出を行い結果をdstへ
	  cv.Canny(src, dst, 50, 100, 3, false);
	  //dst関数を"canvasInput"のidのimgタグに表示
	  cv.imshow('canvasInput', dst);
	  //使用したものは片付け
	  src.delete();
	  dst.delete();
    
  
こちらも難しいことはありません.画像処理の出力用の画像dstをまず準備して、srcはエッジ抽出をするためにカラー画像からグレー画像に変換しておきます.変換後のグレー画像に対してCanny関数を使ってエッジ抽出を行っています.

エッジ抽出をした結果はdstに入れられたので、それを"canvasInput"のidを持つimg要素に表示します.終わったら使ったsrcとdstを削除して終了になります. Cannyのパラメータについては公式を参照ください.
Cannyのパラメータに関する公式ドキュメント
Step
5
選んだファイルのWebエッジ抽出を実装する
先ほどのプログラムの一部を変更して、ボタンを押してファイルを選びその画像に対してエッジ抽出をするような処理を作成します.
フォルダの構成は同じままで以下のようにindex.htmlを変えてください.
HTML : ファイルで画像を選択肢エッジ抽出を行うサンプル
index.html
    
<html>
  <head>
    <script src="opencv.js" id="opencv-script" async type="text/javascript"></script>
  </head>
  <body>
    <div>
      <canvas style="border: 1px solid black;" id="canvasInput"></canvas>
      <input type="file" id="fileInput" name="file" accept="image/*" />
    </div>
    <script>
      let img = new Image();
      
      function canny(){
	  let src = cv.imread(img);
	  let dst = new cv.Mat();
	  cv.cvtColor(src, src, cv.COLOR_RGB2GRAY, 0);	  
	  cv.Canny(src, dst, 50, 100, 3, false);
	  cv.imshow('canvasInput', dst);	  
	  src.delete();
	  dst.delete();
      }
      
      img.onload = canny;
      
      document.getElementById("fileInput").addEventListener('change', (e) => {
          let files = e.target.files;
          if (files.length > 0) {
	      img.src = URL.createObjectURL(files[0]);
          }
      }, false);
    </script>
  </body>
</html>
    
  
今回はfileInputのinputタグでファイル画像が選ばれると、末尾のchangeのコールバックが呼ばれます.そのe.target.filesに画像ファイルが収められているので、その値をimageに与えます.

imgにはあらかじめonload = cannyとしているため、画像が読み込まれるとcannyが実行されます.cannyの中身は先ほど変わらず、エッジ処理をした後にそれがcanvasInputに書き込まれます.

上記で実行すると下記のようにinputタグが見えるはずです.
実行結果画面
Done