質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Q&A

解決済

1回答

4037閲覧

高速な閉領域を判定をするアルゴリズム

concern12

総合スコア18

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

0グッド

0クリップ

投稿2021/09/13 22:36

編集2021/09/13 23:27

高速な閉領域を判定をするアルゴリズムを考えています。
画像1のようにマスが塗りつぶされているかいないかの値が入っている2次元配列bool[,]が用意してある場合に、
画像2のように赤色のマス(矩形)を配置した場合に、赤斜線のような閉鎖されているマスを高速に判別するアルゴリズムをご教授いただきたいです。

調べたところ閉領域を塗りつぶすアルゴリズムは存在するのですが、その手法だとすべてのマスを走査する必要があるので、低速になってしまいます。

データとしてbool[,]の他に、塗りつぶされた重複しているマスのないの矩形情報(画像1を例にすると、座標(2,2)から幅4、高さ1の矩形、座標(1,3)から幅2、高さ4の矩形、座標(2,7)から幅5、高さ2の矩形)を参照ものできるものとします。

ヒントだけでもありがたいです。よろしくお願い致します。

現状思いついている最適化

  • 新しく配置した矩形が、0または1種類の矩形にしか隣り合っていない場合は新しく閉領域となる部分は存在しない

イメージ説明
画像1

イメージ説明
画像2

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2021/09/13 22:43

いちばん汎用的なものを考えれば、「閉領域を塗りつぶすアルゴリズム」になるかと思います。 それ以上に制約できるような、何らかの条件はありますか?
Zuishin

2021/09/13 23:01

赤い矩形の周囲のドットから始め、幅優先探索をして一番初めにそれ以上探索できなくなったところが閉領域です。メモ化しておいてそこを塗りつぶせば良いのではないでしょうか。
concern12

2021/09/13 23:13 編集

ご提案ありがとうございます。 質問文の方に条件の方を追記いたしました。 >幅優先探索をして一番初めにそれ以上探索できなくなったところ 赤い矩形を配置したときに新しく閉領域となる空間は1つとは限らないので厳しそうです。
Zuishin

2021/09/13 23:17

10 × 10 ならどんなアルゴリズムでも大差なさそうに思いますが、計測した結果、普通の方法では遅すぎたということですか?
concern12

2021/09/13 23:22

すみません、10x10は一例となります。実際は1000x1000などを想定しています。 質問文の修正を致します。
guest

回答1

0

ベストアンサー

  • 前提として,黒塗りの領域は常にラベリング処理により,各領域を区別できるようにしておきます.

  • 赤矩形が与えられたとき,赤矩形と隣接する黒マス群のラベル値を調べます.

ある黒領域が赤矩形と協力(?)して新たな閉領域を作る場合,その黒領域のラベルが複数回登場するハズです.
(下図で黄色矩形で示した場所が赤に隣接する黒マス.この2つのマスには同じラベル値が付与されているハズ)

イメージ説明

  • 前ステップで,どの黒領域について調べれば良いのかがわかったので,

その領域の黒マスと赤マスとが共有する「角」から輪郭を追跡します.
(図では2つの矢印で例示)
輪郭を辿る際は,「(黒あるいは赤で)塗られているマスの内側を常に左側に見る」といったルールを設けて辿る方向を決めます.
(図の例はこのルールで辿る形になっている)

  • 輪郭を辿って元の位置に戻ってきたとき,領域の輪郭形状が得られます.

あとは,その輪郭が「閉領域」を成す物か否かを判定するだけです.
(図の例では,緑で示した輪郭追跡結果を棄却し,青で示したものを採用すべきである)
このことは,輪郭追跡中に出会った「角」が「左曲がり と 右曲がり のどちらが多かったか」とかで判定できるかと.

  • ※閉領域内のマスを列挙したい場合には,後段処理として,ふつーの塗りつぶし処理的なことを行う等してください.

輪郭情報が得られているのだから,塗りつぶし開始点は自明なハズです.

投稿2021/09/14 01:35

fana

総合スコア11996

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2021/09/14 01:40

赤領域と黒領域との隣接部のラベル値を調べる際に, 隣接している黒マスがある場合には「1箇所」として数える等の工夫をすれば, 「赤領域と黒領域が(閉領域を作らずに)接しているだけ」みたいな状況に対する無駄な探索を省くこともできるでしょう.
concern12

2021/09/14 04:14

ご回答ありがとうございます。 ご回答いただいた手法でうまくいきそうです! 一つ質問ですが、 >隣接している黒マスがある場合には「1箇所」として数える等の工夫をすれば, がわからなかったので、もう少し詳しくご説明していただけないでしょうか?
fana

2021/09/14 04:22

黒マスを■,赤マスを□とするとき,例えば, ■■■■■ □□□ みたいな状況で何も工夫しない場合,3つの■が赤領域に隣接しているため, > その黒領域のラベルが複数回登場するハズ という話を満たしてしまいます. この状況で輪郭追跡を走らせるのは無駄です. この状況を 「赤領域に ■が3個 隣接している」ではなく「赤領域と黒領域が 1箇所で 隣接している」と判断できれば 輪郭追跡を走らせずに済みます.
fana

2021/09/14 04:27 編集

処理効率を考える(無駄処理を削る)なら ■■■□ ■■ □ ■■■□ ■■■□ これを「3箇所で接する」じゃなくて「2箇所で接する」と判定できるように,【赤矩形と隣接する黒マス群のラベル値を調べる処理】を作りましょう,って話.
fana

2021/09/14 04:42

まぁ,あとは, 「ある黒領域と赤領域とがN箇所で接する」と分かった時点で,閉領域がいくつ生まれるハズなのかがわかると思うので, 処理中に閉領域がその個数見つかった時点で終了してよい,だとか,そういう細かい工夫を入れる余地はあるかと.
fana

2021/09/14 04:48 編集

■■■■■■■■ ■■■■□□ ■■■ ■   □□■■■ ■ ■■□□■■ ■ ■ □□ ■ ■■□□■■■■ ■   □□  ■■ ■■■■□□■■■ こういう,複数の黒領域が赤領域に接する場合に,同じところを何度も追跡しちゃわないように,とか,実装においてはいろいろ考えることはあると思うけど,頑張って.
concern12

2021/09/15 22:12

細かく最適化できそうですね。 試行錯誤してみます。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問