Home › Monthly Archives › 9月 2013

(27) Octaveでコマンドラインデバッグ

Octave ver.4.0ではGUI環境が提供されるとのことですが、現在開発レポジトリにあるOctaveはGUI起動するもののデバッガは実装されておらず…(2013/09/21時点)
(14) Octave開発バージョンをインストール

そこでコマンドラインなデバッガを使ってみます。
Octaveのデバッガ使用手順は公式サイトのこちらのページに書かれています。
http://www.gnu.org/software/octave/doc/interpreter/Debugging.html#Debugging

以下のような簡単なスクリプト test.m を作り、デバッガで追ってみます。

1 function test()
2     a = rand(5);
3     b = ceil(a * 100);
4     c = size(a);
5 end

dbstopで2行目にブレイクポイントを設定します。第1引数は関数名称、第2引数は行番号です。

octave:8> dbstop('test',2)
ans =  2
octave:9>

test.mを実行すると ブレイクポイントを設定した 2行目で実行が停止されます。

octave:10> test
stopped in /home/user/work/octave/test/20130921_debug/test.m at line 2
2: 	a = rand(5);
debug>

表示された行はまだ実行されていないため、この時点では変数 aは空っぽです。

debug> a
error: 'a' undefined near line 10 column 1
debug>

dbstepで 1行実行します。すると aには rand(5)の結果が格納されていることが確認できます。

debug> dbstep
stopped in /home/user/work/octave/test/20130921_debug/test.m at line 3
3: 	b = ceil(a * 100);
debug> a
a =
   0.682724   0.103381   0.472552   0.250516   0.979150
   0.470199   0.204337   0.224814   0.419812   0.598973
   0.459502   0.831599   0.363254   0.403174   0.870916
   0.637460   0.079009   0.193460   0.025521   0.394505
   0.953280   0.589993   0.317156   0.365921   0.788757
debug>

設定されているブレイクポイントをリスト表示したい場合は dbstatusを使います。
引数に関数名称を指定した場合、その関数内のブレイクポイントのみを表示します。

debug> dbstatus
breakpoint in test at line(s) 2.
debug> dbstatus('test')
breakpoint in test at line(s) 2.
debug>

設定されているブレイクポイントを削除したい場合は dbclearを使います。
引数で「関数名称のみ」or「関数名称+行番号」を入力すると、指定したブレイクポイントのみを削除できます。
引数を指定しない場合は設定されている全ブレイクポイントが削除対象となります。

debug> dbclear
debug> dbstatus
debug>

デバッグモードから抜け出るには dbquitと入力すると Octaveのプロンプトに戻ります。

debug> dbquit
octave:10>

今日覚えたデバッグコマンドは以下の5種類です。
dbstop
dbstep
dbstatus
dbclear
dbquit
お腹いっぱいになりそうなので今日はここまでで終わろう。

(26) imread, imwriteで画像ファイル読み書き

imreadで任意の形式の画像ファイルを配列データとして読み込める。
※imreadに失敗する場合は「(25) imreadを使えるようにする」を参照のこと

octave:1> ls
gfish.png
octave:2> img=imread('gfish.png');
octave:3> size(img)
ans =
   238   307     3
octave:4>

imfinfoで画像ファイルの情報を表示することができる。
この画像は、縦238ピクセル、横307ピクセル、RGB 3バンドのPNG画像ファイルだ。

octave:5> imfinfo('gfish.png')
ans =
  scalar structure containing the fields:
    Filename = /home/temp/work/gfish.png
    FileModDate = 19-Sep-2013 00:03:27
    FileSize =  125173
    Height =  238
    Width =  307
    BitDepth =  8
    Format = PNG
    LongFormat = Portable Network Graphics
    XResolution =  37.790
    YResolution =  37.790
    TotalColors =  40382
    TileName = 
    AnimationDelay = 0
    AnimationIterations = 0
    ByteOrder = undefined
    Gamma =  0.45455
    Matte = 0
    ModulusDepth =  8
    Quality =  75
    QuantizeColors =  256
    ResolutionUnits = undefined
    ColorType = truecolor
    View = 
octave:6>

imshowで変数に読み込んだ画像データを表示することができる。

octave:6> imshow(img)
octave:7>

http://octave.dogrow.net/wp-content/uploads/2013/09/20130920_01.png

変数に読み込んだ画像データは、配列データとして扱うことができる。
例えば、各ピクセルのRGBバンドの平均値(画像データ配列の3次元目の平均値)を算出し、グレースケール画像を作成してみる。

octave:7> gimg = uint8(mean(img,3));
octave:8> imshow(gimg)
octave:9>

