手習ひデジタル信号処理(162) Scilab、{IPCV}、画像の輪郭抽出

Joseph Halfmoon

今回は画像の輪郭抽出を行ったのち、その輪郭のConvex Hull(凸包)まで一気に処理せんとの野望あり。というか処理例がそうなっていただけのことなのですが凸包いけませぬ。毎度の処理例途中でのエラー、いろいろ突いてみるもなんともはや動きませぬ。元より素人、分かっておらんからの~。そこで手前の輪郭抽出でお茶を濁しました。

※「手習ひデジタル信号処理」投稿順 Indexはこちら

※Windows11上の    Scilab2024.0.0およびScilab上のScilab IPCVツールボックスを使用させていただいております。

Structural Analysis and Shape Descriptors

今回は、Structural Analysis and Shape Descriptors というタイトルのもとにまとめられているセクションを練習してみん、との希望であります。HELPファイルを見ると以下の3関数の記載があります。

    • imconvexHull — Finds the convex hull of a point set.
    • imdrawcontours — Draw contours from the contour image.
    • imfindcontours — Finds contours in a binary image.

段取りとしては、まず imfindcontours関数 で「輪郭」を抽出し、そこから得られたデータについて imconvexHull 関数を使って「凸包」を計算する形です。ま、途中の輪郭についてimdrawcontours関数でも適用して輪郭も描画してやれば1撃でセクション完了でないかと素人老人の目論見です。

しかし、 imconvexHull 関数のHelpファイル記載の処理例を実行した時点で目論見は脆くも潰えました。Error

imfindcontours関数自体はエラーなく実行可能だったのですが、その結果を処理するところで「お約束の」エラー。今回も「押したり引いたりすれば」動くかといろいろやってみたのですが末尾まで「完走」できませぬ。その上、肝心の imconvexHull 関数について以下の疑問点もあがって参りました。

Sklansky’s algorithm.

Helpファイルを参照すると、imconvexHull 関数は上記のアルゴリズム(噂によるとシンプルで美しいらしいです)を採用しているとのことですが、このアルゴリズムだとすると

ただしい凸包が得られないケースがある

らしいです。Convex Hullのアルゴリズムとその歴史については、カナダ『McGill大』様の以下のページに詳しいです。

A History of Linear-time Convex Hull Algorithms for Simple Polygons

そして上記ページを拝見すると Sklansky 様の2つのアルゴリズムの両方に、

Incorrect

と記されておるのです。キビシー。Sklansky 様はConvex Hullアルゴリズム研究の初期に活躍され、シンプルで美しいアルゴリズムを見つけたものの、正しくなかった、ということみたいです。知らんけど。

IPCVの輪郭抽出関係関数

Helpファイルには輪郭抽出関係で以下の2関数がリストされてます。

    • imdrawContours
    • imfindContours

これまたScilabにアリガチなあるあるですが、Helpファイルには見当たらない(けれど使用可能な)以下2関数も存在してます。

    • implotContours
    • imcontour2label

今回は、上記の4関数を使って「輪郭抽出とそのプロット」を練習してお茶を濁すことにいたしました。

今回の処理例とその結果

素人老人が動かせた部分をツギハギした処理例コードが以下に。

S = imread(fullpath(getIPCVpath() + "/images/hand.jpg"));
Sbw = im2bw(~S,0.5);
Sc = imfindContours(Sbw);
Slabel = imcontour2label(S,Sc);
So = imdrawContours(Slabel);
scf(0); clf;
subplot(151); title('Original'); imshow(S);
subplot(152); title('im2bw'); imshow(Sbw);
subplot(153); title('imfindContours'); plot(Sc(1)(:,1),Sc(1)(:,2));
subplot(154); title('implotContours'); implotContours(S,Sc,5);
subplot(155); title('imdrawContours'); imshow(im2uint8(So));

上記のコードを実行して得られた画像が以下です。plotHandCountours

真ん中のplotの上下が逆転しているのは、画像そのものではなく、imfindContours関数が返してきた座標点を、plot関数を使ってXYプロットしているためです。なお、今回の入力画像に対して、imfindContours関数は、2つの輪郭を抽出してまとめて返してくれるので Sc(1)のように最初のオブジェクトを抽出してプロットしてます。またSc(2)は親指の付け根のとこにある「光の加減」で見えてるらしいポッチなオブジェクトでした。

その辺が分かり易いのが、implotContours関数で、元画像に重ねて輪郭線を表示できます。便利なんだけれどもHelpファイルに使い方の記載がないです。トホホ。

手習ひデジタル信号処理(161) Scilab、{IPCV}、アフィン変換とその眷属 へ戻る

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です