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

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

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

Q&A

解決済

1回答

400閲覧

opencvで取り込んだ画像内の三角形の部分以外を塗りつぶしたい

gorigonsamurai

総合スコア1

0グッド

0クリップ

投稿2023/12/22 05:54

実現したいこと

  • 取り込んだ画像内の三角形の部分以外を塗りつぶしたい

前提

opencvで取り込んだ画像内にある三角形に輪郭をつけるプログラムを作りました。
その後に輪郭の外側を黒く塗りつぶしてその画像を出力したいです。
言語はC++です。

試したこと

下記のコードを実行すると画像内の三角形の内側が塗りつぶされました。

#include <ros/ros.h>
#include <opencv2/opencv.hpp>

int main(int argc, char **argv) {

ros::init(argc, argv, "zykei_node"); // ファイルを読み込み グレースケール化 cv::Mat img = cv::imread("/home/robotpc/catkin_ws/src/timesyncsub/src/orbmix/img/test_img2.png", cv::IMREAD_GRAYSCALE); // ガウシアンぼかしを適用してノイズを軽減 // GaussianBlur(img, img, cv::Size(5, 5), 0); // しきい値指定によるフィルタリング cv::Mat threshold; cv::threshold(img, threshold, 240, 255, cv::THRESH_BINARY); // // Cannyエッジ検出 // Canny(img, img, 50, 150); // 輪郭を抽出 std::vector<std::vector<cv::Point>> contours; std::vector<cv::Vec4i> hierarchy; cv::findContours(threshold, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE); // 図形の数の変数 int triangle = 0; cv::Mat img_test; cv::Mat img_origin; //図形の設定 for (const auto& cnt : contours) { std::vector<cv::Point> approx; cv::approxPolyDP(cnt, approx, 0.005 * cv::arcLength(cnt, true), true); cv::drawContours(img, std::vector<std::vector<cv::Point>>{approx}, 0, cv::Scalar(0), 2); img_origin = img; int x = approx[0].x; int y = approx[0].y; if (approx.size() == 3) { triangle++; cv::putText(img, "triangle" + std::to_string(triangle), cv::Point(x, y), cv::FONT_HERSHEY_DUPLEX, 0.8, cv::Scalar(1)); cv::fillConvexPoly(img, cnt, cv::Scalar(0, 0, 0)); double area = cv::contourArea(cnt); std::cout << "Area of triangle " << triangle << " = " << area << std::endl; } } // bitwise_xor(img, img_test, img_xor); // 結果の画像作成 cv::imwrite("/home/robotpc/catkin_ws/src/timesyncsub/src/orbmix/img/output__img2.jpg", img); // 図形の数の結果 std::cout << "Number of triangle = " << triangle << std::endl; cv::imshow("Result", img); cv::waitKey(0); return 0;

}

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答1

0

ベストアンサー

cv::Mat::setTo というメソッドがあります.
マスクで指定した範囲の画素値を特定の値に変更することができます.

三角形の内側を塗りつぶすことができるのであれば,

  • 画像と同じサイズのマスク画像用バッファ(8bit 1ch かな)を用意する.
  • マスク画像全域を白(255)にしておく.
  • 「三角形の内側を黒(0)に塗りつぶす処理」をマスク画像に対して行う.

という手順でマスク画像を作ることができると思うので,後はそれを前記のsetTo に用いれば良いのではないでしょうか.


あるいは cv::Mat::copyTo を用いるのでも良さそうです.
こちらは「マスクで指定した範囲だけをコピーする」ことができます.
↑と丁度白黒逆なマスクを用意して用いれば,元画像のうちの三角形の内側だけを別の画像にコピーできます.
「別の画像」をあらかじめ真っ黒にしておけば所望の結果が得られそうです.

または,この形のマスクを bitwise_and で用いるのでも良いでしょう.

投稿2023/12/22 06:16

編集2023/12/22 06:39
fana

総合スコア12151

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

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

gorigonsamurai

2023/12/22 06:26

回答有り難うございます。cv::Mat::setT を私が載せているコードに追加するとしたらどのように修正すればよいでしょうか?良ければ教えていただきたいです。
fana

2023/12/22 06:45

この話を実施するにあたり,何がわからないのか? がわからないのですが… とりあえず箇条書きにしてある事柄をやってみてはどうです? > ・画像と同じサイズのマスク画像用バッファ(8bit 1ch かな)を用意する. > ・マスク画像全域を白(255)にしておく. //どこか最初の方で cv::Mat Mask( img.size(), CV_8UC1 ); //マスク画像バッファを用意 Mask = 255; //全域を白にする > ・「三角形の内側を黒(0)に塗りつぶす処理」をマスク画像に対して行う. これは,今のコードにある cv::fillConvexPoly(img, cnt, cv::Scalar(0, 0, 0)); を cv::fillConvexPoly(Mask, cnt, cv::Scalar(0, 0, 0)); //マスク画像に描画する に変えれば良いのではないでしょうか. で,最後に(forループを抜けた後あたりで) img.setTo( cv::Scalar(0), Mask ); とかすればよいのでは.
fana

2023/12/22 06:52 編集

で,もしもやってみた結果がうまくない場合には, 「こいつの言ってる通りにやってみたのに全然ダメなんだが?」みたいな話を質問文に追記(今の質問文を消すのではなくて,後ろに話を追加する形で編集)すると良いです. そうすれば,他の人にも話の経緯が分かるので,「いや,それはこうでは?」みたいな回答をしてくれやすいでしょう.
gorigonsamurai

2023/12/22 13:44

丁寧なご回答ありがとうございます。意見を参考にしたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問