2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

C#Advent Calendar 2023

Day 14
記事投稿キャンペーン 「2024年!初アウトプットをしよう」

【OpenCvSharp】距離変換を用いて内側の図形を取得する

Last updated at Posted at 2024-01-01

入力した任意の図形から、その図形の1px内側の図形を抽出する。
イメージはこう。少し見づらいですが外側が赤、内側が緑になっています。
内側図形.png

今回は距離変換を用いて内側の図形を取得します。

パラメータ

  • 画像データ
    画像データの前提条件は下記。
    1. 閉じた図形である。
    2. 図形は一つだけ描かれている。
    3. 二値画像である。

距離変換

OpenCv(Sharp)にはDistanceTransform()という距離変換を行う便利関数があるのでこれを使う。
Matを入力にMat<float>を返し、このfloatがその画素における距離である。

DistanceTransform()には二つパラメータがある。

  • DistanceType:
    距離計算方法。主にL1, L2, Cを使う。

    • DistanceType.L1: 市街地距離
    • DistanceType.L2: ユークリッド距離
    • DistanceType.C: チェス盤距離
    • DistanceType.L12: L1とL2の中間の性質を持つ距離
    • DistanceType.Fair, Welsch, Huber: いずれも外れ値に対して頑健な距離計算
  • DistanceTransformMasks:
    距離計算に用いるマスクサイズ。マスクサイズが大きいほど複雑な形状に対応した距離変換になる

    • DistanceTransformMasks.Mask3: 3*3の範囲をマスク
    • DistanceTransformMasks.Mask5: 5*5の範囲をマスク
    • DistanceTransformMasks.Precise: より精密な計算のためのマスク
      • ドキュメントではまだサポートされていないとあるが、エラーにはならず動くのでMask3かMask5に変換されているのか?

今回は市街地距離で計算し、複雑な図形を扱わないことからMask3を採用する。

最終的なコード

下記では距離変換で得られた距離をインデックスとして、色付けして見やすくしている。

public void ShowDistanceColor(Mat binaryImage)
{
    // 距離変換を適用する
    var dist = binaryImage.DistanceTransform(DistanceTypes.C, DistanceTransformMasks.Mask3);
    dist.MinMaxLoc(out double _, out var maxVal);

    // 出力画像の準備
    var output = binaryImage.CvtColor(ColorConversionCodes.GRAY2BGR);
    var random = new Random();

    // 距離値ごとに色を変えて描画する
    for (var distance = 0; distance <= (int) maxVal; distance++)
    {
        var color = new Vec3b(
            (byte) random.Next(256),
            (byte) random.Next(256),
            (byte) random.Next(256));

        for (var y = 0; y < dist.Rows; y++)
        for (var x = 0; x < dist.Cols; x++)
        {
            if ((int) dist.At<float>(y, x) != distance) continue;
            // 好きなように処理する
            output.Set(y, x, color);
        }
    }

    Cv2.ImShow("Color Coded Distance Map", output);
    Cv2.WaitKey(0);
}

ちなみにこれを実行すると下記のような画像が得られます。
内側図形_最終.png

まとめ

画像処理のアルゴリズムって勉強していると「いつ使うんだろ?」と思うこと多いけどふとした時に使う場面と出くわしますね。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?