imagesift.cpp
Go to the documentation of this file.
00001 // Copyright (C) 2008 Rosen Diankov (rdiankov@cs.cmu.edu)
00002 //
00003 // This program is free software: you can redistribute it and/or modify
00004 // it under the terms of the GNU Lesser General Public License as published by
00005 // the Free Software Foundation, either version 3 of the License, or
00006 // at your option) any later version.
00007 //
00008 // This program is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 // GNU Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public License
00014 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
00015 #include <ros/node_handle.h>
00016 #include <sensor_msgs/Image.h>
00017 #include <sensor_msgs/CameraInfo.h>
00018 #include <posedetection_msgs/ImageFeature0D.h>
00019 #include <posedetection_msgs/Feature0DDetect.h>
00020 #include <image_transport/image_transport.h>
00021 
00022 #include <opencv/highgui.h>
00023 #include <opencv/cv.h>
00024 
00025 #include <boost/shared_ptr.hpp>
00026 #include <boost/thread/mutex.hpp>
00027 
00028 #include <map>
00029 #include <string>
00030 #include <cstdio>
00031 #include <vector>
00032 
00033 #include <cv_bridge/cv_bridge.h>
00034 #include <siftfast/siftfast.h>
00035 
00036 using namespace std;
00037 using namespace ros;
00038 
00039 class SiftNode
00040 {
00041     boost::mutex _mutex;
00042     ros::NodeHandle _node;
00043     image_transport::ImageTransport _it;
00044     image_transport::Subscriber _subImage;
00045     ros::ServiceServer _srvDetect;
00046     Subscriber _subInfo;
00047     Publisher _pubSift;
00048     posedetection_msgs::ImageFeature0D sift_msg;
00049     bool _bInfoInitialized;
00050 public:
00051     ros::Time lasttime;
00052 
00053     SiftNode() : _it(_node)
00054     { 
00055         _pubSift = _node.advertise<posedetection_msgs::ImageFeature0D>("ImageFeature0D",1);
00056         usleep(100000);
00057         _subImage = _it.subscribe("image",1,&SiftNode::image_cb,this);
00058         usleep(100000);
00059         _subInfo = _node.subscribe("camera_info",1,&SiftNode::info_cb,this);
00060         usleep(100000);
00061         _srvDetect = _node.advertiseService("Feature0DDetect",&SiftNode::detect_cb,this);
00062         lasttime = ros::Time::now();
00063         _bInfoInitialized = false;
00064     }
00065     virtual ~SiftNode() {
00066         _srvDetect.shutdown();
00067         _subInfo.shutdown();
00068         _subImage.shutdown();
00069         _pubSift.shutdown();
00070     }
00071 
00072     void info_cb(const sensor_msgs::CameraInfoConstPtr& msg_ptr)
00073     {
00074         boost::mutex::scoped_lock lock(_mutex);
00075         sift_msg.info = *msg_ptr;
00076         _bInfoInitialized = true;
00077     }
00078 
00079     bool detect_cb(posedetection_msgs::Feature0DDetect::Request& req, posedetection_msgs::Feature0DDetect::Response& res)
00080     {
00081         return Detect(res.features,req.image);
00082     }
00083 
00084     bool Detect(posedetection_msgs::Feature0D& features, const sensor_msgs::Image& imagemsg)
00085     {
00086         boost::mutex::scoped_lock lock(_mutex);
00087         Image imagesift = NULL;
00088         try {
00089             cv_bridge::CvImagePtr frame, framefloat;
00090             if (!(frame = cv_bridge::toCvCopy(imagemsg, "bgr8")) )
00091                 return false;
00092             //frame = _bridge.toIpl();
00093             //frame = _bridge.imgMsgToCv(msg_ptr, "bgr8");
00094 
00095             if (!(framefloat = cv_bridge::toCvCopy(imagemsg, "mono8")) )
00096                 return false;
00097             //IplImage* framefloat = _bridgefloat.toIpl();
00098             //IplImage* framefloat = _bridgefloat.imgMsgToCv(msg_ptr,"mono8");
00099             if( imagesift != NULL && (imagesift->cols!=imagemsg.width || imagesift->rows!=imagemsg.height)  ) {
00100                 ROS_INFO("clear sift resources");
00101                 DestroyAllImages();
00102                 imagesift = NULL;
00103             }
00104 
00105             if( imagesift == NULL )
00106                 imagesift = CreateImage(imagemsg.height,imagemsg.width);
00107 
00108             for(int i = 0; i < imagemsg.height; ++i) {
00109                 uint8_t* psrc = (uint8_t*)framefloat->image.data+framefloat->image.step*i;
00110                 float* pdst = imagesift->pixels+i*imagesift->stride;
00111                 for(int j = 0; j < imagemsg.width; ++j)
00112                     pdst[j] = (float)psrc[j]*(1.0f/255.0f);
00113                 //memcpy(imagesift->pixels+i*imagesift->stride,framefloat->imageData+framefloat->widthStep*i,imagemsg.width*sizeof(float));
00114             }
00115         }
00116         catch (cv_bridge::Exception error) {
00117             ROS_WARN("bad frame");
00118             return false;
00119         }
00120 
00121         // compute SIFT
00122         ros::Time siftbasetime = ros::Time::now();
00123         Keypoint keypts = GetKeypoints(imagesift);
00124         // write the keys to the output
00125         int numkeys = 0;
00126         Keypoint key = keypts;
00127         while(key) {
00128             numkeys++;
00129             key = key->next;
00130         }
00131 
00132         // publish
00133         features.header = imagemsg.header;
00134         features.positions.resize(numkeys*2);
00135         features.scales.resize(numkeys);
00136         features.orientations.resize(numkeys);
00137         features.confidences.resize(numkeys);
00138         features.descriptors.resize(numkeys*128);
00139         features.descriptor_dim = 128;
00140         features.type = "libsiftfast";
00141 
00142         int index = 0;
00143         key = keypts;
00144         while(key) {
00145 
00146             for(int j = 0; j < 128; ++j)
00147                 features.descriptors[128*index+j] = key->descrip[j];
00148 
00149             features.positions[2*index+0] = key->col;
00150             features.positions[2*index+1] = key->row;
00151             features.scales[index] = key->scale;
00152             features.orientations[index] = key->ori;
00153             features.confidences[index] = 1.0; // SIFT has no confidence?
00154 
00155             key = key->next;
00156             ++index;
00157         }
00158 
00159         FreeKeypoints(keypts);
00160         DestroyAllImages();
00161 
00162         ROS_INFO("imagesift: image: %d(size=%d), num: %d, sift time: %.3fs, total: %.3fs", imagemsg.header.seq,
00163                  imagemsg.data.size(),  numkeys,
00164                  (float)(ros::Time::now()-siftbasetime).toSec(), (float)(ros::Time::now()-lasttime).toSec());
00165         lasttime = ros::Time::now();
00166         return true;
00167     }
00168 
00169     void image_cb(const sensor_msgs::ImageConstPtr& msg_ptr)
00170     {
00171         if( _pubSift.getNumSubscribers()==0 ){ 
00172             ROS_DEBUG("number of subscribers is 0, ignoring image");
00173             return;
00174         }
00175         if( !_bInfoInitialized ) {
00176             ROS_DEBUG("camera info not initialized, ignoring image");
00177             return;
00178         }
00179 
00180         Detect(sift_msg.features,*msg_ptr);
00181         sift_msg.image = *msg_ptr; // probably copying pointers so don't use after this call
00182 
00183         {
00184             boost::mutex::scoped_lock lock(_mutex); // needed for camerainfo
00185             _pubSift.publish(sift_msg);
00186         }
00187     }
00188 };
00189 
00190 int main(int argc, char **argv)
00191 {
00192     ros::init(argc,argv,"imagesift");
00193     if( !ros::master::check() )
00194         return 1;
00195     
00196     boost::shared_ptr<SiftNode> siftnode(new SiftNode());
00197     
00198     ros::spin();
00199     siftnode.reset();
00200     return 0;
00201 }


imagesift
Author(s): Rosen Diankov (rdiankov@cs.cmu.edu), Kei Okada
autogenerated on Mon Oct 6 2014 01:16:01