2017年08月16日

画像の白色化について

夏休みがもう終わってしまいました。今回は機械学習の前処理で行われる画像の白色化のテストです。Pythonはよくわからないのでとりあえず今回はC++でEigen使ってやっています。白色化とは、共分散行列を対角行列とか単位行列にして無相関化しましょうという処理です。

まずは画像ですが、前回同様CIFAR-10のデータセットを使っています。白色化を行うときに特異値分解する場合、32x32x3だと結構な時間がかかりますので、今回はグレースケール化と諸事情により少しだけ縮小して30x30の900次元で取り扱っています。

参考にしたサイト[1]では、グレースケール化して色を反転?させていたようですので、それに倣いました。後、試してみたところGCN[2]をした方が結果画像に近づいたので、画像毎の正規化もしていると思います。

Eigenを使う場合、特異値分解するとUΛVに分解されますので、白色化の行列は下記のような感じになると思います。おそらく。
  JacobiSVD<MatrixXd> svd(covmat, ComputeFullU | ComputeFullV);
  MatrixXd inv_sigma = MatrixXd::Zero(dim, dim);
  for (int i=0; i<dim; i++) inv_simga(i, i) = 1.0 / (sqrt(svd.singularValues()[i])+EPS);
  MatrixXd white = svd.matrixU()*inv_sigma*svd.matrixV().adjoint();
実行結果

org0007.png image0007.png
org0029.png image0029.png
左がGCNして0〜1に線形変換したもの、右が[1]に倣ってEPS=0.1として白色化した画像です(見やすいように10倍に拡大したものです)。縮小したせいか微妙に違いますが大体一致していると思います。

[2]の方にありますが、ZCA白色化の各行を画像化すると、下記のような画像が得られましたので、多分処理としては合っていると思います。

white0094.png white0598.png

PythonとC++のどちらでやるかは未定ですが、次は畳込みニューラルネットワークを実装してみたいと思います。

[1] What is the difference between ZCA whitening and PCA whitening?
[2] データの前処理〜白色化 その2〜
web拍手 by FC2
posted by シンドラー at 18:06 | Comment(0) | Machine Learning | このブログの読者になる | 更新情報をチェックする

2017年08月02日

Pythonで画像処理 その2

昨日の続きです。とりあえず画像のデータセットを表示してみることにしました。CIFAR-10 and CIFAR-100 dataset[1]を使ってみようということで、Python用のデータをダウンロードしてみました。サイトにはunpickleの方法しか載っていなかったので、ググって[2]のサイトの方法を試させていただきました。サイトはPython 2系のようでしたので、3系にするためにunpickle関数を[1]に載っている3系のものに書き換えました。

ダウンロードしたデータを展開して実行してみると、下記のようなエラーが出ました。
  File "省略", line 26, in get_cifer10
      tr_data = data_dict['data']
  KeyError: 'data'
'data'なんて名前のキーは無いよというエラーのようでしたので、KeyErrorで検索してみると[3]のサイトがでてきました。
  print(data_dict.keys())
  dict_keys([b'batch_label', b'labels', b'data', b'filenames'])
キーを確認するためにdata_dict.keys()を実行してみたところ、上記のようにb'data'と頭にbがついていました。このbは何のbなんでしょうね。

とりあえずキーにすべてbをつけると、実行できました。後はconv_data2imageという関数も準備していただいていましたので、それを使って画像を表示してみました。
  img0 = tr_data10[0]   # 0番目の画像データ
  img1 = conv_data2image(img0)
  from skimage import io
  io.imshow(img1)
  io.show()

実行結果

dl2_figure_5.png

参考サイトと同じ画像が表示されましたので、とりあえず読み込みは成功したようです。

[1] CIFAR-10 and CIFAR-100 dataset
[2] Qiita - [Python]CIFAR-10, CIFAR-100のデータを読み込む方法
[3] stackoverflow - Reading Cifar10 dataset in batches
web拍手 by FC2
posted by シンドラー at 18:03 | Comment(0) | Machine Learning | このブログの読者になる | 更新情報をチェックする

2017年08月01日

Pythonで画像処理

Anaconda環境ですが、欲張って色々入れてしまうと競合するみたいですね。Anaconda 4.3.0(64ビット)だけインストールするようにしたら、前回のエラーが出なくなりました。

