金子邦彦研究室プログラミングOctave の活用Octave から OpenCV の k-means クラスタリング関数を呼び出す例

Octave から OpenCV の k-means クラスタリング関数を呼び出す例

OpenCV の機能を利用して,Octave から k-means クラスタリングを行う例

Octave 言語で書いた k-means クラスタリングのソースコード (OpenCV を使わないもの) は別の Web ページに載せています 

前準備

Octave のインストール

その他

関連する外部ページ】: http://www.eecs.berkeley.edu/Research/Projects/CS/vision/bsds/

※ Octave のプロンプトを変えたいときは,次のように操作する.

PS1('> ')

※ Octave のインストールによっては,Octave の起動時に毎回次の操作を行う必要があるかもしれない

pkg load image

プログラムのソースコード(書きかけ)

mykmeans.m

function mat = cvreadl2d_to_mat(cv)
# Read2D 型を要素とする CvMat (OpenCV のデータ)cv を,Octave の2次元配列 mat にコピー
for x = [1:cv.width]
  for y = [1:cv.height]
    mat(y,x) = cvGetReal2D(cv, y-1, x-1);
  end
end
endfunction

function cv = mat_to_cvreadl2d(mat)
# Octave の2次元配列 mat を,Read2D 型を要素とする CvMat(OpenCV のデータ)cv にコピー
height = size(mat)(1);
width = size(mat)(2);
for x = [1:width]
  for y = [1:height]
    cvSetReal2D(cv, y-1, x-1), mat(y,x);
  end
end
endfunction

function rgbplot3d(rgb)
# Octave の RGB 画像データ(256階調, 0 から 255 の値,R, G, B プレーン)を使い,画素値の 3次元プロットを行う
    colormap(map);
  plot3(rgb(:,:,1), rgb(:,:,2), rgb(:,:,3));
endfunction


function rgb_to_cvreal3(rgb, samples)
# Octave の RGB 画像データ(256階調, 0 から 255 の値,R, G, B プレーン)を、
# OpenCV のデータ構造である 要素 CV_32FC3 の CvMat (ROW数 > 1, COL数 =1) に [r; g; b; r; g; b; ...] の形で並べる.
height = size(rgb)(1);
width = size(rgb)(2);
for x = [1:width]
  for y = [1:height]
    cvSet2D(samples, ((x - 1) * height) + (y - 1), 0, cvScalar( rgb(y,x,1), rgb(y,x,2), rgb(y,x,3) ) );
  end
end
endfunction

function vec = rgbvec(rgb)
# Octave の RGB 画像データ(256階調, 0 から 255 の値,R, G, B プレーン)を、[r g b r g b ...] の形の行ベクトルに変える
height = size(rgb)(1);
width = size(rgb)(2);
vec = zeros(1,width*height);
for x = [1:width]
  for y = [1:height]
    # 要素番号は 1 から始まるので - 1, + 1 が必要
    vec( ( ((x - 1) * height) + (y - 1) ) * 3 + 1 ) = rgb(y,x,1);
    vec( ( ((x - 1) * height) + (y - 1) ) * 3 + 2 ) = rgb(y,x,2);
    vec( ( ((x - 1) * height) + (y - 1) ) * 3 + 3 ) = rgb(y,x,3);
  end
end
endfunction

function rgb = vecrgb(vec, width, height)
# Octave の [r g b r g b ...] の形の行ベクトルを,RGB 画像データ(256階調, 0 から 255 の値,R, G, B プレーン)に変える.
rgb = zeros(height,width,3);
for x = [1:width]
  for y = [1:height]
    # 要素番号は 1 から始まるので - 1, + 1 が必要
    rgb(y,x,1) = vec( ( ((x - 1) * height) + (y - 1) ) * 3 + 1 );
    rgb(y,x,2) = vec( ( ((x - 1) * height) + (y - 1) ) * 3 + 2 );
    rgb(y,x,3) = vec( ( ((x - 1) * height) + (y - 1) ) * 3 + 3 );
  end
end
endfunction


rgb1 = imread("20090701001_avi01_001000.png");
height = size(rgb1)(1);
width = size(rgb1)(2);

samples1 = cvCreateMat(width * height, 1, CV_32FC3);
rgb_to_cvreal3(rgb1, samples1);

MAX_CLUSTERS = 10;
labels1 = cvCreateMat(width * height, 1, CV_32SC1);
cvKMeans2(samples1, MAX_CLUSTERS, labels1, cvTermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0));

for x = [1:width]
  for y = [1:height]
  mono2(y,x) = cvGetReal2D(labels1, (x-1) * height + (y-1), 0);
  end
end

# colormap ... は,カラーマップの設定
colormap( rainbow(MAX_CLUSTERS) );
imshow(mono2, [min(min(mono2)) max(max(mono2))]);

# # colormap(map);

# imshow(rgb1);
input("Please press enter to continue");

実行方法と実行結果の例

  1. (オプション)Cygwin からリモートログインする場合
    startx
    xhost +
    ssh -X username@ipaddress
    
  2. ソースコードをファイルとして保存
  3. Octave を起動
  4. Octave の source コマンドを使って実行
    cd <ソースコードのファイルを置いたディレクトリ>
    source "<ソースコードのファイル名>"
    
  5. 実行が終わるまで数十秒待つ

元画像の例

[image]

実行手順

上記のファイルを mykmean.m のようなファイル名で保存しておく. 上記のファイル内の画像ファイル名「20090701001_avi01_001000.png」の部分は適切に書き換える

octave
source mykmean.m

クラスタリングの結果

およそ数秒程度で次の結果が出る

[image]