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

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

新規登録して質問してみよう
ただいま回答率
85.48%
OpenCV

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

C++

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

Q&A

解決済

1回答

1199閲覧

c++ opencv を使って検出した円の周りを透過させたい

syoshinnsyac

総合スコア1

OpenCV

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

C++

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

0グッド

0クリップ

投稿2023/01/10 08:05

前提

C言語についてはある程度学習していますがC++, opencvは初心者です。
Visual Studio 17.0.4
openccv 4.5.5

実現したいこと

Houghcircles で検出した円の中心座標,半径を使って 座標と円の中心座標の距離<半径という条件文にすることで円の周りを透過させる

試したこと

透過させる処理を除くと最後まで通ります。円検出も描画関数を使って表示され検出されたことを確認しています。
エラーの場所から型に関してのエラーだとは思うのですが解決できませんでした。
よろしくお願いします。

発生している問題・エラーメッセージ

mat.inl.hpp内でエラーが発生します。
呼び出し履歴はソースコード下から9行目の位置からです

template<typename _Tp> inline _Tp& Mat::at(Point pt) { CV_DbgAssert(dims <= 2); CV_DbgAssert(data); CV_DbgAssert((unsigned)pt.y < (unsigned)size.p[0]); //↓ハンドルされない例外が 0x00007FFA898D06BC で発生しました CV_DbgAssert((unsigned)(pt.x * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels())); CV_DbgAssert(CV_ELEM_SIZE1(traits::Depth<_Tp>::value) == elemSize1()); return ((_Tp*)(data + step.p[0] * pt.y))[pt.x]; }

該当のソースコード

行っている処理は以下の通りです

Mat image; float x0 = 0, y0 = 0; int radius = 0; //画像読み込み 同時にグレイスケール化 image = imread("image.jpg", 0); //サイズ変更 resize(image, image, Size(), 0.3, 0.3); //左右反転 flip(image, image, 1); std::vector<cv::Vec3f> circle; //円検出 パラメータは下サイトで調整済 汎用性はなさそうなので要調整 HoughCircles(image, circle, cv::HOUGH_GRADIENT, 1, 5000, 200, 50, 20, 300); //検知した円の半径、中心座標の取得 for (size_t i = 0; i < circle.size(); i++) { Vec3i c = circle[i]; x0 = c[0], y0 = c[1]; radius = c[2]; } float dx = 0, dy = 0; float l = 0; //検知した円以外を透過させる cv::Mat alpha_img(image.size(), CV_8UC4); for (int y = 0; y < image.rows; y++) { for (int x = 0; x < image.cols; x++) { dx = x - x0; dy = y - y0;//←←←座標から l = sqrt(dx * dx + dy * dy);//← 距離を求める cv::Vec3b p = image.at<cv::Vec3b>(cv::Point(x, y));//呼び出し履歴ココ if ( l > radius /* 距離 > 半径*/ ) {//現在いる座標と検知した円の中心からの距離が半径以上なら透過 alpha_img.at<cv::Vec4b>(cv::Point(x, y)) = cv::Vec4b(p[0], p[1], p[2], 0); //透過 } else { alpha_img.at<cv::Vec4b>(cv::Point(x, y)) = cv::Vec4b(p[0], p[1], p[2], 255); //不透過 } } }

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

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

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

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

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

yominet

2023/01/11 00:45

直接試せていないのでコメントで失礼。 imageがグレースケール=>8ビットシングルチャンネル(CV_8UC1)に変換されているため cv::Vec3b(8ビット3チャンネル用)で取り出すことが間違っていると思います。
syoshinnsyac

2023/01/11 01:52

yominetさんの指摘されたとおりだと思います ありがとうございます。 質問ばかりですみません。 グレイスケール画像にするとアルファチャンネル(透過度)は扱うことはできないのでしょうか?
yominet

2023/01/11 06:42

>グレイスケール画像にするとアルファチャンネル(透過度)は扱うことはできないのでしょうか? 主語がでかすぎて答えにならないのでヒントのようなものをいくつか、 1.画像1ch+透過情報1chのCV_8UC2形式のMatを、この意味で処理してくれる関数はOpenCVにはないはず。 2.画像と透過の2つMatをもち自分で管理する、もしくは必要時にCV_8UC4に変換して扱う。 例えば、質問にあるalpha_imgに入れたいのであれば BYTE p = image.at<BYTE>(cv::Point(x, y)); (略)   alpha_img.at<cv::Vec4b>(cv::Point(x, y)) = cv::Vec4b(p, p, p, A);// R,G,Bに同じもの入れる   とか
fana

2023/01/13 02:17 編集

> アルファチャンネル(透過度)は扱うことはできないのでしょうか? そもそも OpenCV に,あるチャンネルを「透過度」として扱うような処理(関数)自体が存在するのですか?(←私は見たことないし知らないので,もしもあるなら教えて欲しい) そのようなものが存在しないのであれば,「透過度」という意味合いのデータ値をどのように保持するか?に関しては,単純にあなたのプログラムの都合に合わせて好きにやれば良い…ということになると思います.
fana

2023/01/13 02:17

ここでの「透過させる」のゴールとは一体どのような状態を指すのか? っていうのが不明というか. 【8bit4chなMatの4ch目に「透過度」を示す値を入れること】がゴール?
syoshinnsyac

2023/01/13 18:34

yominetさんからいただいたヒントのBYTEはなぜかメンバーbyteがありませんとなったので 代わりに uchar p = image.at<uchar>(cv::Point(x, y)); とすることで解決することができました。
guest

回答1

0

自己解決

画像と透過の2つMatをもち自分で管理する、もしくは必要時にCV_8UC4に変換して扱う。
例えば、質問にあるalpha_imgに入れたいのであれば
BYTE p = image.at<BYTE>(cv::Point(x, y));
(略)
alpha_img.atcv::Vec4b(cv::Point(x, y)) = cv::Vec4b(p, p, p, A);// R,G,Bに同じもの入れる
とか

上記 yominetさんからいただいたヒントのBYTEはなぜかメンバーbyteがありませんとなったので 代わりに
uchar p = image.at<uchar>(cv::Point(x, y));
とすることで解決することができました。

投稿2023/01/14 08:58

syoshinnsyac

総合スコア1

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問