今回は機械学習で使うため画像の枚数を回転させて無理矢理増やす方法です。OpenCVに付属のcreatesamplesユーティリティの真似です。といってもあちらはx、y軸の回転や明るさの変化などもできますが。
  from PIL import Image
  import numpy as np
  import os

  # 「実践コンピュータビジョン」より改変
  def get_imlist(path, ext):
      # pathに指定されたディレクトリのすべてのext拡張子を持つ画像のリストを返す
      return [os.path.join(path,f) for f in os.listdir(path) if f.endswith(ext)]

  folder = "./image"
  filelist = get_imlist(folder, '.jpg')

  # 増やしたい枚数
  samples = 100
  # クラス番号
  classNo = 1

  # 増やした画像ファイル名とクラス番号のリスト
  txtfile = folder + "imagelist.txt"
  fout = open(txtfile, 'wt')

  # 画像ファイルの数だけ繰り返す
  for infile in filelist:
      # splitext: パス名を(root, ext)のペアに分割
      root = os.path.splitext(infile)[0]
      # -180.0〜180.0の回転角度を乱数で生成
      randDeg = 360.0 * np.random.rand(samples) - 180.0

      # 増やしたい枚数だけ繰り返す
      for idx in range(samples):
          # ゼロパディングしたファイル名を作成
          # 参考URL: http://www.lifewithpython.com/2015/10/python-zero-padding.html
          number_padded = '{0:05d}'.format(idx)
          filename = root + "_" + number_padded + ".png"
          # ファイル名をテキストファイルに書き出す
          fout.write(filename + ' ' + str(classNo) + '\n')
          # 画像を開いて乱数の角度で回転して保存
          out = Image.open(infile).rotate(randDeg[idx])
          out.save(filename)

  # ファイルを閉じる
  fout.close()
機械学習の時は画像のパスとクラス番号が書かれたファイルもよく使いますので、それも出力するようにしてみました。

forループのところなどはpythonに慣れていればもっとスマートに書けそうですが。後、既に混ざってしまってアレですが、シングルクォートとダブルクオートってPythonだとどういう扱いなんですかね。C言語だと文字定数と文字列の違いがあったのですが…。

実行結果

Lenna00000.png
Lenna.jpg1枚から回転した100枚が増えました。

参考文献
[1] Ja Erik Solem著,相川 愛三 訳,「実践コンピュータビジョン」,オライリー・ジャパン
[2] Bill Lubanovic著,斎藤 康毅 監訳,長尾 高弘 訳,「入門Python3」,オライリー・ジャパン
[3] Python Tips: Pythonでゼロパディングしたい
web拍手 by FC2
posted by シンドラー at 18:00 | Comment(0) | Machine Learning | このブログの読者になる | 更新情報をチェックする

2017年07月21日

Visual Studio Community 2017 + Anaconda 4.3.0 で Python環境の構築

AIとかDeep Learningが流行っていますね。色々なフレームワークが出来ていますが、Pythonを使ったものが多いので、Pythonの勉強をしてみることにします。環境としてはWindowsのVisual Studio使用です。

環境構築

まずはVisual Studioのインストールです。セットアップファイルが便利になっているので、インストールの時にPython開発にチェックしてインストールするだけです。どれを選べば良いのかいまいちわかりませんでしたが、Python 3 (3.6.0) (64ビット) Pythonネイティブ開発ツール、Anaconda3(4.3.0.1) (64ビット)辺りをインストールしました。

1. 新しいプロジェクトの作成→Python→PythonアプリケーションでPythonのプロジェクトを新規作成
2. ツール→Python→Python環境を選択→ドロップダウンリストから概要を選択→Anaconda3(2.7, 64-bit)を選択→新しいプロジェクトに対する既定の環境にする
3. プロジェクト→〇〇のプロパティ→全般→インタープリター:Anaconda 4.3.0(2.7, 64-bit)に変更

とりあえずはこのような感じです。最初Anaconda 4.3.0(3.6, 64-bit)のPython 3.6使用でやろうとしていたのですが、import numpy as npとすると、ImportError: DLL load failed: と出てうまくいきませんでした。[1]によると2.7にしましょうとありましたので、特にこだわりもないので2.7にしました。おそらく3.6でも動かせるのだと思いますので、必要があればやり方を調べたいと思います。

4. 文字コードの設定として1行目を下記のようにする
  # -*- coding: utf-8 -*-

後は[2]などを参考にMatplotlibを使って関数の描画や画像の表示を試してみました。

実行結果
figure_1.png figure_1-1.png
[2]の本を一通りやれば大体イメージは掴めそうですかね。

