15 #include <yarp/cv/Cv.h>
16 #include <iCub/pf3dBottomup.hpp>
28 bool pf3dBottomup::updateModule()
32 CvMemStorage* storage = cvCreateMemStorage(0);
35 int num_detected_objects;
37 if(_blur>0) cvSmooth(image,image, CV_GAUSSIAN, 0, 0, _blur, 0);
38 cvCvtColor(image, hsv, CV_BGR2HSV );
40 cvInRangeS(hsv, cvScalar(0,_maskSmin,MIN(_maskVmin,_maskVmax),0),
41 cvScalar(181,256,MAX(_maskVmin,_maskVmax),0), mask);
42 cvSplit(hsv, hue, sat, val, 0 );
45 cvCalcBackProject(&hue, backproject, _object_model.hist);
46 cvAnd(backproject, mask, backproject, 0);
53 normalize_to_global_max(backproject);
56 cvConvert(backproject, infloat);
57 ss.BuildAll((
float*)infloat->imageData);
60 scale_space_segmentation(backproject, &ss, backprojectmask2);
63 cvSetImageROI(backprojectmask2, cvRect(1,1,image->width,image->height));
64 num_detected_objects = object_localization_simple(backprojectmask2, &_object_model, &_camera);
66 cvResetImageROI(backprojectmask2);
69 if(num_detected_objects>0){
70 Bottle& particleOutput=_outputParticlePort.prepare();
int count;
71 particleOutput.clear();
72 particleOutput.addInt32(_nParticles);
73 for(count=0;count<_nParticles;count++)
75 particleOutput.addFloat64((
double)cvmGet(_object_model.particles,0,count));
76 particleOutput.addFloat64((
double)cvmGet(_object_model.particles,1,count));
77 particleOutput.addFloat64((
double)cvmGet(_object_model.particles,2,count));
80 _outputParticlePort.write();
84 _yarpImage = _inputVideoPort.read();
86 cv::Mat imageMat=cv::cvarrToMat(image);
87 cv::resize(yarp::cv::toCvMat(*_yarpImage),imageMat,imageMat.size());
89 cvCvtColor(image, image, CV_RGB2BGR);
100 bool pf3dBottomup::configure(ResourceFinder &rf)
102 _doneInitializing=
false;
104 string trackedObjectColorTemplate;
109 _inputVideoPortName = rf.check(
"inputVideoPort",
110 Value(
"/pf3dBottomup/video:i"),
111 "Input video port (string)").asString();
112 _outputParticlePortName = rf.check(
"outputParticlePort",
113 Value(
"/pf3dBottomup/particles:o"),
114 "Output particle port (string)").asString();
116 _inputVideoPort.open(_inputVideoPortName);
117 _outputParticlePort.open(_outputParticlePortName);
119 _nParticles = rf.check(
"nParticles",
121 "Number of particles used in the tracker (int)").asInt32();
122 _calibrationImageWidth = rf.check(
"w",
124 "Image width (int)").asInt32();
125 _calibrationImageHeight = rf.check(
"h",
127 "Image height (int)").asInt32();
128 _camera.fx = rf.check(
"perspectiveFx",
130 "Focal distance * kx (double)").asFloat64();
131 _camera.fy = rf.check(
"perspectiveFy",
133 "Focal distance * ky (double)").asFloat64();
134 _camera.cx = rf.check(
"perspectiveCx",
136 "X position of the projection center, in pixels (double)").asFloat64();
137 _camera.cy = rf.check(
"perspectiveCy",
139 "Y position of the projection center, in pixels (double)").asFloat64();
140 _scaleSpaceLevels = rf.check(
"scaleSpaceLevels",
142 "Number of levels on the scale space (int)").asInt32();
143 _maskVmin = rf.check(
"maskVmin",
145 "Minimum acceptable image value (int)").asInt32();
146 _maskVmax = rf.check(
"maskVmax",
148 "Maximum acceptable image value (int)").asInt32();
149 _maskSmin = rf.check(
"maskSmin",
151 "Minimum acceptable image saturation (int)").asInt32();
152 _blur = rf.check(
"Blur",
154 "Blur variance applied to the input image (int)").asInt32();
155 _object_model.raio_esfera = rf.check(
"sphereRadius",
157 "Radius of the sphere in case that is our object (double)").asFloat64();
159 trackedObjectColorTemplate = rf.findFile(
"trackedObjectColorTemplate");
160 if(trackedObjectColorTemplate==
""){
161 cout<<
"Couldnt find color model specified in pf3dBottomup.ini\n";
166 calc_hist_from_model_2D(trackedObjectColorTemplate, &_object_model.hist, _maskVmin, _maskVmax);
167 _object_model.particles = cvCreateMat(3,_nParticles,CV_32FC1);
170 _camera.fov = 2*atan(_calibrationImageHeight/(2*_camera.fy))*180/PI;
171 _camera.aspect = _calibrationImageWidth/(double)_calibrationImageHeight * (_camera.fy/_camera.fx);
172 _camera.znear = 0.01;
177 _scaleSpaceScales[0]=16.0 * _calibrationImageWidth/640;
178 _scaleSpaceScales[1]= 8.0 * _calibrationImageWidth/640;
179 _scaleSpaceScales[2]= 4.0 * _calibrationImageWidth/640;
180 ss.AllocateResources(_calibrationImageHeight, _calibrationImageWidth, _scaleSpaceLevels, _scaleSpaceScales);
183 _yarpImage = _inputVideoPort.read();
184 image = cvCreateImage(cvSize(_calibrationImageWidth, _calibrationImageHeight), 8, 3);
185 cv::cvtColor(yarp::cv::toCvMat(*_yarpImage),cv::cvarrToMat(image),CV_RGB2BGR);
188 infloat = cvCreateImage( cvGetSize(image), IPL_DEPTH_32F, 1);
189 hsv = cvCreateImage( cvGetSize(image), 8, 3 );
190 hue = cvCreateImage( cvGetSize(image), 8, 1 );
191 sat = cvCreateImage( cvGetSize(image), 8, 1 );
192 val = cvCreateImage( cvGetSize(image), 8, 1 );
193 mask = cvCreateImage( cvGetSize(image), 8, 1 );
194 backproject = cvCreateImage( cvGetSize(image), 8, 1 );
195 backprojectmask2 = cvCreateImage( cvSize(image->width+2,image->height+2), 8, 1 );
198 _doneInitializing=
true;
205 bool pf3dBottomup::close()
208 _inputVideoPort.close();
209 _outputParticlePort.close();
213 cvReleaseMat(&_object_model.particles);
214 cvReleaseImage(&image);
215 cvReleaseImage(&infloat);
216 cvReleaseImage(&hsv);
217 cvReleaseImage(&hue);
218 cvReleaseImage(&sat);
219 cvReleaseImage(&val);
220 cvReleaseImage(&mask);
221 cvReleaseImage(&backproject);
222 cvReleaseImage(&backprojectmask2);
229 bool pf3dBottomup::interruptModule()
232 _inputVideoPort.interrupt();
233 _outputParticlePort.interrupt();
240 pf3dBottomup::pf3dBottomup()
246 pf3dBottomup::~pf3dBottomup()
248 cout<<
"oh my god! they killed kenny! you bastards!\n";
262 void pf3dBottomup::calc_hist_from_model_2D(
string file, CvHistogram **objhist,
int _vmin,
int _vmax)
265 float bins[35][10], *curbin;
267 float kernFactor=0.1F;
268 IplImage *histmodel = 0, *histmask = 0, *histhue = 0, *histsat = 0, *histval = 0;
271 int dims[] = {35, 10};
272 float cbRanges[] = {0, 180};
273 float crRanges[] = {0, 255};
274 float* ranges[] = {cbRanges, crRanges};
275 IplImage* imgs[] = {0, 0};
277 auto histMat = cv::imread(file);
278 histmodel = cvCreateImage(cvSize(histMat.cols,histMat.rows),histMat.depth(),histMat.channels());
280 cvInitImageHeader(&ipltemp, cvSize(histMat.cols, histMat.rows), cvIplDepth(histMat.flags), histMat.channels());
281 cvSetData(&ipltemp, histMat.data, (
int)histMat.step[0]);
282 histmodel = &ipltemp;
283 cvCvtColor(histmodel, histmodel, CV_BGR2HSV);
284 histmask = cvCreateImage(cvGetSize(histmodel), 8, 1);
285 histhue = cvCreateImage(cvGetSize(histmodel), 8, 1);
286 histsat = cvCreateImage(cvGetSize(histmodel), 8, 1);
287 histval = cvCreateImage(cvGetSize(histmodel), 8, 1);
288 cvInRangeS(histmodel, cvScalar(0,70,MIN(_vmin,_vmax),0),cvScalar(181,256,MAX(_vmin,_vmax),0), histmask);
289 cvSplit(histmodel, histhue, histsat, histval, 0);
291 imgs[0]=histhue; imgs[1]=histsat;
292 hist = cvCreateHist(2, dims, CV_HIST_ARRAY, ranges, CV_HIST_UNIFORM);
294 cvCalcHist((IplImage **)imgs, hist, 0, histmask);
297 for(i=0;i<dims[0];i++)
298 for(j=0;j<dims[1];j++)
300 for(i=0;i<dims[0];i++)
301 for(j=0;j<dims[1];j++){
302 bins[i][j]+=(float)((1+kernFactor)*cvGetReal2D(hist->bins,i,j));
304 if(i>0) bins[i-1][j]+=(float)(kernFactor*cvGetReal2D(hist->bins,i,j));
305 else bins[dims[0]-1][j]+=(float)(kernFactor*cvGetReal2D(hist->bins,i,j));
306 if(i<dims[0]-1) bins[i+1][j]+=(float)(kernFactor*cvGetReal2D(hist->bins,i,j));
307 else bins[0][j]+=(float)(kernFactor*cvGetReal2D(hist->bins,i,j));
309 if(j>0) bins[i][j-1]+=(float)(kernFactor*cvGetReal2D(hist->bins,i,j));
310 if(j<dims[1]-1) bins[i][j+1]+=(float)(kernFactor*cvGetReal2D(hist->bins,i,j));
311 if(j>1) bins[i][j-2]+=(float)(kernFactor*cvGetReal2D(hist->bins,i,j));
312 if(j<dims[1]-2) bins[i][j+2]+=(float)(kernFactor*cvGetReal2D(hist->bins,i,j));
314 for(i=0;i<dims[0];i++)
315 for(j=0;j<dims[1];j++){
316 curbin = (
float*)cvPtr2D(hist->bins, i, j);
317 (*curbin) = bins[i][j];
321 cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 );
323 cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 );
326 cvReleaseImage(&histmask);
327 cvReleaseImage(&histhue);
331 void pf3dBottomup::normalize_to_global_max(IplImage *img)
338 int px1=0,numpx1=0,px2=0,numpx2=0;
340 step = img->widthStep/
sizeof(uchar);
341 data = (uchar *)img->imageData;
344 for(i=0 ; i<img->height ; i++)
345 for(j=0 ; j<img->width ; j++)
346 if(data[i*step+j] > max){ pmax=i*step+j; max=data[pmax]; }
350 for(i=0 ; i<img->height ; i++)
351 for(j=0 ; j<img->width ; j++)
352 data[i*step+j] = ((data[i*step+j]*M)/max);
357 void pf3dBottomup::scale_space_segmentation(IplImage *img, ScaleSpace *ss, IplImage *result)
362 IplImage *outgray, *outfloat, *floodmask;
368 step = img->widthStep/
sizeof(uchar);
370 outgray = cvCreateImage(cvGetSize(img), 8, 1);
371 outfloat = cvCreateImage(cvGetSize(img), IPL_DEPTH_32F, 1);
372 floodmask = cvCreateImage(cvGetSize(result), 8, 1 );
377 for(l=0 ; l < ss->GetLevels() ; l++){
382 outfloat->imageData = (
char*)(ss->GetLevel(l));
385 cvConvert(outfloat, outgray);
386 data = (
float *)outfloat->imageData;
387 step = outfloat->widthStep/
sizeof(
float);
388 maxdata = (uchar *)outgray->imageData;
389 maxstep = outgray->widthStep/
sizeof(uchar);
392 for(i=r;i<img->height-r;i++){
393 for(j=r;j<img->width-r;j++){
395 if(data[i*step+j] < thres){ maxdata[i*maxstep+j]=0;
continue; }
398 for(si=i-r,aux=0 ; si<=i+r && !aux ; si++)
399 for(sj=j-r ; sj<=j+r ; sj++)
400 if(!(si==i && sj==j) && data[i*step+j] <= data[si*step+sj]){
401 maxdata[i*maxstep+j]=0; aux=1;
break;
407 cvFloodFill2(outfloat, cvPoint(j,i), cvScalar(255),
408 cvScalar(T), cvScalar(T), NULL,
409 4+(255<<8)+CV_FLOODFILL_MASK_ONLY+CV_FLOODFILL_FIXED_RANGE, floodmask);
413 cvOr(floodmask, result, result, 0);
417 cvReleaseImage(&floodmask);
418 cvReleaseImage(&outfloat);
419 cvReleaseImage(&outgray);
423 int pf3dBottomup::object_localization_simple(IplImage *segm, ObjectModel *model, CameraModel *camera)
425 CvMemStorage* storage = cvCreateMemStorage(0);
430 double m00,m01,m10,area;
434 fx=camera->fx; fy=camera->fy; cx=camera->cx; cy=camera->cy;
435 raio = model->raio_esfera;
438 cvFindContours( segm, storage, &contours,
sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );
442 area = fabs(cvContourArea( contours, CV_WHOLE_SEQ ));
443 if(area>300.0 * segm->width/640){
444 double uu,vv,raiopx,xx,yy,zz;
446 cvMoments(contours,&moments,0);
447 m00 = cvGetSpatialMoment( &moments, 0, 0);
448 m10 = cvGetSpatialMoment( &moments, 1, 0);
449 m01 = cvGetSpatialMoment( &moments, 0, 1);
452 center = cvPoint((
int)uu, (
int)vv);
453 raiopx = sqrt(1.0*area/PI);
454 zz = raio/( ((uu+raiopx-cx)/fx)-((uu-cx)/fx) );
458 cvmSet(model->particles,0,count, xx*1000);
459 cvmSet(model->particles,1,count, yy*1000);
460 cvmSet(model->particles,2,count, zz*1000);
464 contours = contours->h_next;
468 for(i=0 , j=count ; i<count ; i++)
469 for( ; j<count+(i+1)*(_nParticles-count)/count ; j++){
470 cvmSet(model->particles,0,j, cvmGet(model->particles,0,i)+SCATTER(30));
471 cvmSet(model->particles,1,j, cvmGet(model->particles,1,i)+SCATTER(30));
472 cvmSet(model->particles,2,j, cvmGet(model->particles,2,i)+SCATTER(50));
475 cvReleaseMemStorage( &storage );