グレースケール画像ができた。
http://octave.dogrow.net/wp-content/uploads/2013/09/20130920_02.png

作成したグレースケール画像を imwriteでPNGファイル出力してみる。

octave:9> imwrite(gimg,'gray.png','png')
octave:10> ls
gfish.png  gray.png
octave:11>

(25) imreadを使えるようにする

Octaveで imread を使って画像ファイルを読み込もうとしたところ、以下のようなエラーが発生した。

octave:3> imread('test.tif')
error: imread: invalid image file: imread: image reading capabilities were disabled when Octave was compiled
error: called from:
error:   /usr/local/share/octave/3.6.4/m/image/imread.m at line 74, column 7
octave:3>

どうやらOctaveをコンパイルしたときに画像ファイルの読み込みができるように作っていなかったようだ。

そこで Octaveを再度コンパイルすることにした。

[user@dog-server]$ tar zxf octave-3.6.4.tar.gz
[user@dog-server]$ cd octave-3.6.4
[user@dog-server]$ mkdir .build
[user@dog-server]$ cd .build
[user@dog-server]$ ../configure

すると configure実行時に imreadに関する以下のような警告が出た。

configure: WARNING: GraphicsMagick++ library not found.  The imread function for reading image files will not be fully functional.

GraphicsMagick++ライブラリが見つからずに imreadが不完全な動作になるとのこと。

GraphicsMagick++を共有ライブラリ(.so)生成指定付きでインストールする。

[user@dog-server]$ tar zxf GraphicsMagick-1.3.18.tar.gz
[user@dog-server]$ cd GraphicsMagick-1.3.18
[user@dog-server]$ ./configure --enable-shared
[user@dog-server]$ make
[user@dog-server]$ make check
[user@dog-server]$ sudo make install

ここで、Octaveの configureを再度実行してみる。

[user@dog-server]$ ../configure --with-quantum-depth=32 --enable-shared --disable-static --with-magick-plus-plus=yes

すると、また同じ警告が出た…

configure: WARNING: GraphicsMagick++ library not found.  The imread function for reading image files will not be fully functional.

config.logを見ると、どうやら環境変数 PKG_CONFIG_PATHGraphicsMagick++.pc のパスを設定する必要があるとのこと。
GraphicsMagick++の make installで出力されているはずなので /usr 配下で検索してみる。

[user@dog-server]$ find /usr -name "GraphicsMagick++.pc"
/usr/local/lib/pkgconfig/GraphicsMagick++.pc

GraphicsMagick++.pcが置かれている /usr/local/lib/pkgconfig を環境変数 PKG_CONFIG_PATH に設定し、再度Octaveのconfigureを実行する。

[user@dog-server]$ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
[user@dog-server]$ ../configure --with-quantum-depth=32 --enable-shared --disable-static --with-magick-plus-plus=yes

すると config.logから「imreadが…」の警告が消えた。

configureがうまく行ったようなので Octaveを make, make checkする。

[user@dog-server]$ make
[user@dog-server]$ make check

Octaveを make installする前に imreadが使えるようになったかを run-octave で確認してみる。

[user@dog-server]$ run-octave
octave:1> ls
picture.jpg
octave:2> img=imread('picture.jpg');
octave:3> size(img)
ans =
   241   266     3
octave:4>

imreadが正常に動作した。

最後に Octaveを make installする。

[user@dog-server]$ sudo make install

いろいろと手間取ったけれども何とか動くようになりました(^^)

(24) csvwriteでCSVファイル出力

任意の配列を csvwrite でCSVファイルとして出力できる。

octave:1> a=rand(5)
a =
   0.542996   0.489232   0.047035   0.599449   0.292406
   0.645112   0.505513   0.170523   0.144984   0.458485
   0.321232   0.073533   0.298546   0.088937   0.861154
   0.930462   0.157901   0.486024   0.130868   0.111856
   0.714509   0.815946   0.053521   0.206195   0.887324
octave:2>
octave:2> csvwrite('temp.csv', a)

出力したファイルは、「,」区切りのCSVファイルとなっている。

[user@dog-server]$ cat temp.csv
0.5429963046629652,0.4892324282133353,0.04703543400988712,0.5994492495798024,0.2924063414552014
0.6451117490214259,0.5055131090427051,0.1705233495889967,0.1449835559314347,0.4584854134958692
0.3212318726559802,0.07353300388710242,0.2985459491039432,0.08893719071145494,0.8611542924326369
0.9304620335200237,0.1579012055122481,0.4860241431674273,0.1308681261672557,0.1118555082863725
0.7145092069852456,0.8159457131196939,0.05352063406290257,0.2061950295261054,0.887324445259423
[user@dog-server]$

