00001 #include <ros/ros.h>
00002 #include <ros/node_handle.h>
00003 #include "sensor_msgs/Image.h"
00004 #include "image_transport/image_transport.h"
00005 #include "cv_bridge/CvBridge.h"
00006 #include <opencv/cv.h>
00007 #include <opencv/highgui.h>
00008 #include "cvaux.h"
00009 #include "cxmisc.h"
00010 #include "highgui.h"
00011 #include <stdio.h>
00012 #include <stdlib.h>
00013 #include <ctype.h>
00014 #include <string.h>
00015
00016 class BGFGCodeBook {
00017
00018 public:
00019 BGFGCodeBook(ros::NodeHandle &n) :
00020 nh_(n), it_(nh_)
00021 {
00022
00023 n.param("input_image_topic", input_image_topic_, std::string("/narrow_stereo/left/image_color_rect"));
00024 n.param("modMin", modMin_, 35);
00025 n.param("modMax", modMax_, 35);
00026 n.param("cbBounds_", cbBounds_, 10);
00027 n.param("nframesToLearnBG", nframesToLearnBG_, 10);
00028 n.param("nChannels", nChannels_, 3);
00029 image_sub_ = it_.subscribe(
00030 input_image_topic_, 1, &BGFGCodeBook::imageCallback, this);
00031
00032
00033 model_ = 0;
00034 ch_={true,true,true};
00035 rawImage_ = 0;
00036 yuvImage_ = 0;
00037 ImaskCodeBook_ = 0;
00038 ImaskCodeBookCC_ = 0;
00039 c_ = n_ = nframes_ = 0;
00040 model_ = cvCreateBGCodeBookModel();
00041
00042
00043 model_->modMin[0] = modMin_;
00044 model_->modMin[1] = model_->modMin[2] = modMin_;
00045 model_->modMax[0] = modMax_;
00046 model_->modMax[1] = model_->modMax[2] = modMax_;
00047 model_->cbBounds[0] = model_->cbBounds[1] = model_->cbBounds[2] = cbBounds_;
00048
00049 pause_ = false;
00050 singlestep_ = false;
00051 }
00052
00053 ~BGFGCodeBook()
00054 {
00055 cvDestroyWindow( "Raw" );
00056 cvDestroyWindow( "ForegroundCodeBook");
00057 cvDestroyWindow( "CodeBook_ConnectComp");
00058 }
00059
00060 void help(void)
00061 {
00062 printf("\nLearn background and find foreground using simple average and average difference learning method:\n"
00063 "\nUSAGE:\nbgfg_codebook_node _input_image_topic:=/image_topic\n"
00064 "***Keep the focus on the video windows, NOT the console***\n\n"
00065 "INTERACTIVE PARAMETERS:\n"
00066 "\tESC,q,Q - quit the program\n"
00067 "\th - print this help\n"
00068 "\tp - pause toggle\n"
00069 "\ts - single step\n"
00070 "\tr - run mode (single step off)\n"
00071 "=== AVG PARAMS ===\n"
00072 "\t- - bump high threshold UP by 0.25\n"
00073 "\t= - bump high threshold DOWN by 0.25\n"
00074 "\t[ - bump low threshold UP by 0.25\n"
00075 "\t] - bump low threshold DOWN by 0.25\n"
00076 "=== CODEBOOK PARAMS ===\n"
00077 "\ty,u,v- only adjust channel 0(y) or 1(u) or 2(v) respectively\n"
00078 "\ta - adjust all 3 channels at once\n"
00079 "\tb - adjust both 2 and 3 at once\n"
00080 "\ti,o - bump upper threshold up,down by 1\n"
00081 "\tk,l - bump lower threshold up,down by 1\n"
00082 "\tSPACE - reset the model\n"
00083 );
00084 }
00085
00086 void imageCallback(const sensor_msgs::ImageConstPtr& msg_ptr)
00087 {
00088
00089 IplImage *cv_image = NULL;
00090 try
00091 {
00092 cv_image = bridge_.imgMsgToCv(msg_ptr, "bgr8");
00093 }
00094 catch (sensor_msgs::CvBridgeException error)
00095 {
00096 ROS_ERROR("error");
00097 }
00098
00099 if( !pause_ )
00100 {
00101
00102 rawImage_ = cv_image;
00103 ++nframes_;
00104 if(!rawImage_)
00105 {
00106 ROS_WARN("[BGFGCodeBook:] No image received");
00107 return;
00108 }
00109 }
00110 if( singlestep_ )
00111 pause_ = true;
00112
00113
00114 if( nframes_ == 1 && rawImage_ )
00115 {
00116 ROS_DEBUG("[BGFGCodeBook:] First image received");
00117
00118 yuvImage_ = cvCloneImage(rawImage_);
00119 ImaskCodeBook_ = cvCreateImage( cvGetSize(rawImage_), IPL_DEPTH_8U, 1 );
00120 ImaskCodeBookCC_ = cvCreateImage( cvGetSize(rawImage_), IPL_DEPTH_8U, 1 );
00121 cvSet(ImaskCodeBook_,cvScalar(255));
00122
00123 cvNamedWindow( "Raw", 1 );
00124 cvNamedWindow( "ForegroundCodeBook",1);
00125 cvNamedWindow( "CodeBook_ConnectComp",1);
00126 }
00127
00128
00129 if( rawImage_ )
00130 {
00131 cvCvtColor( rawImage_, yuvImage_, CV_BGR2YCrCb );
00132
00133 if( !pause_ && nframes_-1 < nframesToLearnBG_ )
00134 {
00135 cvBGCodeBookUpdate( model_, yuvImage_ );
00136 ROS_DEBUG("[BGFGCodeBook:] Learning BG, nframes: %d", nframes_);
00137 }
00138 if( nframes_-1 == nframesToLearnBG_ )
00139 cvBGCodeBookClearStale( model_, model_->t/2 );
00140
00141
00142 if( nframes_-1 >= nframesToLearnBG_ )
00143 {
00144 ROS_DEBUG("[BGFGCodeBook:] Finding FG (modMin: %d , modMax: %d)",model_->modMin[0],model_->modMax[0]);
00145
00146 cvBGCodeBookDiff( model_, yuvImage_, ImaskCodeBook_ );
00147
00148 cvCopy(ImaskCodeBook_,ImaskCodeBookCC_);
00149 cvSegmentFGMask( ImaskCodeBookCC_ );
00150 }
00151
00152 cvShowImage( "Raw", rawImage_ );
00153 cvShowImage( "ForegroundCodeBook",ImaskCodeBook_);
00154 cvShowImage( "CodeBook_ConnectComp",ImaskCodeBookCC_);
00155 }
00156
00157 c_ = cvWaitKey(10)&0xFF;
00158 c_ = tolower(c_);
00159
00160 if(c_ == 27 || c_ == 'q')
00161 {
00162 ros::shutdown();
00163 return;
00164 }
00165
00166 switch( c_ )
00167 {
00168 case 'h':
00169 help();
00170 break;
00171 case 'p':
00172 pause_ = !pause_;
00173 break;
00174 case 's':
00175 singlestep_ = !singlestep_;
00176 pause_ = false;
00177 break;
00178 case 'r':
00179 pause_ = false;
00180 singlestep_ = false;
00181 break;
00182 case ' ':
00183 cvBGCodeBookClearStale( model_, 0 );
00184 nframes_ = 0;
00185 break;
00186
00187 case 'y': case '0':
00188 case 'u': case '1':
00189 case 'v': case '2':
00190 case 'a': case '3':
00191 case 'b':
00192 ch_[0] = c_ == 'y' || c_ == '0' || c_ == 'a' || c_ == '3';
00193 ch_[1] = c_ == 'u' || c_ == '1' || c_ == 'a' || c_ == '3' || c_ == 'b';
00194 ch_[2] = c_ == 'v' || c_ == '2' || c_ == 'a' || c_ == '3' || c_ == 'b';
00195 printf("CodeBook YUV Channels active: %d, %d, %d\n", ch_[0], ch_[1], ch_[2] );
00196 break;
00197 case 'i':
00198 case 'o':
00199 case 'k':
00200 case 'l':
00201 {
00202 uchar* ptr = c_ == 'i' || c_ == 'o' ? model_->modMax : model_->modMin;
00203 for(n_=0; n_<nChannels_; n_++)
00204 {
00205 if( ch_[n_] )
00206 {
00207 int v = ptr[n_] + (c_ == 'i' || c_ == 'l' ? 1 : -1);
00208 ptr[n_] = CV_CAST_8U(v);
00209 }
00210 printf("%d,", ptr[n_]);
00211 }
00212 printf(" CodeBook %s Side\n", c_ == 'i' || c_ == 'o' ? "High" : "Low" );
00213 }
00214 break;
00215 }
00216
00217 }
00218
00219
00220 protected:
00221
00222 ros::NodeHandle nh_;
00223 image_transport::ImageTransport it_;
00224 image_transport::Subscriber image_sub_;
00225 sensor_msgs::CvBridge bridge_;
00226 std::string input_image_topic_;
00227
00228
00229 CvBGCodeBookModel* model_;
00230 int modMin_, modMax_, cbBounds_;
00231
00232 bool ch_[3];
00233 IplImage* rawImage_, *yuvImage_;
00234 IplImage *ImaskCodeBook_, *ImaskCodeBookCC_;
00235 int c_, n_, nframes_, nChannels_;
00236 int nframesToLearnBG_;
00237 bool pause_;
00238 bool singlestep_;
00239 };
00240
00241 int main(int argc, char** argv)
00242 {
00243 ros::init(argc, argv, "bgfg_codebook");
00244 ros::NodeHandle n("~");
00245 BGFGCodeBook bg(n);
00246 ros::spin();
00247 return 0;
00248 }