00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <iostream>
00037 #include <ros/ros.h>
00038
00039 #include <opencv2/highgui/highgui.hpp>
00040 #include <opencv2/core/core.hpp>
00041 #include <opencv2/opencv.hpp>
00042 #include <opencv/cv.h>
00043 #include <opencv/cvaux.h>
00044 #include <opencv/cxcore.h>
00045 #include <cv_bridge/cv_bridge.h>
00046 #include <sensor_msgs/image_encodings.h>
00047
00048 #include <sensor_msgs/Image.h>
00049 #include <geometry_msgs/PoseStamped.h>
00050 #include <geometry_msgs/Pose2D.h>
00051 #include <image_transport/image_transport.h>
00052 #include "cv_detection.h"
00053
00054
00055 using namespace std;
00056 using namespace cv;
00057
00058
00059 DetectionCV::DetectionCV(ros::NodeHandle& nh_)
00060 :it_(nh_)
00061 {
00062 ros::NodeHandle private_nh_("~");
00063 private_nh_.param("initial_x", p_initial_x, 350);
00064 private_nh_.param("initial_y", p_initial_y, 200);
00065 private_nh_.param("initial_r", p_initial_r, 20);
00066
00067 object.x=p_initial_x;
00068 object.y=p_initial_y;
00069
00070 camera_sub_=it_.subscribe("/camera/image_raw", 1, &DetectionCV::object_detection, this);
00071
00072 image_object_pub_=nh_.advertise<geometry_msgs::Pose2D>("/camera/object_position", 1, true);
00073
00074 }
00075
00076 DetectionCV::~DetectionCV(void)
00077 {
00078
00079 }
00080
00081 void DetectionCV::object_detection(const sensor_msgs::ImageConstPtr& msg)
00082 {
00083 cv_bridge::CvImagePtr cv_ptr;
00084 cv::Mat prev_image;
00085
00086 try
00087 {
00088 cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
00089 }
00090 catch (cv_bridge::Exception& e)
00091 {
00092 ROS_ERROR("cv_bridge exception: %s", e.what());
00093 return;
00094 }
00095
00096 IplImage UNImg=cv_ptr->image.operator _IplImage();
00097
00098 cvShowImage("original",&UNImg);
00099 cv::waitKey(3);
00100
00101 CV_Detect(&UNImg, object);
00102
00103 geometry_msgs::Pose2D object_pose2D;
00104 object_pose2D.x=object.x;
00105 object_pose2D.y=object.y;
00106
00107 image_object_pub_.publish(object_pose2D);
00108 }
00109
00110 double DetectionCV::Sum(IplImage *srcImg,int nrow,int ncol)
00111 {
00112 double ImgSum=0;
00113 for(int i=0;i<nrow;i++)
00114 {
00115 for(int j=0;j<ncol;j++)
00116 {
00117 ImgSum+=CV_IMAGE_ELEM(srcImg,float,i,j);
00118 }
00119 }
00120
00121 return ImgSum;
00122 }
00123
00124 void DetectionCV::ShowIndex(int row,int col,IplImage *srcImg)
00125 {
00126 int nrow,ncol;
00127 CvSize ImageSize=cvGetSize(srcImg);
00128 while(1)
00129 {
00130 scanf("%d",&nrow);
00131 scanf("%d",&ncol);
00132 if(nrow==-1||ncol==-1)
00133 break;
00134 }
00135 }
00136
00137 void DetectionCV::ImageConvert(IplImage *srcImg,int nrow,int ncol)
00138 {
00139 float ImageMax=0,Gain;
00140 double Gain1=1.0;
00141 IplImage* TempImage=cvCloneImage(srcImg);
00142
00143 for(int i=0;i<nrow;i++)
00144 {
00145 for(int j=0;j<ncol;j++)
00146 {
00147 if(CV_IMAGE_ELEM(srcImg,float,i,j)>ImageMax)
00148 {
00149 ImageMax=CV_IMAGE_ELEM(srcImg,float,i,j);
00150 }
00151 }
00152 }
00153
00154
00155
00156 Gain=255/ImageMax;
00157
00158 cvSet(TempImage,cvScalar(Gain));
00159 cvMul(srcImg,TempImage,srcImg,1.0);
00160
00161 cvReleaseImage(&TempImage);
00162 }
00163
00164 void DetectionCV::sdf2circle(IplImage* Phi_0,int nrow,int ncol,int Next_X,int Next_Y,int r,CvSize ImgSize)
00165 {
00166 for(int i=0;i<nrow;i++)
00167 {
00168 for(int j=0;j<ncol;j++)
00169 {
00170 CV_IMAGE_ELEM(Phi_0,float,i,j)=sqrt((pow((double)(j-Next_X),2.0)+pow((double)(i-Next_Y),2.0)))-(double)r;
00171 }
00172 }
00173 }
00174
00175 void DetectionCV::Heaviside(IplImage* phi,double epsilon,IplImage* H)
00176 {
00177 CvSize ImageSize=cvGetSize(phi);
00178
00179 for(int i=0;i<ImageSize.height;i++)
00180 {
00181 for(int j=0;j<ImageSize.width;j++)
00182 {
00183 CV_IMAGE_ELEM(H,float,i,j)=0.5*(1+(2/3.1416)*atan(CV_IMAGE_ELEM(phi,float,i,j)/epsilon));
00184 }
00185 }
00186
00187 }
00188
00189 void DetectionCV::Delta(IplImage* phi,double epsilon,IplImage* Delta_h)
00190 {
00191 IplImage* TempImage=cvCloneImage(phi);
00192
00193 cvMul(phi,phi,Delta_h,1.0);
00194 cvAddS(Delta_h,cvScalar(epsilon*epsilon),Delta_h);
00195 cvSet(TempImage,cvScalar(epsilon/3.1416));
00196 cvDiv(TempImage,Delta_h,Delta_h,1.0);
00197
00198 cvReleaseImage(&TempImage);
00199 }
00200
00201 void DetectionCV::NeumannBoundCond(IplImage* phi)
00202 {
00203 CvSize ImgSize=cvGetSize(phi);
00204 int i;
00205 int nrow=ImgSize.height,ncol=ImgSize.width;
00206 CV_IMAGE_ELEM(phi,float,0,0) = CV_IMAGE_ELEM(phi,float,2,2);
00207 CV_IMAGE_ELEM(phi,float,0,ncol-1) = CV_IMAGE_ELEM(phi,float,2,ncol-3);
00208 CV_IMAGE_ELEM(phi,float,nrow-1,0) = CV_IMAGE_ELEM(phi,float,nrow-3,2);
00209 CV_IMAGE_ELEM(phi,float,nrow-1,ncol-1) = CV_IMAGE_ELEM(phi,float,nrow-3,ncol-3);
00210 for(i=1;i<ncol-1;i++)
00211 {
00212 CV_IMAGE_ELEM(phi,float,4330,i)=CV_IMAGE_ELEM(phi,float,2,i);
00213 }
00214 for(i=1;i<ncol-1;i++)
00215 {
00216 CV_IMAGE_ELEM(phi,float,nrow-1,i)=CV_IMAGE_ELEM(phi,float,nrow-3,i);
00217 }
00218 for(i=1;i<nrow-1;i++)
00219 {
00220 CV_IMAGE_ELEM(phi,float,i,0)=CV_IMAGE_ELEM(phi,float,i,2);
00221 }
00222 for(i=1;i<nrow-1;i++)
00223 {
00224 CV_IMAGE_ELEM(phi,float,i,ncol-1)=CV_IMAGE_ELEM(phi,float,i,ncol-3);
00225 }
00226
00227 }
00228
00229 double DetectionCV::binaryfit_C1(IplImage* Img,IplImage* H_phi,int nrow,int ncol)
00230 {
00231 IplImage* a=cvCloneImage(Img);
00232 double numer_1,denom_1,C1;
00233
00234 cvMul(H_phi,Img,a,1.0);
00235
00236 numer_1=Sum(a,nrow,ncol);
00237 denom_1=Sum(H_phi,nrow,ncol);
00238 C1=numer_1/denom_1;
00239
00240 cvReleaseImage(&a);
00241 return C1;
00242 }
00243
00244 double DetectionCV::binaryfit_C2(IplImage* Img,IplImage* H_phi,int nrow,int ncol)
00245 {
00246 IplImage* a=cvCloneImage(Img);
00247 double numer_1,denom_1,C2;
00248 cvSubRS(H_phi,cvScalar(1.0),H_phi);
00249 cvMul(H_phi,Img,a);
00250 numer_1=Sum(a,nrow,ncol);
00251 denom_1=Sum(H_phi,nrow,ncol);
00252 C2=numer_1/denom_1;
00253
00254 cvReleaseImage(&a);
00255 return C2;
00256 }
00257
00258 void DetectionCV::EVOL_CV(IplImage* I,IplImage* phi,double nu,double lambda_1,double lambda_2,double timestep,double epsilon,int numIter)
00259 {
00260 IplImage *Hphi=cvCloneImage(phi);
00261 IplImage *kappa=cvCloneImage(phi);
00262 IplImage *diracPhi=NULL,*I_C1=NULL,*I_C2=NULL,*lambda1=NULL,*lambda2=NULL,*Times=NULL;
00263 double C1,C2;
00264 CvSize ImgSize=cvGetSize(I);
00265 int nrow=ImgSize.height,ncol=ImgSize.width;
00266
00267 I_C1=cvCloneImage(I);
00268 I_C2=cvCloneImage(I);
00269 diracPhi=cvCloneImage(I);
00270 lambda1=cvCloneImage(I);
00271 lambda2=cvCloneImage(I);
00272 Times=cvCloneImage(I);
00273
00274 for(int i=0;i<numIter;i++)
00275 {
00276 NeumannBoundCond(phi);
00277
00278 Delta(phi,epsilon,diracPhi);
00279
00280 Heaviside(phi, epsilon,Hphi);
00281
00282 C1=binaryfit_C1(I,Hphi,nrow,ncol);
00283
00284 C2=binaryfit_C2(I,Hphi,nrow,ncol);
00285
00286 cvSubS(I,cvScalar(C1),I_C1);
00287 cvPow(I_C1,I_C1,2.0);
00288 cvSet(lambda1,cvScalar(lambda_1));
00289 cvMul(lambda1,I_C1,I_C1);
00290 cvSubRS(I_C1,cvScalar(nu),I_C1);
00291
00292 cvSubS(I,cvScalar(C2),I_C2);
00293 cvPow(I_C2,I_C2,2.0);
00294 cvSet(lambda2,cvScalar(lambda_2));
00295 cvMul(lambda2,I_C2,I_C2);
00296 cvAdd(I_C1,I_C2,I_C1);
00297 cvMul(diracPhi,I_C1,diracPhi);
00298 cvSet(Times,cvScalar(timestep));
00299 cvMul(Times,diracPhi,Times);
00300 cvAdd(phi,Times,phi);
00301 }
00302
00303 cvReleaseImage(&diracPhi);
00304 cvReleaseImage(&Hphi);
00305 cvReleaseImage(&kappa);
00306 cvReleaseImage(&I_C1);
00307 cvReleaseImage(&I_C2);
00308 cvReleaseImage(&lambda1);
00309 cvReleaseImage(&lambda2);
00310 cvReleaseImage(&Times);
00311
00312 }
00313
00314 void DetectionCV::ImageProcess_1(IplImage* phi,int nrow,int ncol)
00315 {
00316 for(int i=0;i<nrow;i++)
00317 {
00318 for(int j=0;j<ncol;j++)
00319 {
00320 if(CV_IMAGE_ELEM(phi,float,i,j)<0)
00321 {
00322 CV_IMAGE_ELEM(phi,float,i,j)=-CV_IMAGE_ELEM(phi,float,i,j);
00323 if(CV_IMAGE_ELEM(phi,float,i,j)>255)
00324 CV_IMAGE_ELEM(phi,float,i,j)=255;
00325 }
00326 else
00327 CV_IMAGE_ELEM(phi,float,i,j)=0;
00328 }
00329 }
00330
00331 }
00332
00333 void DetectionCV::PlanePoint(IplImage* ProcessImg_1,IplImage* SImg,int nrow,int ncol,CvPoint &PlanePoint)
00334 {
00335 int num=0,SumRow=0,SumCol=0,AveRow=0,AveCol=0;
00336 for(int i=0;i<nrow;i++)
00337 {
00338 for(int j=0;j<ncol;j++)
00339 {
00340 if(CV_IMAGE_ELEM(ProcessImg_1,float,i,j)!=0&&CV_IMAGE_ELEM(SImg,float,i,j)>200)
00341 {
00342 num++;
00343 SumRow+=i;
00344 SumCol+=j;
00345 }
00346 }
00347 }
00348 if(num!=0)
00349 {
00350 AveRow=SumRow/num;
00351 AveCol=SumCol/num;
00352 PlanePoint.x=AveCol;
00353 PlanePoint.y=AveRow;
00354
00355 }
00356 else
00357 {
00358 PlanePoint.x=0;
00359 PlanePoint.y=0;
00360 ROS_WARN("No Such Point");
00361 }
00362 }
00363
00364 void DetectionCV::CV_Detect(IplImage* UNImg,CvPoint &Plane)
00365 {
00366 IplImage *phi_0=NULL,*phi=NULL;
00367 IplImage *floatUNImg=NULL,*HSVImg=NULL,*SImg=NULL,*HImg=NULL,*VImg=NULL;
00368 CvSize ImgSize;
00369 int nrow,ncol;
00370 int Next_X=Plane.x;
00371 int Next_Y=Plane.y;
00372 int r;
00373 int i,m,n;
00374 int numIter;
00375 int HeadNum,LastHeadNum;
00376 double nu,lambda_1,lambda_2,timestep,epsilon;
00377 float index1,index2;
00378
00379 LastHeadNum=0;
00380 numIter=10;
00381 nu = 0.001*255*255;
00382 lambda_1=1;
00383 lambda_2=1;
00384 epsilon=1;
00385 timestep=0.8;
00386
00387 ImgSize=cvGetSize(UNImg);
00388 nrow=ImgSize.height;
00389 ncol=ImgSize.width;
00390
00391 floatUNImg=cvCreateImage(ImgSize,IPL_DEPTH_32F,3);
00392 HSVImg=cvCreateImage(ImgSize,IPL_DEPTH_32F,3);
00393 SImg=cvCreateImage(ImgSize,IPL_DEPTH_32F,1);
00394 phi_0 = cvCloneImage(SImg);
00395 phi = cvCloneImage(SImg);
00396
00397 cvConvertScale(UNImg,floatUNImg,1.0/255.0,0);
00398
00399 cvCvtColor(floatUNImg,HSVImg,CV_BGR2HSV);
00400
00401 cvSplit(HSVImg,HImg,SImg,VImg,NULL);
00402
00403 ImageConvert(SImg,nrow,ncol);
00404
00405 sdf2circle(phi,nrow,ncol,Next_X,Next_Y,p_initial_r,ImgSize);
00406
00407
00408 for(i=0;i<numIter;i++)
00409 {
00410 EVOL_CV(SImg,phi,nu,lambda_1, lambda_2, timestep, epsilon, 1);
00411
00412 HeadNum=0;
00413
00414 for(m=0;m<nrow;m++)
00415 {
00416 for(n=0;n<ncol;n++)
00417 {
00418 index1=CV_IMAGE_ELEM(phi,float,m,n);
00419 index2=CV_IMAGE_ELEM(SImg,float,m,n);
00420
00421 if(CV_IMAGE_ELEM(phi,float,m,n)<=0)
00422 if(CV_IMAGE_ELEM(SImg,float,m,n)>=200)
00423 HeadNum++;
00424 }
00425 }
00426 if(abs(HeadNum-LastHeadNum)<=0&&HeadNum>10)
00427 {
00428 r=HeadNum/4;
00429 if(r>20)
00430 r=20;
00431 if(r<5)
00432 r=5;
00433 break;
00434 }
00435 LastHeadNum=HeadNum;
00436
00437 }
00438
00439 cvCircle(UNImg,Plane,20,CV_RGB(255,0,0),2,8,0);
00440 ImageProcess_1(phi,nrow,ncol);
00441
00442 PlanePoint(phi,SImg,nrow,ncol,Plane);
00443
00444 cvCircle(UNImg,Plane,2,CV_RGB(0,255,0),2,8,0);
00445
00446 cvShowImage("Result",UNImg);
00447 waitKey();
00448 cvReleaseImage(&phi_0);
00449 cvReleaseImage(&phi);
00450 cvReleaseImage(&floatUNImg);
00451 cvReleaseImage(&HSVImg);
00452 cvReleaseImage(&HImg);
00453 cvReleaseImage(&SImg);
00454 cvReleaseImage(&VImg);
00455
00456 }
00457
00458