実現したいこと
opencvで三角形以外を黒塗りにするプログラムを作成しました。
その後、別のプログラムに応用しようと思ったのですが思うように動かせないのでどこの部分を修正すればいいのかを教えてほしいです。
前提
opencvを使用しています。言語はC++です。
先日opencvで三角形以外を黒塗りにするプログラムを作成しました
下記のコードを動かしたところ三角形の中身以外を黒塗りにすることができました。
#include <ros/ros.h>
#include <opencv2/opencv.hpp>
int main(int argc, char **argv) {
ros::init(argc, argv, "zukei_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); cv::Mat Mask( img.size(), CV_8UC1 ); //マスク画像バッファを用意 Mask = 255; //全域を白にする // 輪郭を抽出 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::fillPoly(img, cnt, cv::Scalar(0, 0, 0)); cv::fillConvexPoly(Mask, cnt, cv::Scalar(0, 0, 0)); //マスク画像に描画する double area = cv::contourArea(cnt); std::cout << "Area of triangle " << triangle << " = " << area << std::endl; } } img.setTo( cv::Scalar(0), Mask ); // 透明にする色を指定(ここでは緑色) cv::Scalar targetColor(0, 0, 0); // BGR順 // 透明度の設定 uchar alpha = 0; // 0: 完全透明, 255: 完全不透明 // 指定した色のピクセルを透明にする cv::Mat mask; cv::inRange(img, targetColor, targetColor, Mask); // 指定した色のピクセルだけを白にするマスクを作成 img.setTo(cv::Scalar(0, 0, 0, alpha), Mask); // 指定した色のピクセルを透明にする // 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;
}
このコードは三角形以外を黒塗りにした画像を出力できました。
そのため次のコードを書いて実行したところ画像がすべて真っ黒になってしまいました。
#include <opencv2/opencv.hpp>
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <sensor_msgs/Image.h>
#include <cv_bridge/cv_bridge.h>
#include <image_transport/image_transport.h>
geometry_msgs::Twist twist;
void ImgCallback(){
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); cv::Mat Mask( img.size(), CV_8UC1 ); //マスク画像バッファを用意 Mask = 255; //全域を白にする // 輪郭を抽出 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_xor; cv::Mat img_test; //図形の設定 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); 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(Mask, cnt, cv::Scalar(0, 0, 0)); //マスク画像に描画する double area = cv::contourArea(cnt); std::cout << "Area of triangle " << triangle << " = " << area << std::endl; img_test = img; if (area > 5000){ twist.linear.x = 0.0; twist.linear.y = 0.0; twist.linear.z = 0.0; twist.angular.x = 0.0; twist.angular.y = 0.0; twist.angular.z = 0.0; } else{ twist.linear.x = 0.1; twist.linear.y = 0.0; twist.linear.z = 0.0; twist.angular.x = 0.0; twist.angular.y = 0.0; twist.angular.z = 0.0; } } } img.setTo( cv::Scalar(0), Mask ); // 透明にする色を指定(ここでは緑色) cv::Scalar targetColor(0, 0, 0); // BGR順 // 透明度の設定 uchar alpha = 0; // 0: 完全透明, 255: 完全不透明 // 指定した色のピクセルを透明にする cv::Mat mask; cv::inRange(img, targetColor, targetColor, Mask); // 指定した色のピクセルだけを白にするマスクを作成 img.setTo(cv::Scalar(0, 0, 0, alpha), Mask); // 指定した色のピクセルを透明にする bitwise_xor(img, img_test, img_xor); // 結果の画像作成 cv::imwrite("/home/robotpc/catkin_ws/src/timesyncsub/src/orbmix/img/output__img2.jpg", img_xor); // 図形の数の結果 std::cout << "Number of triangle = " << triangle << std::endl; cv::imshow("Result", img); cv::waitKey(0);
}
int main(int argc, char **argv){
ros::init(argc, argv, "open_whill_node");
ros::NodeHandle nh;
ros::Publisher twist_pub = nh.advertise<geometry_msgs::Twist>("/whill/controller/cmd_vel", 10);
image_transport::ImageTransport it(nh);
//image_transport::Subscriber sub = it.subscribe("usb_camera/image_raw", 1, ImgCallback);
ros::Rate loop_rate(1);
while(ros::ok()){ ros::spinOnce(); // コールバック関数を呼び出す std::cout << "現在の速度 : " << twist.linear.x <<"m/s" << std::endl; ImgCallback(); twist_pub.publish(twist); loop_rate.sleep(); } return 0;
}
このコードのどこを修正すれば画面内の三角形内以外を黒塗りにする画像が出力されますか。
拙い文章ではありますがお願い致します。
試したこと
mg.setTo( cv::Scalar(0), Mask );
// 透明にする色を指定(ここでは緑色)
cv::Scalar targetColor(0, 0, 0); // BGR順
// 透明度の設定
uchar alpha = 0; // 0: 完全透明, 255: 完全不透明
// 指定した色のピクセルを透明にする
cv::Mat mask;
cv::inRange(img, targetColor, targetColor, Mask); // 指定した色のピクセルだけを白にするマスクを作成
img.setTo(cv::Scalar(0, 0, 0, alpha), Mask); // 指定した色のピクセルを透明にする
このコードの位置が悪いのかと考え、このコードの部分を直前の1つ前の}、2つ前の}に移動して実行したのですが結果が変わりませんでした。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。

0 コメント