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;
    cv::imshow("Original", train);
    cv::imshow("Gray", train_g);
  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_;
   // 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


 void imageCb(const sensor_msgs::ImageConstPtr& msg)

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

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

// 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.


 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;


 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);

     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)
    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

int main(int argc, char** argv)
  ros::init(argc, argv, "Edge_Detector");
  ros::NodeHandle nh; 
  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);
   Edge_Detector ic;
  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.


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


1 Answer 1


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


Your Answer

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