0
$\begingroup$

Rosanswers logo

Hi all! First question in the site!

Hope you guys can help me out, I've got a problem by trying to use an image inside a function. In this function I got an example of edge detector from the camera. I want to use SIFT Feature Detector but I can't manage to use the information of the image. I think it is because in some way I haven't made the callback properly.

I have a node that publishes image and in an other node I want to subscribe to that image and compare it with the video frame. The only way I got to read that image is putting the subscriber in the main function.

#include <ros/ros.h>
#include <iostream>
#include <sstream>
#include <math.h>
#include <string>
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/types_c.h>
#include <opencv2/core/core_c.h>
#include <opencv2/xfeatures2d/nonfree.hpp>
#include <opencv2/features2d/features2d.hpp>

using namespace cv;
using namespace std;
using namespace xfeatures2d;

Mat train, train_g;
Mat train_desc;
vector<KeyPoint> train_kp;
static const std::string OPENCV_WINDOW = "Raw Image window";
static const std::string OPENCV_WINDOW_1 = "Edge Detection";
static const std::string OPENCV_WINDOW_2 = "TEST_G";

void imageCallback(const sensor_msgs::ImageConstPtr& msg) {
   try {
    
        train=cv_bridge::toCvShare(msg, "bgr8")->image;
    cvtColor(train,train_g,CV_BGR2GRAY);    
    cv::imshow("Original", train);
    cv::imshow("Gray", train_g);
    cv::waitKey(30);
 }
  catch (cv_bridge::Exception& e) {
    ROS_ERROR("Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str());
  }
}

class Edge_Detector
{
  ros::NodeHandle nh_;
  image_transport::ImageTransport it_;
  image_transport::Subscriber image_sub_;
  image_transport::Publisher image_pub_;
  
public:
 Edge_Detector():it_(nh_)
 {
   // Subscribe to input video feed and publish output video feed
   image_sub_ = it_.subscribe("/cv_camera/image_raw", 1, &Edge_Detector::imageCb, this); //usb_cam
   image_pub_ = it_.advertise("/edge_detector/raw_image", 1); ///edge_detector/raw_image
   //createTrackbars();
 }

 ~Edge_Detector()
 {
  cv::destroyWindow(OPENCV_WINDOW);
 }

 void imageCb(const sensor_msgs::ImageConstPtr& msg)
 {

   cv_bridge::CvImagePtr cv_ptr;
   namespace enc = sensor_msgs::image_encodings;

   try
       {
       cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
       }
       catch (cv_bridge::Exception& e)
       {
       ROS_ERROR("cv_bridge exception: %s", e.what());
       return;
       }

// Draw an example circle on the video stream
//if (cv_ptr->image.rows > 400 && cv_ptr->image.cols > 600){

detect_edges(cv_ptr->image); // sth tells me here is the problem, I'm not caling the image but I have tried many things and still doesn't work.
    image_pub_.publish(cv_ptr->toImageMsg());

//}
    }


 void detect_edges(cv::Mat img) {
    
     cv::Mat src, src_gray;
 cv::Mat dst, detected_edges;

     int edgeThresh = 1;
 int lowThreshold = 200;
 int highThreshold =300;
 int kernel_size = 5;

 img.copyTo(src);

 cv::cvtColor( img, src_gray, CV_BGR2GRAY );
     cv::blur( src_gray, detected_edges, cv::Size(5,5) );
 cv::Canny( detected_edges, detected_edges, lowThreshold, highThreshold, kernel_size );

 dst = cv::Scalar::all(0);
 img.copyTo( dst, detected_edges);
 dst.copyTo(img);

     Mat test, test_g;

    cv::cvtColor(img, test_g, CV_BGR2GRAY);


 //detect SIFT keypoints and extract descriptors in the test image
vector<KeyPoint> test_kp;
Mat test_desc;
Ptr<SiftFeatureDetector> featureDetector=SiftFeatureDetector::create();//SiftFeatureDetector featureDetector;
featureDetector->detect(test_g, test_kp);//featureDetector.detect(test_g, test_kp);
Ptr<SiftDescriptorExtractor> featureExtractor=SiftDescriptorExtractor::create(); //SiftDescriptorExtractor featureExtractor;
featureExtractor->compute(test_g, test_kp, test_desc);//featureExtractor.compute(test_g, test_kp, test_desc);

     BFMatcher matcher; 
 // match train and test descriptors, getting 2 nearest neighbors for all test descriptors
 vector<vector<DMatch> > matches;
 matcher.knnMatch(test_desc, matches, 2);

 // filter for good matches according to Lowe's algorithm
 vector<DMatch> good_matches;
 for(int i = 0; i < matches.size(); i++) {
        if(matches[i][0].distance < 0.6 * matches[i][1].distance)
       good_matches.push_back(matches[i][0]);
}
     
    Mat img_show;
drawMatches(test, test_kp, train, train_kp, good_matches, img_show);
imshow("Matches", img_show);

    cv::imshow(OPENCV_WINDOW, src);//black_h_range - src
    //cv::imshow(OPENCV_WINDOW_1, dst);//edges - dst
cv::imshow(OPENCV_WINDOW_2, test_g);//edges - dst
    cv::waitKey(3);
    }   
};

int main(int argc, char** argv)
{
  ros::init(argc, argv, "Edge_Detector");
  ros::NodeHandle nh; 
  cv::namedWindow("Original");
  cv::startWindowThread();
  image_transport::ImageTransport it(nh);
  image_transport::Subscriber sub = it.subscribe("camera/image", 1, imageCallback);
  //detect SIFT keypoints and extract descriptors in the train image
    vector<KeyPoint> train_kp;
Mat train_desc;
Ptr<SiftFeatureDetector> featureDetector=SiftFeatureDetector::create();//SiftFeatureDetector featureDetector;
featureDetector->detect(train_g, train_kp);//featureDetector.detect(train_g, train_kp);
Ptr<SiftDescriptorExtractor> featureExtractor=SiftDescriptorExtractor::create();//SiftDescriptorExtractor featureExtractor;
featureExtractor->compute(train_g, train_kp, train_desc);//featureExtractor.compute(train_g, train_kp, train_desc);

// Brute Force based descriptor matcher object
BFMatcher matcher;
vector<Mat> train_desc_collection(1, train_desc);
matcher.add(train_desc_collection);
matcher.train();
   Edge_Detector ic;
  ros::spin();
  return 0;
}

That is the code! That is the only way I manage to get it working. But when I start the camera node crashes. Hope you can give me some advice. Also, I'm not so skill in programming. Thanks in advance.

Update:

This is the error message I get while trying to run it.

OpenCV Error: Assertion failed (!outImage.empty()) in drawKeypoints, file /tmp/binarydeb/ros-kinetic-opencv3-3.2.0/modules/features2d/src/draw.cpp, line 115 terminate called after throwing an instance of 'cv::Exception'
  what():  /tmp/binarydeb/ros-kinetic-opencv3-3.2.0/modules/features2d/src/draw.cpp:115: error: (-215) !outImage.empty() in function drawKeypoints

Aborted (core dumped)

Originally posted by DAC31415 on ROS Answers with karma: 1 on 2017-08-12

Post score: 0


Original comments

Comment by jayess on 2017-08-12:
What do you mean by "I can't manage to use the information of the image" and "I think it is because in some way I haven't made the callback properly"? Why do you believe this? Is there any terminal output that you can copy and paste such as errors/warnings?

Comment by DAC31415 on 2017-08-12:
Yes, I got this: OpenCV Error: Assertion failed (!outImage.empty()) in drawKeypoints, file /tmp/binarydeb/ros-kinetic-opencv3-3.2.0/modules/features2d/src/draw.cpp, line 115 terminate called after throwing an instance of 'cv::Exception' what(): /tmp/binarydeb/ros-kinetic-opencv3-3.2.0/modul....

Comment by DAC31415 on 2017-08-12:
/modules/features2d/src/draw.cpp:115: error: (-215) !outImage.empty() in function drawKeypoints

Aborted (core dumped)

As far as I know and investigated it is because I have and empty mat and I guess is the image.

Comment by jayess on 2017-08-12:
Please update your question with any errors (such as the one you just mentioned) and warnings.

Comment by DAC31415 on 2017-08-12:
Ok, that's the only one. thx

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

According to this answer on Stack Overflow, it may be from these lines:

Mat img_show;
drawMatches(test, test_kp, train, train_kp, good_matches, img_show);

The error message hints that it's not expecting an empty() image. You can try to initialize the image with black pixels first:

img_show = Mat::zeros(img_1.size(), CV_8UC3 );

Notice I'm using the first image dimensions/size, assuming both images have the same size. Be sure double check your setup and use the appropriate size. Additionally you can put the block in a try...catch block to see the details:

try {  //your drawKeyPoints code here
} catch (cv::Exception &e) { 
  cerr <<  e.msg << endl;  
}

Originally posted by jayess with karma: 6155 on 2017-08-12

This answer was ACCEPTED on the original site

Post score: 0


Original comments

Comment by jayess on 2017-08-13:
I noticed a copy and paste error on my part so I updated the answer with img_show instead of img_matches

Comment by DAC31415 on 2017-08-16:
I added that lines and the same error message. I will try to separate the program in different nodes. THX

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.