scikit-imageでの画像データの扱い

Pythonでの機械学習ライブラリとしては有名な scikit-learn があるが,
画像処理ライブラリは scikit-image がある.
最近Pythonでの画像処理の勉強をしていて気になったので,
scikit-image での画像の型の扱いについてメモ.
scikit-image ライブラリでは,画像の読み込みは,サブモジュールの skimage.data を使い,

import skimage.data
img = skimage.data.imread("lenna.jpg")

のように書く.
この時,読み込まれた画像は,uint8の型のarrayになっていて,
値は 0〜255 の間の整数値となる.
例えばグレースケール化したいと思った時,skimage.color.rgb2gray という関数を使うが,
これを行なうと,

import skimage.color
gimg = skimage.color.rgb2gray(img)

結果の gimg は,float64 型になっていて,
値は 0.0〜1.0 の浮動小数点型となる.
画像処理においては, 0.0〜1.0 の間の浮動小数点数として扱うのが,
メモリは食うけど便利.
この辺りの型の変換を行なうのが,

skimage.img_as_bool(img)
skimage.img_as_ubyte(img)
skimage.img_as_int(img)
skimage.img_as_uint(img)
skimage.img_as_float(img)

の関数.
それぞれ,
skimage.img_as_bool(img):
bool型 (True / False の2値)
skimage.img_as_ubyte(img):
uint8型(読み込んだ時の状態.[0,255]の範囲)
skimage.img_as_int(img):
int16型(uint8の[0,255]が[0,32767]にマップされる.負の値も格納可.)
skimage.img_as_uint(img):
uint16型([0,65535]の範囲)
skimage.img_as_float(img):
float64型(uint8の[0,255]が[0.0,1.0]にマップされる.負の値も格納可.)
となる.
なお,この範囲は, skimage.dtype_limits(img) によってタプルで取得可能.

風邪ひき

風邪をひいた.前日までの沖縄出張気温20℃から,京都気温0℃雪の急激な変化で案の定という感じ.
ルルのドリンクと,葛根湯とバファリンExを飲んで寝たけど完治せず.のど飴なめてしのいでる.
以下,いくつか気になった記事を紹介.
Deep Learning論文紹介「Learning Recurrent Neural Networks with Hessian-Free Optimization」
Reccurent Neural Networksを使ったDeep Learningの話.詳しいことは論文を読んでみないとわからないけど,HFの勉強はきちんとしてみたい.
開幕したソチ五輪、生中継はネットとアプリで見られます
話題のソチオリンピックがネットで生中継で観れるっぽい.あまり家でテレビ見ることが無いけど,ネットで見れるなら便利だな.東京五輪でもネット中継見れるのかな?
JALの不正ログイン事件について徳丸さんに聞いてみた
僕もJALユーザなので気になる記事.この前の不正ログイン事件についての解説.
【5分で読める便利ツール紹介】ImageMagickでコマンドライン上から軽快に画像変換
知り合いの @payashim さんのブログから.convertコマンドは便利.よくzshのfor文と組み合わせて

for img in *.jpg; do; echo $img; convert $img ${img:r}.png; done

などして一括で画像変換したりする.

OpenCVのradiusSearch

今日OpenCVのradiusSearchを使っていてハマったのでメモ.
radiusSearchとは,「ある点(検索クエリ)から半径(radius)いくら以内にある点を探す」という処理.例えば,画像上にいくつかの特徴点があるときにある特徴点から距離r以内にある点を探す,とか,特徴空間中のある点から距離r以内にある点を探す,といったことに使う.実装上は,前者なら画像上の座標を,後者なら特徴空間中の座標=特徴量を各行の値として入れた行列(列数=点の数,行数=座標や特徴量の次元数)に対してIndexというものを作り,そのIndexを使ってradiusSearchを行う.
普通,何も考えずに上記の処理を行おうとすると,ある点と他の全ての点との距離を計算してソートし,上位のものを返せば良いが,それは計算量が大きい.特に何度もそういった処理を繰り返す場合.
これに対して,予め索引を作っておき,高速に検索できるようにするのがIndex.例えば,(Randomized) kd-treeや,Locality-Sensitive Hashing (LSH)などの手法がある.
以下ではRandomized kd-treeの使い方を簡単に説明する.ここで検索対象のデータは,cv::Mat型の変数dataに,前述のとおり,点数(行)×次元数(列)の行列として格納されているとする.この例では,各点から距離r内にある点のうち最大maxRadius個をすべて求める例である.

// 予めIndexを作成しておく.この例ではRandomized KDTreeをTree数4で
cv::flann::Index idx(data, cv::flann::KDTreeIndexParams(4), cvflann::FLANN_DIST_EUCLIDEAN);
int maxRadius=10; // 最大10個の点を求める
for(int i=0; i<data.rows; i++){
    cv::Mat_<int> indices; // dataの何行目か
    cv::Mat_<float> dists; // それぞれどれだけの距離だったか
    idx.radiusSearch(query, indices, dists, r, maxResults);
    for(int j=0;j<indices.row; j++){
        std::cout << indices(j,0) << "[" << dists.row(j) << "]" << " " << std::endl;
    }
}

こちらの公式ドキュメントでは引数が5個だったが,本当は5個目の引数にmaxResultsが必要(6個目の引数は省略可).

Tokyo.SciPy#4 出張版 (aka Kan.SciPy#1)で発表しました

※だいぶ前の話ですが
先日のTokyo.SciPy#4 出張版 (aka Kan.SciPy#1)で発表してきました。
Tokyo.SciPyはその名の通り、東京で行われているSciPy (Scientific Python)の勉強会です。
今回、特別に出張版として関西で開催されました。
そのため、名前はKan.SciPyとなっています。
僕は画像処理でPythonを(そしてNumPy及びSciPyを)使い始めていたので、 それに関して発表させていただきました。
資料はslideshareにアップしています。

発表するにあたって色々いじったので、だいぶPythonで画像処理をする事に関するノウハウが貯まったように思います。
それに関して、今後またこのブログで書いて行きたいと思います。