🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

1回答

1123閲覧

Matにおける同一画素値とその座標の取得

kpkq307

総合スコア2

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/01/07 01:36

編集2021/01/07 09:04

前提・実現したいこと

CV_32SC2型のMat(以下img)を取り扱うプログラムになります。
imgの1チャネル目には0~PROJ_WIDTHPROJ_HEIGHTの画素値が重複ありで格納されています。(PROJ_WIDTHPROJ_HEIGHTは200万ほどです。)
ただし、画素値が重複する画素同士は必ず隣接しています。
このようなsrcにおいて画素値が同じ領域の重心座標を計算し、2チャネル目に重心座標に相当する画素に目印となる値を格納するようなプログラムを考えています。
愚直に記述すると下記のような形になると思うのですが、for文が3重になっていたりと複雑なコードになってしまいます。
もっとシンプルな形で記述をしたいためアドバイスをお願いします。
初心者のため読みにくいコードだと思いますがよろしくお願いいたします。
###試したこと
for (int y = 0;y < CAMERA_HEIGHT;y++)
for (int x = 0;x < CAMERA_WIDTH;x++)
の2重ループの部分を簡略化するために、「指定した画素値をもつピクセルの総数を返す関数」、「指定した画素値をもつピクセルの座標を返す関数」のようなものがあれば簡略化できると思い探してみたのですが見つけることができませんでした。もし、そのような関数があるのでしたら教えていただきたいです。

該当のソースコード

読みやすいように一部省略しています。

C++

1//Mat imgはあらかじめ用意してあります。 2 for (int proj_index = 0;proj_index < PROJ_HEIGHT * PROJ_WIDTH;proj_index++) 3 { 4 double sum_x = 0; 5 double sum_y = 0; 6 double ave_x = 0; 7 double ave_y = 0; 8 int count = 0; 9 10 for (int y = 0;y < CAMERA_HEIGHT;y++) 11 { 12 for (int x = 0;x < CAMERA_WIDTH;x++) 13 { 14 if (img.data[y*CAMERA_WIDTH+x*img.channels()] == proj_index) 15 { 16 sum_x += x; 17 sum_y += y; 18 count++; 19 } 20 ave_x = round(sum_x / count); 21 ave_y = round(sum_y / count); 22 img.at<int[2]>(ave_y, ave_x)[1] = proj_index; 23 } 24 } 25 }

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

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

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

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

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

guest

回答1

0

画素値が重複する画素同士は必ず隣接しています。

とのことであれば,まずはラベリングを行い,次にその結果の領域毎に重心を計算すれば良いのではないでしょうか.

投稿2021/01/07 01:52

fana

総合スコア11987

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

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

kpkq307

2021/01/07 02:21

fanaさん ご回答ありがとうございます。 ラベリング処理についてなのですがCV::conectedComponents関数をつかうのでしょうか? その場合だと入力は2値画像になるため、画素値が0と1以外の値も持つ今回の場合は適用できないのではないでしょうか? 初歩的な質問で申し訳ありませんが、ご返信いただけると幸いです。
fana

2021/01/07 02:29

私が知らないだけなのかもしれませんが,OpenCVには多値画像に対する扱いやすいラベリングの実装が無いように見えます.(逆に,見つけたら教えていただきたい) PROJ_WIDTH*PROJ_HEIGHT なる値がかなり小さい(数パターンとか)ならば, 「"ある特定の画素値を持つか否か"という判定による二値化を行ってはconnectedComponents()を使う」 ということを繰り返す,という手はあるでしょうが…… PROJ_WIDTH*PROJ_HEIGHT がある程度大きいようであれば,ラベリング処理を自前で実装することを考えた方が良いかもしれません.
fana

2021/01/07 08:15

(状況次第では floodfill() あたりを利用できる可能性もあるかも?)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問