前提
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); //不透過 } } }
直接試せていないのでコメントで失礼。
imageがグレースケール=>8ビットシングルチャンネル(CV_8UC1)に変換されているため
cv::Vec3b(8ビット3チャンネル用)で取り出すことが間違っていると思います。
yominetさんの指摘されたとおりだと思います ありがとうございます。
質問ばかりですみません。
グレイスケール画像にするとアルファチャンネル(透過度)は扱うことはできないのでしょうか?
>グレイスケール画像にするとアルファチャンネル(透過度)は扱うことはできないのでしょうか?
主語がでかすぎて答えにならないのでヒントのようなものをいくつか、
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に同じもの入れる
とか
> アルファチャンネル(透過度)は扱うことはできないのでしょうか?
そもそも OpenCV に,あるチャンネルを「透過度」として扱うような処理(関数)自体が存在するのですか?(←私は見たことないし知らないので,もしもあるなら教えて欲しい)
そのようなものが存在しないのであれば,「透過度」という意味合いのデータ値をどのように保持するか?に関しては,単純にあなたのプログラムの都合に合わせて好きにやれば良い…ということになると思います.
ここでの「透過させる」のゴールとは一体どのような状態を指すのか? っていうのが不明というか.
【8bit4chなMatの4ch目に「透過度」を示す値を入れること】がゴール?
yominetさんからいただいたヒントのBYTEはなぜかメンバーbyteがありませんとなったので 代わりに
uchar p = image.at<uchar>(cv::Point(x, y));
とすることで解決することができました。

回答1件
あなたの回答
tips
プレビュー