[1] NumPy library ImportError: DLL load failed: The specified procedure could not be found
[2] 斎藤 康毅 著,"ゼロから作るDeep Learning", オライリー・ジャパン
web拍手 by FC2
posted by シンドラー at 19:13 | Comment(0) | TrackBack(0) | Machine Learning | このブログの読者になる | 更新情報をチェックする

2017年07月12日

自己組織化マップを使った256色画像への減色

またあまり用途のない減色のテストです。以前はc-means法で減色していたのですが、時間がかかるのでもう少し別の方法で試してみることにしました。SOMも特に早い手法ではありませんが、c-means法と比べるとかなり速いです。SOMについては以前の記事でテストだけしていましたが、かなり前だったので書き直しました。

今回256色のパレットをSOMで学習しますので、マップとしては16x16となります。入力次元はRGBの3次元で、入力画像として512x512のLenna画像を使いました。

工夫した点?は下記のとおりです。
・最大試行回数maxTの1/3までは5x5のガウスフィルタ、残りの2/3は3x3のガウスフィルタを使用
・減衰係数alpha=0.1*exp(-2.3*(t/maxT))で計算し、初期0.1〜最終0.01ぐらいの係数になるように設定
・更新式はf(t+1)=(1.0-alpha*gauss)*f(t)+alpha*gauss*v(t)として、アルファブレンドで更新
・1回の更新は画像の全画素を使用するのではなくランダムに指定した数だけ選ぶ

実行結果
1回の更新で100画素ランダムに選んでマップ更新というのを500回繰り返した結果です(計50,000回の更新)。最初の数回は疑似輪郭が目立ってますが、Lenna画像は使用されている色が偏っている方なので、200回ぐらいの繰り返しで十分収束していそうです。

ただ、パレットの右下とか使われていなそうな領域が残っているので、必ず最も色が近いところを更新するのではなくもう少し何かランダム性を入れてもいいのかもしれません。
web拍手 by FC2
posted by シンドラー at 22:41 | Comment(0) | TrackBack(0) | Neural Network | このブログの読者になる | 更新情報をチェックする

2017年07月05日

凸多面体の内外判定について その2

とりあえず画像処理ソフトの方に組み込んで試してみました。

実行結果

いつ作ったのか覚えてないですが、良さそうな画像があったので試してみます。
circles.png
入力画像

drag_test_006.png
一番大きい円の色と思われる辺りを囲んだ結果

drag_test_007.png
右下の円の色と思われる辺りを囲んだ結果

HSV変換した分布領域を多面体で囲んで、領域内の色は白、それ以外は黒で2値化しています。色が似ていても(線形分離可能であれば)うまくいきそうです。複数領域選択とかできればもっとやりやすそうですが面倒ですね。

web拍手 by FC2
posted by シンドラー at 19:32 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

2017年07月04日

凸多面体の内外判定について

2値化の範囲を決定する際に、数値で刻んで矩形領域を設定するのは効率が悪いし自由度も低いので、その辺をマウスでできるようにしようかなと思いました。

直方体の8頂点をマウスでドラッグできるようにするのですが、自由に動かすと凹面ができてしまいますので、各面の中心に頂点を追加して、面が凹面になる場合にはこの中央点を移動させて無理やり凸面に修正するようにしました。

マウスドラッグで頂点移動はこれまでもやってきたような行列変換でできます。

drag_test_001.png
drag_test_002.png
drag_test_003.png
PPTで作ってみましたが見づらいですね。

実行結果
drag_test_004.png
透視投影変換を基準にしているので直感性は低いかと思います。こういう矩形の選択には正射影が向いていそうです。

続いて点の内外判定についてです。直方体の頂点を移動させた凸多面体ですので、それぞれの面が構成する平面と点の内外判定を行えば判定できると思います。点と平面の距離などは以前のスライドに追記しました。


実行結果
drag_test_005.png

ちゃんと選択した範囲のみ青くなっているので合っているとは思います。点群がRGBやHSVなど画素の色を3次元空間に投影したものを考えていて、それをこういうやり方で範囲選択できれば2値化がうまくできるのではないかと思っていますが、それはこれから試してみる予定です。

web拍手 by FC2
posted by シンドラー at 21:46 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

2017年06月11日

画像処理のGUI作成

キューブマップの作成のついでに、画像処理関係のGUIを追加してみました。グレースケール化は昔の記事でやった方法で、ラベリングとかCannyエッジ抽出とかはOpenCV使っています。ラベリングは[1]を参考にさせていただきました。

