今回は Watershedアルゴリズムです。画像を「地形図」にみたててその高低を測り、「分水嶺」を求めて川の流域のごとくにセグメンテーションするのだとかしないとか。分かったような、分からぬような。まあScilab IPCVにも変換関数あり、やってみるのですが、Helpの例が動きませぬ。IPCVの中の人のチェック漏れ?
※「手習ひデジタル信号処理」投稿順 Indexはこちら
※Windows11上の Scilab2024.0.0およびScilab上のScilab IPCVツールボックスを使用させていただいております。
Watershedアルゴリズム
信号処理素人のお惚け老人が分かりもせぬことを書かないように、いつものようにこのアルゴリズムについて先達の皆さまを調べてました。どうも見つかる日本語ドキュメントのほとんどが同じドキュメントの「引き写し」みたいです。OpenCVの解説ドキュメントね。よって処理例に使っている画像もコインが並んだような奴一択。その中の一つへのリンクを以下に掲げました。
上記を参照すればアルゴリズムについては分かるんじゃないかと思います。知らんけど。
さて、例によってScilab IPCVのHelpページは素っ気なく、アルゴリズムについての説明はありませぬ。ただ、関数とその引数、戻り値くらいが説明されているだけ。しかし、処理例は付属してます。実行してみるとこんな感じ。
なんじゃい、エラーじゃん!よくよく見てみると処理例でロードしている元画像はグレースケール画像でした。一方 imwatershed関数に食わせる画像は8ビットx3チャネルのRGB画像がよろしいようです。処理例に食わせる画像のフォーマットがあってなかったんかい!テストしてないじゃろ。プンプン。
まあ、Scilabやっていると時折あることでないかと。理由を調べて対処していけば立派な人になれるかも(なれるとは言ってないデス。)
改造した処理例
というわけで、HELPファイルの例を諦めたので、テキトーな画像をピックアップして、いつもの勝手改造を施した処理例が以下に。
S = imread(fullpath(getIPCVpath() + "/images/peppers.png")); Sgray = rgb2gray(S); Sb = im2bw(Sgray,0.1); Sd = imdistransf(Sb); dist = Sd > 0.4; [markers,n] = imlabel(dist); markers(1:5,1:5) = 255; Sw = imwatershed(S, markers); scf(); subplot(151); title('Original'); imshow(S); subplot(152); title('Gray'); imshow(Sgray); subplot(153); title('BW'); imshow(Sb); subplot(154); title('distansf'); imshow(Sd); subplot(155); title('watershed'); imshow(Sw,hsvcolormap(12));
本当は、OpenCVの解説ドキュメントのようなコインの一個一個をセグメンテーションするような立派な例をやりたかったのですが、コインではなくピーマンになってしまいました。トホホ。
カラフルに「セグメンテーション」はされているみたい。でもコインの例ほど決定的ではないわいな。もしかすると dist のスレッショルド値いじるともっと良くなるのか。まあ、一応、関数動作しましたな。素人老人が手習ひするのはこんなもんかい。