00001 #include <ros/ros.h>
00002 #include <ros/node_handle.h>
00003 #include <cstdlib>
00004 #include <robot_mask/GetMask.h>
00005 #include <string.h>
00006 #include "cv_bridge/CvBridge.h"
00007 #include <opencv2/highgui/highgui.hpp>
00008 #include <opencv2/core/core.hpp>
00009 #include <boost/thread.hpp>
00010 #include <sensor_msgs/Image.h>
00011 #include <message_filters/subscriber.h>
00012 #include <sensor_msgs/image_encodings.h>
00013 #include <siftfast/siftfast.h>
00014
00015 using namespace message_filters;
00016 using namespace cv::flann;
00017 using namespace cv;
00018
00020 class LatestMatchingTFMessage
00021 {
00022 private:
00023 ros::Subscriber tf_sub_;
00024 ros::Subscriber image_sub_;
00025 std::string source_frame_, camera_frame_;
00026 int fovy_, width_, height_, count_ ;
00027 ros::NodeHandle nh_;
00028 bool valid_, save_images_;
00029 public:
00030 ros::ServiceClient client ;
00031 robot_mask::GetMask srv;
00032 tf::tfMessageConstPtr tf_state , last_matching_tf;
00033 std::string tf_topic_, image_topic_;
00034 sensor_msgs::CvBridge bridge_;
00035 cv::Mat mask_, original_image_ , final_image_ , image_, image_roi_ , image_roi2_;
00036 Rect rect_;
00037 std::string mode_;
00038 double radius_;
00039 int min_nn_ , knn_ ;
00040
00041 LatestMatchingTFMessage(ros::NodeHandle &nh, const std::string &source_frame)
00042 : source_frame_(source_frame),
00043 nh_ (nh),
00044 valid_(false)
00045 {
00046
00047 nh_.param("tf_topic", tf_topic_, std::string("/tf"));
00048 nh_.param("image_topic", image_topic_, std::string("/camera/rgb/image_mono"));
00049 tf_sub_ = nh_.subscribe(tf_topic_, 1, &LatestMatchingTFMessage::TFcallback, this);
00050 image_sub_ = nh_.subscribe(image_topic_, 1, &LatestMatchingTFMessage::Imagecallback, this);
00051
00052
00053 nh_.param("fovy", fovy_, 25);
00054 nh_.param("width", width_, 640);
00055 nh_.param("height", height_, 480);
00056 nh_.param("camera_frame", camera_frame_, std::string("openni_rgb_optical_frame"));
00057 nh_.param("save_images", save_images_, true);
00058 nh_.param("mode", mode_ , std::string("knn_search"));
00059 nh_.param("min_nn", min_nn_ , 2);
00060 nh_.param("knn", knn_ , 2);
00061 srv.request.width = width_;
00062 srv.request.height = height_;
00063 srv.request.fovy = fovy_;
00064 srv.request.camera_frame = camera_frame_;
00065 count_ = 0;
00066 radius_ = 30;
00067
00068
00069 client = nh.serviceClient<robot_mask::GetMask>("/robot_mask/get_mask");
00070
00071 mask_.create(srv.request.height, srv.request.width, CV_8UC1);
00072 final_image_.create(srv.request.height, srv.request.width, CV_8UC1);
00073
00074 }
00076
00079 void TFcallback(const tf::tfMessageConstPtr &msg )
00080 {
00081 for (uint i = 0; i < msg->transforms.size(); i++)
00082 {
00083
00084 if(!valid_)
00085 {
00086 if(msg->transforms[i].header.frame_id == source_frame_)
00087 {
00088 last_matching_tf = msg;
00089 valid_ = true;
00090 }
00091 }
00092 }
00093 }
00094
00096
00104 void Imagecallback(const sensor_msgs::ImageConstPtr& image )
00105 {
00106 ROS_INFO("[LatestMatchingTFMessage:] Image received in frame: %s with height %d and width %d",
00107 image->header.frame_id.c_str(), image->height, image->width);
00108 if(valid_)
00109 {
00110 srv.request.tf_state = *last_matching_tf;
00111 ROS_INFO("[LatestMatchingTFMessage:] waiting for service server...");
00112 if(!client.waitForExistence (ros::Duration (1)))
00113 {
00114 ROS_ERROR("[LatestMatchingTFMessage:] Could not find service.");
00115 }
00116
00117 try
00118 {
00119 original_image_ = bridge_.imgMsgToCv(image);
00120 ROS_INFO("[LatestMatchingTFMessage:] Image converted");
00121 }
00122 catch (sensor_msgs::CvBridgeException error)
00123 {
00124 ROS_ERROR("error");
00125 }
00126 ROS_INFO("[LatestMatchingTFMessage:] The server was found - calling now");
00127
00128 if (client.call(srv))
00129 {
00130
00131
00132 for (unsigned int i=0; i < srv.response.mask.size(); i++)
00133 {
00134 if (srv.response.mask[i] == 1)
00135 mask_.at<uint8_t>(i/mask_.cols, i%mask_.cols) = 0;
00136 else
00137 mask_.at<uint8_t>(i/mask_.cols, i%mask_.cols) = 255;
00138 }
00139
00140 for (int i=0; i < mask_.rows; i++)
00141 {
00142 for ( int j = 0; j < mask_.cols; j++)
00143 {
00144 if (mask_.at<uint8_t>(i,j-1) == mask_.at<uint8_t>(i,j))
00145 mask_.at<uint8_t>(i,j-1) = mask_.at<uint8_t>(i,j);
00146 else
00147 {
00148
00149 mask_.at<uint8_t>(i,j-1) = 0;
00150 mask_.at<uint8_t>(i,j-2) = 0;
00151 mask_.at<uint8_t>(i,j-3) = 0;
00152 mask_.at<uint8_t>(i,j-4) = 0;
00153 mask_.at<uint8_t>(i,j-5) = 0;
00154 mask_.at<uint8_t>(i,j-6) = 0;
00155 mask_.at<uint8_t>(i,j-7) = 0;
00156 mask_.at<uint8_t>(i,j-8) = 0;
00157 mask_.at<uint8_t>(i,j-9) = 0;
00158 mask_.at<uint8_t>(i,j-10) = 0;
00159 mask_.at<uint8_t>(i,j-11) = 0;
00160 mask_.at<uint8_t>(i,j-12) = 0;
00161 mask_.at<uint8_t>(i,j-13) = 0;
00162 mask_.at<uint8_t>(i,j-14) = 0;
00163 mask_.at<uint8_t>(i,j-15) = 0;
00164 }
00165 }
00166 }
00167 }
00168 else
00169 {
00170 ROS_ERROR("[LatestMatchingTFMessage:] Failed to call service robot_mask");
00171 valid_ = false;
00172 return;
00173 }
00174 ROS_INFO("after service call");
00175
00176 final_image_.zeros(srv.request.height, srv.request.width, CV_8UC1);
00177
00178 bitwise_and(original_image_, mask_, final_image_);
00179 valid_ = false ;
00180 }
00181 else
00182 {
00183 valid_ = false;
00184 return;
00185 }
00186 if(mode_ == "manual")
00187 {
00188 Keypoint template_keypoints = extract_keypoints(final_image_ ,true);
00189 Keypoint template_keypoints1 = template_keypoints;
00190
00191 rect_.x = 262;
00192 rect_.y = 133;
00193 rect_.width = 126;
00194 rect_.height = 267;
00195
00196 image_roi_ = extract_roi(final_image_, template_keypoints, rect_);
00197 visualize(final_image_ , template_keypoints1);
00198
00199 cv::namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
00200 cv::namedWindow("Mask", CV_WINDOW_AUTOSIZE);
00201 cv::namedWindow("Mask Image", CV_WINDOW_AUTOSIZE);
00202 cv::namedWindow("Keypoints Image", CV_WINDOW_AUTOSIZE);
00203 cv::namedWindow("Rect Image", CV_WINDOW_NORMAL);
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 if (save_images_)
00215 {
00216 count_++;
00217 std::stringstream ss;
00218 ss << count_;
00219 cv::imwrite(ss.str() + ".png", original_image_);
00220 cv::imwrite(ss.str() + "a.png", final_image_ );
00221 cv::imwrite(ss.str() + "b.png", image_roi_);
00222 cv::imwrite(ss.str() + "c.png", image_ );
00223 }
00224 }
00225 else if(mode_ == "radius_search")
00226 {
00227 cv::Mat query , indices , dists, output_image;
00228 query.create(0, 2, CV_32FC1);
00229 Keypoint template_keypoints2 = extract_keypoints(final_image_ , true);
00230
00231
00232 int query_rows = 0;
00233 for (int k=0; template_keypoints2 != NULL; ++k, template_keypoints2 = template_keypoints2->next)
00234 {
00235 cv::Mat q(1, 2, CV_32FC1);
00236 q.at<float>(0, 0) = template_keypoints2->col;
00237 q.at<float>(0, 1) = template_keypoints2->row;
00238 query.push_back(q);
00239 query_rows = k;
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 indices.create(0, query_rows, CV_32SC1);
00257 dists.create(0, query_rows, CV_32FC1);
00258 ROS_INFO("indices: %d %d ", indices.rows, indices.cols);
00259
00260
00261 radiusSearch(query, indices, dists, radius_);
00262
00263 cv::Mat min_indices(0, indices.cols, CV_32SC1);
00264
00265 std::vector<int> inliers;
00266
00267
00268
00269 for (int i = 0; i < indices.rows; i++)
00270 {
00271
00272 if (indices.at<int>(i, min_nn_) != 0)
00273 {
00274 continue;
00275 }
00276 else
00277 {
00278 inliers.push_back(i);
00279 }
00280 }
00281
00282 ROS_INFO("image_final %d, %d", final_image_.rows, final_image_.cols);
00283 output_image.create(final_image_.rows , final_image_.cols, CV_8UC3);
00284
00285
00286 cvtColor(final_image_, output_image, CV_GRAY2RGB );
00287
00288 image_roi2_ = extract_roi(inliers, query, output_image);
00289 visualize(inliers, query, output_image);
00290
00291
00292
00293
00294
00295
00296
00297
00298 if (save_images_)
00299 {
00300 count_++;
00301 std::stringstream ss;
00302 ss << count_;
00303 cv::imwrite(ss.str() + ".png", output_image);
00304 cv::imwrite(ss.str() + "a.png", image_roi2_);
00305 }
00306 }
00307 else if(mode_ == "knn_search")
00308 {
00309 cv::Mat query , indices , dists, output_image;
00310 query.create(0, 2, CV_32FC1);
00311 Keypoint template_keypoints2 = extract_keypoints(final_image_ , true);
00312
00313
00314 int query_rows = 0;
00315 for (int k=0; template_keypoints2 != NULL; ++k, template_keypoints2 = template_keypoints2->next)
00316 {
00317 cv::Mat q(1, 2, CV_32FC1);
00318 q.at<float>(0, 0) = template_keypoints2->col;
00319 q.at<float>(0, 1) = template_keypoints2->row;
00320 query.push_back(q);
00321
00322 query_rows = k;
00323 }
00324
00325 ROS_INFO("query: %d %d ", query.rows, query.cols);
00326
00327 indices.create(0, query_rows, CV_32SC1);
00328 dists.create(0, query_rows, CV_32FC1);
00329 ROS_INFO("indices: %d %d ", indices.rows, indices.cols);
00330
00331
00332 knnSearch(query, indices, dists, min_nn_);
00333
00334
00335
00336 std::vector<int> inliers;
00337
00338
00339
00340 for (int i = 0; i < dists.rows; i++)
00341 {
00342 bool has_outliers = false;
00343 for (int j = 0; j < dists.cols; j++)
00344 {
00345
00346 if (dists.at<float>(i,j) != 0 && dists.at<float>(i,j) > radius_)
00347 {
00348 has_outliers = true;
00349 }
00350 }
00351 if (!has_outliers)
00352 inliers.push_back(i);
00353 has_outliers = false;
00354 }
00355
00356 ROS_INFO("image_final %d, %d", final_image_.rows, final_image_.cols);
00357
00358 output_image.create(final_image_.rows , final_image_.cols, CV_8UC3);
00359 cvtColor(final_image_, output_image, CV_GRAY2RGB );
00360
00361 image_roi2_ = extract_roi(inliers, query, output_image);
00362 visualize(inliers, query, output_image);
00363
00364
00365
00366
00367
00368
00369
00370
00371 if (save_images_)
00372 {
00373 count_++;
00374 std::stringstream ss;
00375 ss << count_;
00376 cv::imwrite(ss.str() + ".png", output_image);
00377 cv::imwrite(ss.str() + "a.png", image_roi2_);
00378 }
00379 }
00380 else
00381 return;
00382 }
00384
00390 void radiusSearch(Mat& query, Mat& indices, Mat& dists, double radius)
00391 {
00392
00393 Index* index;
00394
00395
00396 index = new Index (query, LinearIndexParams() );
00397
00398 for( int i = 0; i < query.rows; i++ )
00399 {
00400
00401 Mat q(1, query.cols, CV_32FC1, query.ptr<float>(i) );
00402 Mat in;
00403 in = Mat::zeros(1, indices.cols, CV_32SC1);
00404 Mat di;
00405 di = Mat::zeros(1, dists.cols,CV_32FC1);
00406
00407 index->radiusSearch( q, in, di, radius_ , SearchParams() );
00408 indices.push_back(in);
00409 dists.push_back(di);
00410 }
00411
00412 delete index;
00413 }
00414
00416
00422 void knnSearch(Mat& query, Mat& indices, Mat& dists, int knn)
00423 {
00424 Index* index;
00425 index = new Index (query, LinearIndexParams() );
00426 for( int i = 0; i < query.rows; i++ )
00427 {
00428 Mat q(1, query.cols, CV_32FC1, query.ptr<float>(i) );
00429 Mat in;
00430 in = Mat::zeros(1, indices.cols, CV_32SC1);
00431 Mat di;
00432 di = Mat::zeros(1, dists.cols,CV_32FC1);
00433 index->knnSearch( q, in, di, knn, SearchParams() );
00434 indices.push_back(in);
00435 dists.push_back(di);
00436 }
00437 delete index;
00438 }
00439
00441
00445 Keypoint extract_keypoints(cv::Mat & image, bool frames_only)
00446 {
00447
00448 Image sift_image = CreateImage(image.rows, image.cols);
00449
00450 for (int i = 0; i < image.rows; ++i)
00451 {
00452
00453
00454
00455 float* pDst = sift_image->pixels + i * sift_image->stride;
00456 for (int j = 0; j < image.cols; ++j)
00457 pDst[j] = image.at<uint8_t>(i, j) * (1.0f / 255.0f);
00458 }
00459 Keypoint keypoints;
00460 if (frames_only)
00461 keypoints = GetKeypointFrames(sift_image);
00462 else
00463 keypoints = GetKeypoints(sift_image);
00464 DestroyAllImages();
00465 return keypoints;
00466 }
00467
00469
00475 cv::Mat extract_roi(cv::Mat& image, Keypoint &camera_keypoints, Rect rect )
00476 {
00477 std::vector<Point2f> keypoints_rect;
00478 for (int ii = 0; camera_keypoints != NULL; ++ii, camera_keypoints = camera_keypoints->next)
00479 {
00480 if ((camera_keypoints->col > rect.x) &&
00481 (camera_keypoints->col < (rect.x + rect.width)) &&
00482 (camera_keypoints->row > rect.y) &&
00483 (camera_keypoints->row < (rect.y + rect.height)))
00484 {
00485 Point2f pt;
00486 pt.x = camera_keypoints->col;
00487 pt.y = camera_keypoints->row;
00488 keypoints_rect.push_back(pt);
00489 }
00490 }
00491
00492 Rect rect1 = boundingRect(Mat(keypoints_rect));
00493
00494 Mat image_roi = image(rect1);
00495 return image_roi;
00496 }
00497
00499
00504 cv::Mat extract_roi(std::vector<int> inliers, cv::Mat query, cv::Mat &output_image )
00505 {
00506 cv::Mat image;
00507 std::vector<Point2f> keypoints_rect;
00508 for (uint ii=0; ii < inliers.size() ; ++ii)
00509 {
00510 Point2f pt;
00511 pt.x = query.at<float>(inliers.at(ii),0);
00512 pt.y = query.at<float>(inliers.at(ii),1);
00513 keypoints_rect.push_back(pt);
00514 }
00515 ROS_INFO("GET THE KEYPOINTS %ld ", keypoints_rect.size());
00516
00517 if (keypoints_rect.size()!= 0)
00518 {
00519 Rect rect1 = boundingRect(Mat(keypoints_rect));
00520 ROS_INFO_STREAM("rect1: " << rect1.x << " " << rect1.y << " " << rect1.width << " " << rect1.height);
00521
00522 cv::Mat image_roi2 = output_image(rect1);
00523 return image_roi2;
00524 }
00525 else return image;
00526 }
00527
00529
00533 void visualize(cv::Mat camera_image_in, Keypoint &camera_keypoints)
00534 {
00535 image_.create(camera_image_in.cols, camera_image_in.rows, CV_8UC1);
00536
00537 cvtColor(camera_image_in, image_, CV_GRAY2RGB);
00538
00539 for (int ii=0; camera_keypoints != NULL; ++ii, camera_keypoints = camera_keypoints->next)
00540 {
00541 circle(image_, cvPoint((int) (camera_keypoints->col), (int) (camera_keypoints->row)), 3,
00542 cvScalar(255, 0, 0));
00543 }
00544 }
00545
00547
00552 void visualize(std::vector<int> inliers, cv::Mat query, cv::Mat &output_image )
00553 {
00554
00555 for (uint ii=0; ii < inliers.size() ; ++ii)
00556 {
00557
00558
00559 circle(output_image, cvPoint((int) (query.at<float>(inliers.at(ii),0)), (int) (query.at<float>(inliers.at(ii),1))), 3,
00560 cvScalar(255, 0, 0));
00561 }
00562 }
00563 };
00564
00566 int main(int argc, char **argv)
00567 {
00568
00569 ros::init(argc, argv, "get_mask_client");
00570 ros::NodeHandle n("~");
00571 LatestMatchingTFMessage tf(n, "/base_footprint");
00572
00573 ros::spin();
00574 }
00575