実行結果

ip_gui_000.png
別ウィンドウでHSVの色分布を表示しています。Hが360度で一周するので、0付近が見づらい場合があるので、シフトできるようにしています。今回はテスト画像として[2]の画像を使用させていただきました。

画像を読み込んで表示して、右クリックするとその色を取得できるようにしています。そこからその色との距離/類似度を使ってグレースケール化します。今回は赤いチョコ?を抽出するということで、HSVを使いました。
ip_gui_002.png

次は普通に閾値で2値化しました。
ip_gui_003.png

OpenCVのラベリングを使って色を塗りました。くっついているので困りますが、一応赤いチョコだけ抽出できているかと思います。
ip_gui_004.png

面積の情報も取得できますので、面積が50以下のものを削除してノイズを減らしました。
ip_gui_005.png

処理前の画像を一応確認できるように右上に小さく表示しています。これから膨張収縮とか穴埋めとか色々追加するとGUIが狭くなりそうですね。
ip_gui_001.png

[1] http://qiita.com/wakaba130/items/9d921b8b3eb812e4f197
[2] http://sipi.usc.edu/database/

web拍手 by FC2
posted by シンドラー at 00:33 | Comment(0) | TrackBack(0) | Image Processing | このブログの読者になる | 更新情報をチェックする

2017年06月08日

キューブマップとスフィアマップの作成

キューブマップとかスフィアマップとか出てきたのでパノラマ画像[1]をキューブマップやスフィアマップに変換するプログラムを作成してみました。

キューブマップは球面調和関数を試していたころに作っていた関数があったのでそのまま使用しました。積分などは行わずに極座標変換してレイが当たったところの色をそのままとっていたと思います。

スフィアマップの方は[2]を参考にさせていただきました。細かい話ですが、ray[2]とray[3]はray[1]とray[2]の間違いですね。ちゃんと見ていませんが、fire_ray関数の実装はなさそうでしたので、rayをワールド座標に見立てて、それを極座標に変換してキューブマップと同じ方法で変換してみました。

実行結果

cubemap_001.png
HDR画像を開いた後です。一応輝度値の最小/最大も表示するようにしています。255が1.0になるようにしているので、普通の画像は0〜1になります。

cubemap_002.png
キューブマップ変換後です。1枚にまとめたものと、各方向個別の6枚も出力するようにしました。

cubemap_003.png
スフィアマップ変換後です。これで合っているのかどうかはいまいちわかりませんが、[3]のミラーボールに似た結果になっているので良いことにします。

参考サイト
[1] http://vgl.ict.usc.edu/Data/HighResProbes/
[2] ftp://ftp.sgi.com/opengl/contrib/blythe/advanced99/notes/node179.html
[3] http://steradian.co.jp/adv3d/3dcg/HDRShop/PanoramicImage.html

web拍手 by FC2
posted by シンドラー at 21:20 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

2017年06月07日

四角ポリゴンの三角ポリゴン化

Oculus Mediumというソフトウェアを試してみたのですが、3次元空間でのお絵描きというのも新鮮でいいですね。MediumでObjファイルをStampとして空間に描くことができるのですが、少し前のバージョンでは四角ポリゴンがあったり法線ベクトルがなかったりするとエラーで読み込めませんでした。最新バージョンでは直したみたいです[1]。

以前他のレンダラ用の変換プログラムを作っていた気がしたので、それに四角ポリゴンを三角ポリゴンに変換する機能も入れました。やり方自体は簡単です。QUADの場合、indexに4頂点が指定されていますので、3頂点×2個の面に分割して追加するだけです。

quad2triangles_001.png

一応四角ポリゴンの.objを読み込んで出力してみましたが、きちんと三角ポリゴンになっていました。この変換プログラムは輪郭線の描画は画像処理でやっていたので、遅かったのでOpenMPを試してみました。parallel forしか使っていませんが、体感的には2倍ぐらい早くなった気がします。ついでに過去の記事でやっていたブルーム効果も追加してみました。

実行結果

render_blume_001.png
キューブマップを導入したら動くPCと動かないPCがあって謎です。キューブマップ単体のサンプルなら表示されるので、テクスチャ周りの使い方に何か問題があるんだと思うのですが…。

[1] Oculus Medium Updates

web拍手 by FC2
posted by シンドラー at 22:22 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする