現在の状況: 画像からセグメントを抽出しようとしています。openCV のメソッドのおかげfindContours()
で、すべての等高線の 8 連結点のリストができました。ただし、これらのリストには多くの重複が含まれているため、直接使用することはできません。
問題:重複を含む可能性のある 8 連結点のリストを指定して、そこからセグメントを抽出します。
可能な解決策:
- 最初はopenCVの
approxPolyDP()
方法を使いました。ただし、結果はかなり悪いです...ズームされた等高線は次のとおりです。
の結果は次のとおりですapproxPolyDP()
: (9 セグメント! 一部重複)
しかし、私が欲しいのはもっと似ています:
approxPolyDP()
「いくつかのセグメントに見える」ものを「いくつかのセグメント」に変換できるので悪いです。ただし、私が持っているのは、それ自体を数回反復する傾向があるポイントのリストです。
たとえば、私のポイントが次の場合:
0 1 2 3 4 5 6 7 8
9
次に、ポイントのリストは次のようになります0 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1 9
...そして、ポイントの数が大きくなった場合(> 100)、によって抽出されたセグメントapproxPolyDP()
は残念ながら重複していません(つまり、互いに重なり合っていますが、厳密には等しくないので、できます'たとえば、ピクセルとは対照的に、「重複を削除する」と言うだけです)
- おそらく、私は解決策を持っていますが、それはかなり長いです (興味深いですが)。まず、すべての 8 連結リストに対して、疎行列を作成し(効率化のため)、ピクセルがリストに属している場合は行列の値を 1 に設定します。次に、ピクセルに対応するノードと隣接するピクセル間のエッジを持つグラフを作成します。これは、ピクセル間に欠けているすべてのエッジを追加することも意味します(複雑さが小さいため、スパース マトリックスが原因である可能性があります)。次に、可能なすべての「正方形」 (隣接する 4 つのノード) を削除します。これは、すでにかなり細い輪郭で作業しているため可能です。次に、最小スパニング ツリーアルゴリズムを起動します。そして最後に、ツリーのすべてのブランチを openCV で近似することができます
approxPolyDP()
要約すると、エラーが発生しやすいように思われるため、まだ実装していない面倒な方法があります。ただし、スタック オーバーフローの皆さんにお尋ねします。他に既存のメソッドがあり、適切に実装されている可能性がありますか?
編集:明確にするために、ツリーを作成したら、「ブランチ」を抽出できます(ブランチは、3つ以上の他のノードにリンクされた葉またはノードから始まります)次に、openCVのアルゴリズムapproxPolyDP()
はRamer–Douglas–Peuckerアルゴリズムです。それが何をするかのウィキペディアの写真:
この図では、ポイントが互いに重複している可能性がある場合に失敗する理由を簡単に理解できます
別の編集: 私の方法では、注目すべき興味深いことがあります。グリッド内に配置されたポイント (ピクセルなど) を考慮する場合、一般に、最小スパニング ツリー アルゴリズムは有用ではありません。
X-X-X-X
|
X-X-X-X
とは根本的に大きく異なります。
X-X-X-X
| | | |
X X X X
しかし、どちらも最小全域木です
ただし、私の場合、ノードは輪郭であると想定されているため、ノードがクラスターを形成することはめったにありませんfindContours()
。
トマラクのコメントへの回答:
DP アルゴリズムが 4 つのセグメントを返す場合 (点2
から中心までのセグメントが 2 回ある)、私は満足です! もちろん、適切なパラメータを使用すると、「たまたま」同一のセグメントが存在する状態になり、重複を削除できます。ただし、明らかに、アルゴリズムはそのように設計されていません。
以下は、セグメントが多すぎる実際の例です。