出力したCSVファイルは、Excelで入力していろいろと加工できる。

(23) 行末の「;」入力で結果表示を抑制

octaveのコマンドを入力すると、直後にその結果が表示される。

octave:1> a=rand(5)
a =
   0.948277   0.879068   0.984755   0.911834   0.582972
   0.986024   0.469933   0.602465   0.927959   0.474812
   0.171462   0.846142   0.911001   0.727675   0.607291
   0.156386   0.785915   0.735773   0.917030   0.853956
   0.222759   0.369714   0.744204   0.013498   0.971795

このような少ない結果表示の場合は問題にならないが、計算結果が数千個、数万個と多い場合は煩わしい。

octave:2> a=rand(1000)
a =
 Columns 1 through 13:
   5.8366e-01   9.3538e-01   3.3443e-01   2.8172e-01   5.6701e-01
   7.9487e-01   3.5421e-01   3.0166e-01   7.3360e-01   4.1492e-01
   6.2559e-01   1.3823e-01   6.4445e-02   9.2671e-01   8.7322e-01
   1.7135e-01   6.3989e-01   9.7787e-01   3.2567e-02   6.2130e-01
   1.4096e-02   4.1311e-01   1.9048e-01   9.1873e-01   4.2091e-01
   7.7403e-01   7.7621e-01   2.4902e-01   6.7568e-01   2.4357e-01
   6.8968e-01   4.3378e-01   1.6004e-01   3.4825e-01   2.6041e-01
   3.4973e-01   4.4200e-01   9.0781e-01   7.0193e-01   2.0544e-01
   1.7061e-01   2.4874e-01   7.7378e-01   4.8450e-01   7.9732e-01
-- less -- (f)orward, (b)ack, (q)uit

このようなときは、コマンドの行末に「;」を付与すると、結果表示を抑制できる。

octave:3> a=rand(1000);
octave:4>

(22) parforは使えるけど使えない

MATLABの Parallel Computing Toolboxでは、forループを parforに書き換えるだけでマルチコア並列化が実現できる。
このプログラムをそのままOctave上で実行すると、エラーは発生しないが、高速化もしない…

Octave公式Wikiには、「3.6.N seriesで parforを認識するようになった」とある。

What's new in Octave
[edit] What's new in version series 3.6.N and 3.7.N of Octave
Several new features have been added to the 3.6.N series. The full details are in the NEWS file, but in brief 3.6.N series brings: 
 Perl compatible regular expressions 
 A profiler has been added. 
 Broadcasting enabled for all built-in binary element-wise operators. 
 The statistical distribution functions have been overhauled. 
 The functions strread(), textscan(), and textread() have been rewritten. 
 Performance of all m-file string functions has been improved. 
 The qhull geometry functions have been revamped. 
 Date/time functions have been updated. 
 Matlab compatible preference functions have been added. 
 Various handle graphics functions have been introduced. 
 The parfor keyword is now recognized. ←コレ

すなわち、キーワードとして認識する(=エラーとしない)だけで、実際の動作は forと同じく1プロセスのようだ。

MATLABとOctaveでプログラムを共通化できないが、Octaveで MATLABの parfor相当のことを実現したい場合、
pararrayfun
parcellfun
を使用することができる。

これを使うと、

function ret = calc( a, b )
    ret = a + b;
endfunction

のような関数を4並列処理したい場合に、

ret = paraarrayfun( 4, @calc, a, b )

と書くと、Octaveを4プロセス起動して並列処理してくれる。
※スレッド並列ではなく Octaveプロセスを新たに起動している。

parforでループカウンタをキーに並列処理するのとと同じく、
各処理で配列 a, bのインデックスをキーに並列処理してくれる。

ただし…
オーバーヘッドがかなり大きいので適用箇所を間違えると低速化する。

(21) Octave入門書籍

Octave教科書
1,995円
工学社, I/Oブックス
まったくの初心者の方には、この本がおすすめです。
Octaveによる画像処理入門
1,995円
工学社, I/Oブックス
幾何変換など視覚的に納得したい初心者の方には、この本がおすすめです。
Octaveの精義
3,780円
カットシステム
脱初心者したい方には、この本がおすすめです。

入門書を読み終えて物足りなくなったら…

ネット上には画像処理や信号処理などのOctave/MATLABプログラムソースコードがあちらこちらに置かれています。
これらをステップ実行しながら追っていくと、よい勉強になります。
ここ(↓)を漁ると面白いものが見つかります。
http://jp.mathworks.com/matlabcentral/?s_tid=gn_mlc