OpenCV 2.4.8 Ubuntu 14.04 imshow QMetaMethod::invoke Freeze
I've installed OpenCV 2.4.8 (libopencv-dev) by using apt-get and receive the following message.
init done opengl support available QMetaMethod::invoke: Unable to invoke methods with return values in queued connections.
I ran the program in gdb and it actually seems to stop and freeze on calling cv::waitKey(30); however, the problem only occurs when I call cv::imshow and it seems to be only when imshow is called in a callback function (in a single threaded program that had imshow in a loop did not exhibit the same problems).
Here is the backtrace:
#0 0x00007ffff27f8d7d in nanosleep () at ../sysdeps/unix/syscall-template.S:81
#1 0x00007ffff376d3c8 in ros::ros_wallsleep(unsigned int, unsigned int) ()
from /opt/ros/indigo/lib/librostime.so
#2 0x00007ffff4890877 in ros::waitForShutdown() () from /opt/ros/indigo/lib/libroscpp.so
#3 0x00007ffff48ac2f8 in ros::MultiThreadedSpinner::spin(ros::CallbackQueue*) ()
from /opt/ros/indigo/lib/libroscpp.so
#4 0x0000000000412267 in CM::Robot::Robot (this=0x7fffffffd210, handle=..., mod=...)
at /home/charlie/turtlebot/packages/mapping/src/robot.cc:88
#5 0x000000000041f128 in main (argc=1, argv=0x7fffffffd468)
at /home/charlie/turtlebot/packages/mapping/src/mapping.cc:32
Here is the output. I added a few cout statements to help decide exactly where the program was freezing.
Before
init done
opengl support available
Between
After
Before
QMetaMethod::invoke: Unable to invoke methods with return values in queued connections
Between
Killed
Here is a simplified version of the code that produces the problem: robot.h
# necessary include statements...
(opencv specific includes)
#include <opencv2/core/core.hpp>
#include <opencv2/nonfree/nonfree.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <highgui.h>
Robot {
public:
Robot(ros::NodeHandle& handle, const std::string& mod): node(handle), mode(mod){
ros::MultiThreadedSpinner threads(3);
ros::Subscriber odom = node.subscribe("/odom", 1, &Robot::get_pose, this);
ros::Subscriber cloud = node.subscribe("/camera/depth/points", 1, &Robot::add_cloud, this);
threads.spin();
}
void get_pose(nav_msgs::Odometry data){
(...)
}
void add_cloud(sensor_msgs::PointCloud2 cloud){
PointCloud::Ptr cl(new(PointCloud));
pcl::fromROSMsg(cloud, *cl);
cl->width = 640;
cl->height = 480;
extract_surf_features(cl);
(...)
}
void extract_surf_features(pcl::PointCloud<pcl::PointXYZRGB>::Ptr points){
cv::Mat image(cur->height, cur->width, CV_8UC3);
(... get 2d rgb image from point cloud ...)
cv::SURF surf_extractor(500.0); // Hession threshold = 500.0
std::vector<cv::KeyPoint> keypoints;
// actually compute the surf keypoints
surf_extractor(image, cv::Mat(), keypoints);
cv::drawKeypoints(image, keypoints, image, cv::Scalar::all(-1), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
cout << "Before\n";
cv::imshow("Image", image);
cout << "Between\n";
cv::waitKey(30);
cout << "After\n";
(...)
}
private:
ros::NodeHandle node;
std::string mode;
}
main.cc:
#include <ros/ros.h>
#include <iostream>
#include "robot.h"
using namespace std;
int main(int argc, char** argv){
ros::init(argc, argv, "PCL_Map");
if (!ros::master::check()){
cout << "\033[1;31mERROR: ROS Master not found. Please Start ROS.\n\033[0m";
return -1;
}
ros::NodeHandle node("/map/pcl");
node.setParam("downsample", 0.04);
CM::Robot robot(node,"SURF");
return 0;
}
I have written another very similar program that does not exhibit the freezing behaviors ...
hmm you are using PCL and ROS which are both packages based on core OpenCV functionality but not maintained by OpenCV. So it will be hard to debug those parts in this forum. On the other hand I never get why people use preconfigure packages. Download the latest github 2.4 branch of OpenCV and built it yourself. Works perfectly here on Ubuntu14.04
Hi Steven, I forgot to mention but I also used a source installed version of Opencv 2.4.8. I think I've found the why of the program crash but not the how to fix (other than rewriting the program to have a specific thread for imshow). I was reading another persons problem that was similar and it seems imshow is not threadsafe as in problems occur when you try to update the same window from different threads.
Ow yeah .. imshow has been made for debugging purposes mainly. Basically if you want to create thread safety, you should add some timeout after drawing until the internal drawing is completely finished before firing it up in another thread or something like this. This is indeed known afaik.
Basically adding a waitKey(1) after each imshow will solve this problem. However this is sometimes unwanted to hold your thread for a millisec.