21 #include <yarp/cv/Cv.h>
22 #include "DispModule.h"
71 using namespace yarp::cv;
74 void DispModule::printParameters()
76 std::cout <<
"params ("
77 << this->stereo_parameters.minDisparity <<
" "
78 << this->useBestDisp <<
" "
79 << this->stereo_parameters.numberOfDisparities <<
" "
80 << this->stereo_parameters.SADWindowSize <<
" "
81 << this->stereo_parameters.disp12MaxDiff <<
" "
82 << this->stereo_parameters.preFilterCap <<
" "
83 << this->stereo_parameters.uniquenessRatio <<
" "
84 << this->stereo_parameters.speckleWindowSize <<
" "
85 << this->stereo_parameters.speckleRange <<
" "
86 << this->stereo_parameters.sigmaColorBLF <<
" "
87 << this->stereo_parameters.sigmaSpaceBLF <<
" "
88 << this->stereo_parameters.wls_lambda <<
" "
89 << this->stereo_parameters.wls_sigma <<
" "
90 << this->stereo_parameters.stereo_matching <<
" "
91 << this->stereo_parameters.BLFfiltering <<
" "
92 << this->stereo_parameters.WLSfiltering
98 bool DispModule::configure(ResourceFinder & rf)
102 string name=rf.check(
"name",Value(
"DisparityModule")).asString();
103 string robot=rf.check(
"robot",Value(
"icub")).asString();
104 string left=rf.check(
"leftPort",Value(
"/left:i")).asString();
105 string right=rf.check(
"rightPort",Value(
"/right:i")).asString();
106 string SFMFile=rf.check(
"SFMFile",Value(
"SFM.ini")).asString();
108 string sname=
"/"+name;
114 string outDispName=rf.check(
"outDispPort",Value(
"/disp:o")).asString();
115 string outDepthName=rf.check(
"outDepthPort",Value(
"/depth:o")).asString();
117 outDepthName=sname+outDepthName;
118 outDispName=sname+outDispName;
122 this->localCalibration.setDefaultContext(
"cameraCalibration");
123 this->localCalibration.setDefaultConfigFile(SFMFile.c_str());
124 this->localCalibration.configure(0,NULL);
126 this->camCalibFile=this->localCalibration.getHomeContextPath();
127 this->camCalibFile+=
"/"+SFMFile;
131 string rpc_name=sname+
"/rpc";
135 leftImgPort.open(left);
136 rightImgPort.open(right);
137 outDepth.open(outDepthName);
138 outDisp.open(outDispName);
139 handlerPort.open(rpc_name);
147 Mat KL, KR, DistL, DistR;
149 loadIntrinsics(rf,KL,KR,DistL,DistR);
150 loadConfigurationFile(this->localCalibration,R0,T0,eyes0);
154 this->original_parameters = this->stereo_parameters;
158 eyes.resize(eyes0.length(),0.0);
160 stereo->setIntrinsics(KL,KR,DistL,DistR);
165 this->HL_root=Mat::zeros(4,4,CV_64F);
166 this->HR_root=Mat::zeros(4,4,CV_64F);
168 bool useCalibrated = rf.check(
"useCalibrated");
174 Mat KL=this->stereo->getKleft();
175 Mat KR=this->stereo->getKright();
176 Mat zeroDist=Mat::zeros(1,8,CV_64FC1);
177 this->stereo->setIntrinsics(KL,KR,zeroDist,zeroDist);
183 this->numberOfTrials=0;
186 utils=
new Utilities();
187 utils->initSIFT_GPU();
191 optionHead.put(
"device",
"remote_controlboard");
192 optionHead.put(
"remote",
"/"+robot+
"/head");
193 optionHead.put(
"local",sname+
"/headClient");
195 if (headCtrl.open(optionHead))
197 headCtrl.view(iencs);
198 iencs->getAxes(&nHeadAxes);
202 std::cout <<
"[DisparityModule] Devices not available" << std::endl;
209 optionGaze.put(
"device",
"gazecontrollerclient");
210 optionGaze.put(
"remote",
"/iKinGazeCtrl");
211 optionGaze.put(
"local",sname+
"/gazeClient");
212 if (gazeCtrl.open(optionGaze))
213 gazeCtrl.view(igaze);
216 std::cout <<
"[DisparityModule] Devices not available" << std::endl;
223 if (!R0.empty() && !T0.empty())
225 stereo->setRotation(R0,0);
226 stereo->setTranslation(T0,0);
230 std::cout <<
"[DisparityModule] No local calibration file found in " << camCalibFile
231 <<
"[DisparityModule] ... Using Kinematics and Running SFM once." << std::endl;
232 updateViaGazeCtrl(
true);
233 R0=this->stereo->getRotation();
234 T0=this->stereo->getTranslation();
237 this->runRecalibration=
false;
238 this->updateViaGazeCtrl(
false);
246 if (rf.check(
"sgbm"))
247 this->stereo_parameters.stereo_matching = SM_MATCHING_ALG::SGBM_OPENCV;
248 else if(rf.check(
"sgbm_cuda"))
249 this->stereo_parameters.stereo_matching = SM_MATCHING_ALG::SGBM_CUDA;
250 else if(rf.check(
"libelas"))
251 this->stereo_parameters.stereo_matching = SM_MATCHING_ALG::LIBELAS;
254 this->stereo_parameters.BLFfiltering = SM_BLF_FILTER::BLF_ORIGINAL;
255 else if(rf.check(
"blf_cuda"))
256 this->stereo_parameters.BLFfiltering = SM_BLF_FILTER::BLF_CUDA;
257 else if(rf.check(
"no_blf"))
258 this->stereo_parameters.BLFfiltering = SM_BLF_FILTER::BLF_DISABLED;
261 this->stereo_parameters.WLSfiltering = SM_WLS_FILTER::WLS_ENABLED;
262 else if(rf.check(
"wls_lr"))
263 this->stereo_parameters.WLSfiltering = SM_WLS_FILTER::WLS_LRCHECK;
264 else if(rf.check(
"no_wls"))
265 this->stereo_parameters.WLSfiltering = SM_WLS_FILTER::WLS_DISABLED;
272 this->debugWindow = rf.check(
"gui");
274 if(this->debugWindow)
276 this->gui.initializeGUI(this->stereo_parameters.minDisparity,
277 this->stereo_parameters.numberOfDisparities,
278 this->stereo_parameters.SADWindowSize,
279 this->stereo_parameters.disp12MaxDiff,
280 this->stereo_parameters.preFilterCap,
281 this->stereo_parameters.uniquenessRatio,
282 this->stereo_parameters.speckleWindowSize,
283 this->stereo_parameters.speckleRange,
284 this->stereo_parameters.sigmaColorBLF,
285 this->stereo_parameters.sigmaSpaceBLF,
286 this->stereo_parameters.wls_lambda,
287 this->stereo_parameters.wls_sigma,
288 this->stereo_parameters.BLFfiltering,
289 this->stereo_parameters.WLSfiltering,
290 this->stereo_parameters.stereo_matching);
296 this->matcher =
new StereoMatcherNew(rf, this->stereo);
298 this->matcher->setParameters(this->stereo_parameters.minDisparity,
299 this->stereo_parameters.numberOfDisparities,
300 this->stereo_parameters.SADWindowSize,
301 this->stereo_parameters.disp12MaxDiff,
302 this->stereo_parameters.preFilterCap,
303 this->stereo_parameters.uniquenessRatio,
304 this->stereo_parameters.speckleWindowSize,
305 this->stereo_parameters.speckleRange,
306 this->stereo_parameters.sigmaColorBLF,
307 this->stereo_parameters.sigmaSpaceBLF,
308 this->stereo_parameters.wls_lambda,
309 this->stereo_parameters.wls_sigma,
310 this->stereo_parameters.BLFfiltering,
311 this->stereo_parameters.WLSfiltering,
312 this->stereo_parameters.stereo_matching);
314 this->matcher->updateCUDAParams();
320 cv::Mat DispModule::depthFromDisparity(Mat disparity, Mat Q, Mat R)
326 depth = disparity.clone();
328 depth.convertTo(depth, CV_32FC1, 1./16.);
333 float r02 = float(R.at<
double>(0,2));
334 float r12 = float(R.at<
double>(1,2));
335 float r22 = float(R.at<
double>(2,2));
337 float q00 = float(Q.at<
double>(0,0));
338 float q03 = float(Q.at<
double>(0,3));
339 float q11 = float(Q.at<
double>(1,1));
340 float q13 = float(Q.at<
double>(1,3));
341 float q23 = float(Q.at<
double>(2,3));
342 float q32 = float(Q.at<
double>(3,2));
343 float q33 = float(Q.at<
double>(3,3));
345 const Mat& Mapper=this->stereo->getMapperL();
352 for (
int u = 0; u < depth.rows; u++)
353 for (
int v = 0; v < depth.cols; v++)
355 usign=cvRound(Mapper.ptr<
float>(u)[2*v]);
356 vsign=cvRound(Mapper.ptr<
float>(u)[2*v+1]);
358 if ((usign<0) || (usign>=depth.cols) || (vsign<0) || (vsign>=depth.rows))
359 depth.at<
float>(u,v) = 0.0;
361 depth.at<
float>(u,v) = (r02*(
float(vsign)*q00+q03)+r12*(
float(usign)*q11+q13)+r22*q23)/(depth.at<
float>(vsign,usign)*q32+q33);
369 void DispModule::initializeStereoParams()
371 this->useBestDisp=
true;
373 this->stereo_parameters.uniquenessRatio=15;
374 this->stereo_parameters.speckleWindowSize=50;
375 this->stereo_parameters.speckleRange=16;
376 this->stereo_parameters.SADWindowSize=7;
377 this->stereo_parameters.minDisparity=0;
378 this->stereo_parameters.preFilterCap=63;
379 this->stereo_parameters.disp12MaxDiff=0;
381 this->stereo_parameters.numberOfDisparities = 96;
383 this->stereo_parameters.sigmaColorBLF = 10.0;
384 this->stereo_parameters.sigmaSpaceBLF = 10.0;
386 this->stereo_parameters.wls_lambda = 4500.;
387 this->stereo_parameters.wls_sigma = 1.0;
389 this->stereo_parameters.stereo_matching = SM_MATCHING_ALG::SGBM_OPENCV;
390 this->stereo_parameters.BLFfiltering = SM_BLF_FILTER::BLF_DISABLED;
391 this->stereo_parameters.WLSfiltering = SM_WLS_FILTER::WLS_DISABLED;
393 this->original_parameters = this->stereo_parameters;
397 void DispModule::updateViaKinematics(
const yarp::sig::Vector& deyes)
399 double dpan=CTRL_DEG2RAD*deyes[1];
400 double dver=CTRL_DEG2RAD*deyes[2];
402 yarp::sig::Vector rot_l_pan(4,0.0);
404 rot_l_pan[3]=dpan+dver/2.0;
405 Matrix L1=axis2dcm(rot_l_pan);
407 yarp::sig::Vector rot_r_pan(4,0.0);
409 rot_r_pan[3]=dpan-dver/2.0;
410 Matrix R1=axis2dcm(rot_r_pan);
412 Mat RT0=buildRotTras(R0,T0);
413 Matrix H0; convert(RT0,H0);
414 Matrix H=SE3inv(R1)*H0*L1;
416 Mat R=Mat::zeros(3,3,CV_64F);
417 Mat T=Mat::zeros(3,1,CV_64F);
419 for (
int i=0; i<R.rows; i++)
420 for(
int j=0; j<R.cols; j++)
421 R.at<
double>(i,j)=H(i,j);
423 for (
int i=0; i<T.rows; i++)
424 T.at<
double>(i,0)=H(i,3);
426 this->stereo->setRotation(R,0);
427 this->stereo->setTranslation(T,0);
432 void DispModule::updateViaGazeCtrl(
const bool update)
434 Matrix L1=getCameraHGazeCtrl(LEFT);
435 Matrix R1=getCameraHGazeCtrl(RIGHT);
437 Matrix RT=SE3inv(R1)*L1;
439 Mat R=Mat::zeros(3,3,CV_64F);
440 Mat T=Mat::zeros(3,1,CV_64F);
442 for (
int i=0; i<R.rows; i++)
443 for(
int j=0; j<R.cols; j++)
444 R.at<
double>(i,j)=RT(i,j);
446 for (
int i=0; i<T.rows; i++)
447 T.at<
double>(i,0)=RT(i,3);
451 stereo->setRotation(R,0);
452 stereo->setTranslation(T,0);
455 stereo->setExpectedPosition(R,T);
460 bool DispModule::interruptModule()
462 leftImgPort.interrupt();
463 rightImgPort.interrupt();
465 outDepth.interrupt();
466 handlerPort.interrupt();
473 bool DispModule::close()
476 rightImgPort.close();
495 void DispModule::recalibrate()
499 utils->extractMatch_GPU(leftMat,rightMat);
500 vector<Point2f> leftM,rightM;
501 utils->getMatches(leftM,rightM);
503 this->stereo->setMatches(leftM,rightM);
507 stereo->findMatch(
false);
510 stereo->estimateEssential();
511 bool ok=stereo->essentialDecomposition();
521 this->calibUpdated=
true;
522 this->runRecalibration=
false;
523 calibEndEvent.signal();
525 R0=stereo->getRotation();
526 T0=stereo->getTranslation();
529 std::cout <<
"[DisparityModule] Calibration Successful!" << std::endl;
534 if (++numberOfTrials>5)
536 this->calibUpdated=
false;
537 this->runRecalibration=
false;
538 calibEndEvent.signal();
540 std::cout <<
"[DisparityModule] Calibration failed after 5 trials.." << std::endl <<
541 "[DisparityModule] ..please show a non planar scene." << std::endl;
549 void DispModule::handleGuiUpdate()
557 if(this->gui.toRecalibrate())
559 std::cout <<
"[DisparityModule] Updating calibration.." << std::endl;
561 mutexRecalibration.lock();
563 this->runRecalibration=
true;
564 mutexRecalibration.unlock();
567 else if(this->gui.toSaveCalibration())
569 std::cout <<
"[DisparityModule] Saving current calibration.." << std::endl;
570 updateConfigurationFile(R0,T0,eyes0,
"STEREO_DISPARITY");
572 else if(this->gui.toLoadParameters())
574 std::cout <<
"[DisparityModule] Loading stereo parameters from file.." << std::endl;
576 this->stereo_parameters = this->original_parameters;
578 this->gui.setParameters(this->stereo_parameters.minDisparity,
579 this->stereo_parameters.numberOfDisparities,
580 this->stereo_parameters.SADWindowSize,
581 this->stereo_parameters.disp12MaxDiff,
582 this->stereo_parameters.preFilterCap,
583 this->stereo_parameters.uniquenessRatio,
584 this->stereo_parameters.speckleWindowSize,
585 this->stereo_parameters.speckleRange,
586 this->stereo_parameters.sigmaColorBLF,
587 this->stereo_parameters.sigmaSpaceBLF,
588 this->stereo_parameters.wls_lambda,
589 this->stereo_parameters.wls_sigma,
590 this->stereo_parameters.BLFfiltering,
591 this->stereo_parameters.WLSfiltering,
592 this->stereo_parameters.stereo_matching);
594 this->matcher->setParameters(this->stereo_parameters.minDisparity,
595 this->stereo_parameters.numberOfDisparities,
596 this->stereo_parameters.SADWindowSize,
597 this->stereo_parameters.disp12MaxDiff,
598 this->stereo_parameters.preFilterCap,
599 this->stereo_parameters.uniquenessRatio,
600 this->stereo_parameters.speckleWindowSize,
601 this->stereo_parameters.speckleRange,
602 this->stereo_parameters.sigmaColorBLF,
603 this->stereo_parameters.sigmaSpaceBLF,
604 this->stereo_parameters.wls_lambda,
605 this->stereo_parameters.wls_sigma,
606 this->stereo_parameters.BLFfiltering,
607 this->stereo_parameters.WLSfiltering,
608 this->stereo_parameters.stereo_matching);
610 this->matcher->updateCUDAParams();
612 else if(this->gui.toSaveParameters())
614 std::cout <<
"[DisparityModule] Saving stereo parameters.." << std::endl;
615 updateConfigurationFile(R0,T0,eyes0,
"STEREO_DISPARITY");
620 this->gui.getParameters(this->stereo_parameters.minDisparity,
621 this->stereo_parameters.numberOfDisparities,
622 this->stereo_parameters.SADWindowSize,
623 this->stereo_parameters.disp12MaxDiff,
624 this->stereo_parameters.preFilterCap,
625 this->stereo_parameters.uniquenessRatio,
626 this->stereo_parameters.speckleWindowSize,
627 this->stereo_parameters.speckleRange,
628 this->stereo_parameters.sigmaColorBLF,
629 this->stereo_parameters.sigmaSpaceBLF,
630 this->stereo_parameters.wls_lambda,
631 this->stereo_parameters.wls_sigma,
632 this->stereo_parameters.BLFfiltering,
633 this->stereo_parameters.WLSfiltering,
634 this->stereo_parameters.stereo_matching);
636 this->matcher->setParameters(this->stereo_parameters.minDisparity,
637 this->stereo_parameters.numberOfDisparities,
638 this->stereo_parameters.SADWindowSize,
639 this->stereo_parameters.disp12MaxDiff,
640 this->stereo_parameters.preFilterCap,
641 this->stereo_parameters.uniquenessRatio,
642 this->stereo_parameters.speckleWindowSize,
643 this->stereo_parameters.speckleRange,
644 this->stereo_parameters.sigmaColorBLF,
645 this->stereo_parameters.sigmaSpaceBLF,
646 this->stereo_parameters.wls_lambda,
647 this->stereo_parameters.wls_sigma,
648 this->stereo_parameters.BLFfiltering,
649 this->stereo_parameters.WLSfiltering,
650 this->stereo_parameters.stereo_matching);
652 this->matcher->updateCUDAParams();
656 this->gui.resetState();
661 bool DispModule::updateModule()
665 ImageOf<PixelRgb> *yarp_imgL=leftImgPort.read(
true);
666 ImageOf<PixelRgb> *yarp_imgR=rightImgPort.read(
true);
668 Stamp stamp_left, stamp_right;
669 leftImgPort.getEnvelope(stamp_left);
670 rightImgPort.getEnvelope(stamp_right);
672 if ((yarp_imgL==NULL) || (yarp_imgR==NULL))
677 iencs->getEncoder(nHeadAxes-3,&eyes[0]);
678 iencs->getEncoder(nHeadAxes-2,&eyes[1]);
679 iencs->getEncoder(nHeadAxes-1,&eyes[2]);
684 updateViaKinematics(eyes-eyes0);
685 updateViaGazeCtrl(
false);
687 leftMat=toCvMat(*yarp_imgL);
688 rightMat=toCvMat(*yarp_imgR);
692 getCameraHGazeCtrl(LEFT);
693 getCameraHGazeCtrl(RIGHT);
697 this->stereo->setImages(leftMat,rightMat);
700 if(this->debugWindow && this->gui.isUpdated())
701 this->handleGuiUpdate();
704 mutexRecalibration.lock();
706 if(this->runRecalibration)
709 mutexRecalibration.unlock();
722 matcher->filterBLF(
"base");
726 matcher->filterWLS(
"blf");
731 if (outDisp.getOutputCount() > 0)
740 cv::Mat disp_vis = matcher->getDisparity(
"wls");
742 if(!disp_vis.empty())
748 orig = disp_vis.clone();
751 disp_vis = refineDisparity(old_d, disp_vis, gui.getRefineTh());
753 old_d = orig.clone();
757 ImageOf<PixelMono> &outim = outDisp.prepare();
759 outim = fromCvMat<PixelMono>(disp_vis);
768 if (outDepth.getOutputCount() > 0)
770 cv::Mat disp_depth = matcher->getDisparity16(
"wls");
772 if (disp_depth.empty())
774 std::cout <<
"[DisparityModule] Impossible to compute the depth map.." << std::endl <<
775 "[DisparityModule] ..the disparity map is not available!" << std::endl;
783 orig = disp_depth.clone();
786 disp_depth = refineDisparity(old_de, disp_depth, gui.getRefineTh());
788 old_de = orig.clone();
792 outputDepth = this->depthFromDisparity(disp_depth, this->stereo->getQ(), this->stereo->getRLrect());
794 ImageOf<PixelFloat> &outim = outDepth.prepare();
796 outim = fromCvMat<PixelFloat>(outputDepth);
806 if(this->debugWindow && !this->gui.isDone())
807 this->gui.updateGUI();
809 if(this->gui.isDone())
817 double DispModule::getPeriod()
825 bool DispModule::loadExtrinsics(yarp::os::ResourceFinder& rf, Mat& Ro, Mat& To, yarp::sig::Vector& eyes)
827 Bottle extrinsics=rf.findGroup(
"STEREO_DISPARITY");
830 if (Bottle *bEyes=extrinsics.find(
"eyes").asList())
832 size_t sz=std::min(eyes.length(),(
size_t)bEyes->size());
833 for (
size_t i=0; i<sz; i++)
834 eyes[i]=bEyes->get(i).asFloat64();
837 std::cout <<
"[DisparityModule] Read Eyes Configuration = ("<<eyes.toString(3,3)<<
")" << std::endl;
839 if (Bottle *pXo=extrinsics.find(
"HN").asList())
841 Ro=Mat::zeros(3,3,CV_64FC1);
842 To=Mat::zeros(3,1,CV_64FC1);
843 for (
int i=0; i<(pXo->size()-4); i+=4)
845 Ro.at<
double>(i/4,0)=pXo->get(i).asFloat64();
846 Ro.at<
double>(i/4,1)=pXo->get(i+1).asFloat64();
847 Ro.at<
double>(i/4,2)=pXo->get(i+2).asFloat64();
848 To.at<
double>(i/4,0)=pXo->get(i+3).asFloat64();
858 bool DispModule::loadConfigurationFile(yarp::os::ResourceFinder& rf, Mat& Ro, Mat& To, yarp::sig::Vector& eyes)
861 Bottle extrinsics=rf.findGroup(
"STEREO_DISPARITY");
866 if (Bottle *bEyes=extrinsics.find(
"eyes").asList())
868 size_t sz = std::min(eyes.length(),(
size_t)bEyes->size());
869 for (
size_t i=0; i<sz; i++)
870 eyes[i] = bEyes->get(i).asFloat64();
873 std::cout <<
"[DisparityModule] Read Eyes Configuration = ("
874 << eyes.toString(3,3) <<
")" << std::endl;
879 if (Bottle *pXo=extrinsics.find(
"HN").asList())
881 Ro=Mat::zeros(3,3,CV_64FC1);
882 To=Mat::zeros(3,1,CV_64FC1);
883 for (
int i=0; i<(pXo->size()-4); i+=4)
885 Ro.at<
double>(i/4,0) = pXo->get(i).asFloat64();
886 Ro.at<
double>(i/4,1) = pXo->get(i+1).asFloat64();
887 Ro.at<
double>(i/4,2) = pXo->get(i+2).asFloat64();
888 To.at<
double>(i/4,0) = pXo->get(i+3).asFloat64();
896 if (Bottle *pXo=extrinsics.find(
"params").asList())
899 this->stereo_parameters.minDisparity = pXo->get(0).asInt32();
900 this->useBestDisp = pXo->get(1).asBool();
901 this->stereo_parameters.numberOfDisparities = pXo->get(2).asInt32();
902 this->stereo_parameters.SADWindowSize = pXo->get(3).asInt32();
903 this->stereo_parameters.disp12MaxDiff = pXo->get(4).asInt32();
904 this->stereo_parameters.preFilterCap = pXo->get(5).asInt32();
905 this->stereo_parameters.uniquenessRatio = pXo->get(6).asInt32();
906 this->stereo_parameters.speckleWindowSize = pXo->get(7).asInt32();
907 this->stereo_parameters.speckleRange = pXo->get(8).asInt32();
909 this->stereo_parameters.sigmaColorBLF = pXo->get(9).asFloat64();
910 this->stereo_parameters.sigmaSpaceBLF = pXo->get(10).asFloat64();
912 this->stereo_parameters.wls_lambda = pXo->get(11).asFloat64();
913 this->stereo_parameters.wls_sigma = pXo->get(12).asFloat64();
915 this->stereo_parameters.stereo_matching =
static_cast<SM_MATCHING_ALG
>(pXo->get(13).asInt32());
916 this->stereo_parameters.BLFfiltering =
static_cast<SM_BLF_FILTER
>(pXo->get(14).asInt32());
917 this->stereo_parameters.WLSfiltering =
static_cast<SM_WLS_FILTER
>(pXo->get(15).asInt32());
921 this->initializeStereoParams();
927 bool DispModule::loadIntrinsics(yarp::os::ResourceFinder &rf, Mat &KL, Mat &KR, Mat &DistL,
930 Bottle left=rf.findGroup(
"CAMERA_CALIBRATION_LEFT");
931 if(!left.check(
"fx") || !left.check(
"fy") || !left.check(
"cx") || !left.check(
"cy"))
934 double fx=left.find(
"fx").asFloat64();
935 double fy=left.find(
"fy").asFloat64();
937 double cx=left.find(
"cx").asFloat64();
938 double cy=left.find(
"cy").asFloat64();
940 double k1=left.check(
"k1",Value(0)).asFloat64();
941 double k2=left.check(
"k2",Value(0)).asFloat64();
943 double p1=left.check(
"p1",Value(0)).asFloat64();
944 double p2=left.check(
"p2",Value(0)).asFloat64();
946 DistL=Mat::zeros(1,8,CV_64FC1);
947 DistL.at<
double>(0,0)=k1;
948 DistL.at<
double>(0,1)=k2;
949 DistL.at<
double>(0,2)=p1;
950 DistL.at<
double>(0,3)=p2;
952 KL=Mat::eye(3,3,CV_64FC1);
953 KL.at<
double>(0,0)=fx;
954 KL.at<
double>(0,2)=cx;
955 KL.at<
double>(1,1)=fy;
956 KL.at<
double>(1,2)=cy;
958 Bottle right=rf.findGroup(
"CAMERA_CALIBRATION_RIGHT");
959 if(!right.check(
"fx") || !right.check(
"fy") || !right.check(
"cx") || !right.check(
"cy"))
962 fx=right.find(
"fx").asFloat64();
963 fy=right.find(
"fy").asFloat64();
965 cx=right.find(
"cx").asFloat64();
966 cy=right.find(
"cy").asFloat64();
968 k1=right.check(
"k1",Value(0)).asFloat64();
969 k2=right.check(
"k2",Value(0)).asFloat64();
971 p1=right.check(
"p1",Value(0)).asFloat64();
972 p2=right.check(
"p2",Value(0)).asFloat64();
974 DistR=Mat::zeros(1,8,CV_64FC1);
975 DistR.at<
double>(0,0)=k1;
976 DistR.at<
double>(0,1)=k2;
977 DistR.at<
double>(0,2)=p1;
978 DistR.at<
double>(0,3)=p2;
980 KR=Mat::eye(3,3,CV_64FC1);
981 KR.at<
double>(0,0)=fx;
982 KR.at<
double>(0,2)=cx;
983 KR.at<
double>(1,1)=fy;
984 KR.at<
double>(1,2)=cy;
991 bool DispModule::updateExtrinsics(Mat& Rot, Mat& Tr, yarp::sig::Vector& eyes,
992 const string& groupname)
995 out.open(camCalibFile.c_str());
999 out <<
"["+groupname+
"]" << endl;
1000 out <<
"eyes (" << eyes.toString() <<
")" << endl;
1002 << Rot.at<
double>(0,0) <<
" "
1003 << Rot.at<
double>(0,1) <<
" "
1004 << Rot.at<
double>(0,2) <<
" "
1005 << Tr.at<
double>(0,0) <<
" "
1006 << Rot.at<
double>(1,0) <<
" "
1007 << Rot.at<
double>(1,1) <<
" "
1008 << Rot.at<
double>(1,2) <<
" "
1009 << Tr.at<
double>(1,0) <<
" "
1010 << Rot.at<
double>(2,0) <<
" "
1011 << Rot.at<
double>(2,1) <<
" "
1012 << Rot.at<
double>(2,2) <<
" "
1013 << Tr.at<
double>(2,0) <<
" "
1014 << 0.0 <<
" " << 0.0 <<
" " << 0.0 <<
" " << 1.0 <<
")"
1025 bool DispModule::updateConfigurationFile(Mat& Rot, Mat& Tr, yarp::sig::Vector& eyes,
1026 const string& groupname)
1029 out.open(camCalibFile.c_str());
1033 out <<
"["+groupname+
"]" << endl;
1034 out <<
"eyes (" << eyes.toString() <<
")" << endl;
1036 << Rot.at<
double>(0,0) <<
" "
1037 << Rot.at<
double>(0,1) <<
" "
1038 << Rot.at<
double>(0,2) <<
" "
1039 << Tr.at<
double>(0,0) <<
" "
1040 << Rot.at<
double>(1,0) <<
" "
1041 << Rot.at<
double>(1,1) <<
" "
1042 << Rot.at<
double>(1,2) <<
" "
1043 << Tr.at<
double>(1,0) <<
" "
1044 << Rot.at<
double>(2,0) <<
" "
1045 << Rot.at<
double>(2,1) <<
" "
1046 << Rot.at<
double>(2,2) <<
" "
1047 << Tr.at<
double>(2,0) <<
" "
1048 << 0.0 <<
" " << 0.0 <<
" " << 0.0 <<
" " << 1.0 <<
")"
1055 << this->stereo_parameters.minDisparity <<
" "
1056 << this->useBestDisp <<
" "
1057 << this->stereo_parameters.numberOfDisparities <<
" "
1058 << this->stereo_parameters.SADWindowSize <<
" "
1059 << this->stereo_parameters.disp12MaxDiff <<
" "
1060 << this->stereo_parameters.preFilterCap <<
" "
1061 << this->stereo_parameters.uniquenessRatio <<
" "
1062 << this->stereo_parameters.speckleWindowSize <<
" "
1063 << this->stereo_parameters.speckleRange <<
" "
1064 << this->stereo_parameters.sigmaColorBLF <<
" "
1065 << this->stereo_parameters.sigmaSpaceBLF <<
" "
1066 << this->stereo_parameters.wls_lambda <<
" "
1067 << this->stereo_parameters.wls_sigma <<
" "
1068 << this->stereo_parameters.stereo_matching <<
" "
1069 << this->stereo_parameters.BLFfiltering <<
" "
1070 << this->stereo_parameters.WLSfiltering <<
")"
1081 void DispModule::setDispParameters(
bool _useBestDisp,
int _uniquenessRatio,
1082 int _speckleWindowSize,
int _speckleRange,
1083 int _numberOfDisparities,
int _SADWindowSize,
1084 int _minDisparity,
int _preFilterCap,
int _disp12MaxDiff)
1086 this->mutexDisp.lock();
1088 this->useBestDisp=_useBestDisp;
1089 this->stereo_parameters.uniquenessRatio=_uniquenessRatio;
1090 this->stereo_parameters.speckleWindowSize=_speckleWindowSize;
1091 this->stereo_parameters.speckleRange=_speckleRange;
1092 this->stereo_parameters.numberOfDisparities=_numberOfDisparities;
1093 this->stereo_parameters.SADWindowSize=_SADWindowSize;
1094 this->stereo_parameters.minDisparity=_minDisparity;
1095 this->stereo_parameters.preFilterCap=_preFilterCap;
1096 this->stereo_parameters.disp12MaxDiff=_disp12MaxDiff;
1098 this->mutexDisp.unlock();
1103 Point3f DispModule::get3DPoints(
int u,
int v,
const string &drive)
1105 Point3f point(0.0f,0.0f,0.0f);
1106 if ((drive!=
"RIGHT") && (drive!=
"LEFT") && (drive!=
"ROOT"))
1109 std::lock_guard<std::mutex> lg(mutexDisp);
1112 const Mat& Mapper=this->stereo->getMapperL();
1116 float usign=Mapper.ptr<
float>(v)[2*u];
1117 float vsign=Mapper.ptr<
float>(v)[2*u+1];
1122 const Mat& disp16m=this->matcher->getDisparity16(
"wls");
1123 if (disp16m.empty() || (u<0) || (u>=disp16m.cols) || (v<0) || (v>=disp16m.rows))
1126 const Mat& Q=this->stereo->getQ();
1127 IplImage disp16=disp16m;
1128 CvScalar scal=cvGet2D(&disp16,v,u);
1129 double disparity=scal.val[0]/16.0;
1130 float w=(float)(disparity*Q.at<
double>(3,2)+Q.at<
double>(3,3));
1131 point.x=(float)((usign+1)*Q.at<
double>(0,0)+Q.at<
double>(0,3));
1132 point.y=(float)((vsign+1)*Q.at<
double>(1,1)+Q.at<
double>(1,3));
1133 point.z=(float)Q.at<
double>(2,3);
1143 if ((point.z>10.0f) || (point.z<0.0f))
1148 const Mat& RLrect=this->stereo->getRLrect().t();
1149 Mat Tfake=Mat::zeros(0,3,CV_64F);
1150 Mat P(4,1,CV_64FC1);
1151 P.at<
double>(0,0)=point.x;
1152 P.at<
double>(1,0)=point.y;
1153 P.at<
double>(2,0)=point.z;
1154 P.at<
double>(3,0)=1.0;
1156 Mat Hrect=buildRotTras(RLrect,Tfake);
1158 point.x=(float)(P.at<
double>(0,0)/P.at<
double>(3,0));
1159 point.y=(float)(P.at<
double>(1,0)/P.at<
double>(3,0));
1160 point.z=(float)(P.at<
double>(2,0)/P.at<
double>(3,0));
1162 else if (drive==
"LEFT")
1164 Mat P(3,1,CV_64FC1);
1165 P.at<
double>(0,0)=point.x;
1166 P.at<
double>(1,0)=point.y;
1167 P.at<
double>(2,0)=point.z;
1169 P=this->stereo->getRLrect().t()*P;
1170 point.x=(float)P.at<
double>(0,0);
1171 point.y=(float)P.at<
double>(1,0);
1172 point.z=(float)P.at<
double>(2,0);
1174 else if (drive==
"RIGHT")
1176 const Mat& Rright=this->stereo->getRotation();
1177 const Mat& Tright=this->stereo->getTranslation();
1178 const Mat& RRright=this->stereo->getRRrect().t();
1179 Mat TRright=Mat::zeros(0,3,CV_64F);
1181 Mat HRL=buildRotTras(Rright,Tright);
1182 Mat Hrect=buildRotTras(RRright,TRright);
1184 Mat P(4,1,CV_64FC1);
1185 P.at<
double>(0,0)=point.x;
1186 P.at<
double>(1,0)=point.y;
1187 P.at<
double>(2,0)=point.z;
1188 P.at<
double>(3,0)=1.0;
1191 point.x=(float)(P.at<
double>(0,0)/P.at<
double>(3,0));
1192 point.y=(float)(P.at<
double>(1,0)/P.at<
double>(3,0));
1193 point.z=(float)(P.at<
double>(2,0)/P.at<
double>(3,0));
1200 Mat DispModule::buildRotTras(
const Mat& R,
const Mat& T)
1202 Mat A=Mat::eye(4,4,CV_64F);
1203 for (
int i=0; i<R.rows; i++)
1205 double* Mi=A.ptr<
double>(i);
1206 const double* MRi=R.ptr<
double>(i);
1207 for (
int j=0; j<R.cols; j++)
1211 for (
int i=0; i<T.rows; i++)
1213 double* Mi=A.ptr<
double>(i);
1214 const double* MRi=T.ptr<
double>(i);
1223 Matrix DispModule::getCameraHGazeCtrl(
int camera)
1225 yarp::sig::Vector x_curr;
1226 yarp::sig::Vector o_curr;
1229 check=igaze->getLeftEyePose(x_curr, o_curr);
1231 check=igaze->getRightEyePose(x_curr, o_curr);
1235 Matrix H_curr(4, 4);
1239 Matrix R_curr=axis2dcm(o_curr);
1240 Matrix H_curr=R_curr;
1241 H_curr.setSubcol(x_curr,0,3);
1246 convert(H_curr,HL_root);
1249 else if(camera==RIGHT)
1252 convert(H_curr,HR_root);
1261 void DispModule::convert(Matrix& matrix, Mat& mat)
1263 mat=cv::Mat(matrix.rows(),matrix.cols(),CV_64FC1);
1264 for(
int i=0; i<matrix.rows(); i++)
1265 for(
int j=0; j<matrix.cols(); j++)
1266 mat.at<
double>(i,j)=matrix(i,j);
1271 void DispModule::convert(Mat& mat, Matrix& matrix)
1273 matrix.resize(mat.rows,mat.cols);
1274 for(
int i=0; i<mat.rows; i++)
1275 for(
int j=0; j<mat.cols; j++)
1276 matrix(i,j)=mat.at<
double>(i,j);
1281 bool DispModule::respond(
const Bottle& command, Bottle& reply)
1283 if(command.size()==0)
1286 if (command.get(0).asString()==
"quit") {
1287 std::cout <<
"[DisparityModule] Closing..." << std::endl;
1291 if (command.get(0).asString()==
"help") {
1292 reply.addVocab32(
"many");
1293 reply.addString(
"Available commands are:");
1294 reply.addString(
"- [calibrate]: It recomputes the camera positions once.");
1295 reply.addString(
"- [save]: It saves the current camera positions and uses it when the module starts.");
1296 reply.addString(
"- [getH]: It returns the calibrated stereo matrix.");
1297 reply.addString(
"- [setNumDisp NumOfDisparities]: It sets the expected number of disparity (in pixel). Values must be divisible by 32. ");
1298 reply.addString(
"- [Point x y]: Given the pixel coordinate x,y in the Left image the response is the 3D Point: X Y Z computed using the depth map wrt the LEFT eye.");
1299 reply.addString(
"- [x y]: Given the pixel coordinate x,y in the Left image the response is the 3D Point: X Y Z ur vr computed using the depth map wrt the the ROOT reference system.(ur vr) is the corresponding pixel in the Right image. ");
1300 reply.addString(
"- [Left x y]: Given the pixel coordinate x,y in the Left image the response is the 3D Point: X Y Z computed using the depth map wrt the LEFT eye. Points with non valid disparity (i.e. occlusions) are handled with the value (0.0,0.0,0.0). ");
1301 reply.addString(
"- [Right x y]: Given the pixel coordinate x,y in the Left image the response is the 3D Point: X Y Z computed using the depth map wrt the RIGHT eye. Points with non valid disparity (i.e. occlusions) are handled with the value (0.0,0.0,0.0).");
1302 reply.addString(
"- [Root x y]: Given the pixel coordinate x,y in the Left image the response is the 3D Point: X Y Z computed using the depth map wrt the ROOT reference system. Points with non valid disparity (i.e. occlusions) are handled with the value (0.0,0.0,0.0).");
1303 reply.addString(
"- [Rect tlx tly w h step]: Given the pixels in the rectangle defined by {(tlx,tly) (tlx+w,tly+h)} (parsed by columns), the response contains the corresponding 3D points in the ROOT frame. The optional parameter step defines the sampling quantum; by default step=1.");
1304 reply.addString(
"- [Points u_1 v_1 ... u_n v_n]: Given a list of n pixels, the response contains the corresponding 3D points in the ROOT frame.");
1305 reply.addString(
"- [Flood3D x y dist]: Perform 3D flood-fill on the seed point (x,y), returning the following info: [u_1 v_1 x_1 y_1 z_1 ...]. The optional parameter dist expressed in meters regulates the fill (by default = 0.004).");
1306 reply.addString(
"- [uL_1 vL_1 uR_1 vR_1 ... uL_n vL_n uR_n vR_n]: Given n quadruples uL_i vL_i uR_i vR_i, where uL_i vL_i are the pixel coordinates in the Left image and uR_i vR_i are the coordinates of the matched pixel in the Right image, the response is a set of 3D points (X1 Y1 Z1 ... Xn Yn Zn) wrt the ROOT reference system.");
1307 reply.addString(
"- [cart2stereo X Y Z]: Given a world point X Y Z wrt to ROOT reference frame the response is the projection (uL vL uR vR) in the Left and Right images.");
1308 reply.addString(
"- [doBLF flag]: activate Bilateral filter for flag = true, and skip it for flag = false.");
1309 reply.addString(
"- [bilatfilt sigmaColor sigmaSpace]: Set the parameters for the bilateral filer (default sigmaColor = 10.0, sigmaSpace = 10.0).");
1310 reply.addString(
"- [algorithm name]: Set the stereo matching algorithm used (default = SGMB(cpu)).");
1311 reply.addString(
"For more details on the commands, check the module's documentation");
1315 if (command.get(0).asString()==
"calibrate")
1317 mutexRecalibration.lock();
1319 this->runRecalibration=
true;
1320 mutexRecalibration.unlock();
1322 calibEndEvent.reset();
1323 calibEndEvent.wait();
1325 if (this->calibUpdated)
1327 R0=this->stereo->getRotation();
1328 T0=this->stereo->getTranslation();
1331 reply.addString(
"ACK");
1334 reply.addString(
"[DisparityModule] Calibration failed after 5 trials.. Please show a non planar scene.");
1339 if (command.get(0).asString()==
"save")
1341 updateExtrinsics(R0,T0,eyes0,
"STEREO_DISPARITY");
1342 reply.addString(
"ACK");
1346 if (command.get(0).asString()==
"getH")
1348 Mat RT0=buildRotTras(R0,T0);
1349 Matrix H0; convert(RT0,H0);
1355 if (command.get(0).asString()==
"setNumDisp")
1357 int dispNum=command.get(1).asInt32();
1360 this->stereo_parameters.numberOfDisparities=dispNum;
1361 this->setDispParameters(useBestDisp,
1362 this->stereo_parameters.uniquenessRatio,
1363 this->stereo_parameters.speckleWindowSize,
1364 this->stereo_parameters.speckleRange,
1365 this->stereo_parameters.numberOfDisparities,
1366 this->stereo_parameters.SADWindowSize,
1367 this->stereo_parameters.minDisparity,
1368 this->stereo_parameters.preFilterCap,
1369 this->stereo_parameters.disp12MaxDiff);
1370 reply.addString(
"ACK");
1375 reply.addString(
"Num Disparity must be divisible by 32");
1380 if (command.get(0).asString()==
"setMinDisp")
1382 int dispNum=command.get(1).asInt32();
1383 this->stereo_parameters.minDisparity=dispNum;
1384 this->setDispParameters(useBestDisp,
1385 this->stereo_parameters.uniquenessRatio,
1386 this->stereo_parameters.speckleWindowSize,
1387 this->stereo_parameters.speckleRange,
1388 this->stereo_parameters.numberOfDisparities,
1389 this->stereo_parameters.SADWindowSize,
1390 this->stereo_parameters.minDisparity,
1391 this->stereo_parameters.preFilterCap,
1392 this->stereo_parameters.disp12MaxDiff);
1393 reply.addString(
"ACK");
1397 if (command.get(0).asString()==
"set" && command.size()==10)
1399 bool useBestDisp=command.get(1).asInt32() ? true :
false;
1400 int uniquenessRatio=command.get(2).asInt32();
1401 int speckleWindowSize=command.get(3).asInt32();
1402 int speckleRange=command.get(4).asInt32();
1403 int numberOfDisparities=command.get(5).asInt32();
1404 int SADWindowSize=command.get(6).asInt32();
1405 int minDisparity=command.get(7).asInt32();
1406 int preFilterCap=command.get(8).asInt32();
1407 int disp12MaxDiff=command.get(9).asInt32();
1409 this->setDispParameters(useBestDisp,
1413 numberOfDisparities,
1419 reply.addString(
"ACK");
1421 else if (command.get(0).asString()==
"Point" || command.get(0).asString()==
"Left" )
1423 int u = command.get(1).asInt32();
1424 int v = command.get(2).asInt32();
1425 Point3f point = this->get3DPoints(u,v);
1426 reply.addFloat64(point.x);
1427 reply.addFloat64(point.y);
1428 reply.addFloat64(point.z);
1430 else if (command.get(0).asString()==
"Right")
1432 int u = command.get(1).asInt32();
1433 int v = command.get(2).asInt32();
1434 Point3f point = this->get3DPoints(u,v,
"RIGHT");
1435 reply.addFloat64(point.x);
1436 reply.addFloat64(point.y);
1437 reply.addFloat64(point.z);
1439 else if (command.get(0).asString()==
"Root")
1441 int u = command.get(1).asInt32();
1442 int v = command.get(2).asInt32();
1443 Point3f point = this->get3DPoints(u,v,
"ROOT");
1444 reply.addFloat64(point.x);
1445 reply.addFloat64(point.y);
1446 reply.addFloat64(point.z);
1448 else if (command.get(0).asString()==
"Rect")
1450 int tl_u = command.get(1).asInt32();
1451 int tl_v = command.get(2).asInt32();
1452 int br_u = tl_u+command.get(3).asInt32();
1453 int br_v = tl_v+command.get(4).asInt32();
1456 if (command.size()>=6)
1457 step=command.get(5).asInt32();
1459 for (
int u=tl_u; u<br_u; u+=step)
1461 for (
int v=tl_v; v<br_v; v+=step)
1463 Point3f point=this->get3DPoints(u,v,
"ROOT");
1464 reply.addFloat64(point.x);
1465 reply.addFloat64(point.y);
1466 reply.addFloat64(point.z);
1470 else if (command.get(0).asString()==
"Points")
1472 for (
int cnt=1; cnt<command.size()-1; cnt+=2)
1474 int u=command.get(cnt).asInt32();
1475 int v=command.get(cnt+1).asInt32();
1476 Point3f point=this->get3DPoints(u,v,
"ROOT");
1477 reply.addFloat64(point.x);
1478 reply.addFloat64(point.y);
1479 reply.addFloat64(point.z);
1482 else if (command.get(0).asString()==
"cart2stereo")
1484 double x = command.get(1).asFloat64();
1485 double y = command.get(2).asFloat64();
1486 double z = command.get(3).asFloat64();
1488 Point2f pointL = this->projectPoint(
"left",x,y,z);
1489 Point2f pointR = this->projectPoint(
"right",x,y,z);
1491 reply.addFloat64(pointL.x);
1492 reply.addFloat64(pointL.y);
1493 reply.addFloat64(pointR.x);
1494 reply.addFloat64(pointR.y);
1496 else if (command.get(0).asString()==
"bilatfilt" && command.size()==3)
1500 reply.addString(
"Bilateral filter activated.");
1502 this->stereo_parameters.sigmaColorBLF = command.get(1).asFloat64();
1503 this->stereo_parameters.sigmaSpaceBLF = command.get(2).asFloat64();
1504 reply.addString(
"BLF sigmaColor ");
1505 reply.addFloat64(this->stereo_parameters.sigmaColorBLF);
1506 reply.addString(
"BLF sigmaSpace ");
1507 reply.addFloat64(this->stereo_parameters.sigmaSpaceBLF);
1509 else if (command.get(0).asString()==
"doBLF")
1511 bool onoffBLF = command.get(1).asBool();
1512 if (onoffBLF ==
false ){
1513 if (this->doBLF ==
true){
1514 this->doBLF =
false;
1515 reply.addString(
"Bilateral Filter OFF");
1517 reply.addString(
"Bilateral Filter already OFF");
1521 if (this->doBLF ==
true){
1522 reply.addString(
"Bilateral Filter Already Running");
1525 reply.addString(
"Bilateral Filter ON");
1528 reply.addFloat64(this->stereo_parameters.sigmaColorBLF);
1529 reply.addFloat64(this->stereo_parameters.sigmaSpaceBLF);
1532 reply.addString(
"NACK");
1538 Point2f DispModule::projectPoint(
const string &camera,
double x,
double y,
double z)
1545 vector<Point3f> points3D;
1547 points3D.push_back(point3D);
1549 vector<Point2f> response;
1554 response=this->stereo->projectPoints3D(
"left",points3D,HL_root);
1556 response=this->stereo->projectPoints3D(
"right",points3D,HL_root);
1564 cv::Mat DispModule::refineDisparity(cv::Mat old_disp, cv::Mat new_disp,
int th)
1566 cv::Mat mask, result;
1568 cv::absdiff(old_disp, new_disp, mask);
1569 cv::threshold(mask, mask, th, 1, cv::THRESH_BINARY_INV);
1571 result = new_disp.mul(mask);
1577 DispModule::~DispModule()
1581 if(this->debugWindow)
1582 this->gui.killGUI();
1588 DispModule::DispModule()
1590 this->debugWindow =
false;
1594 int main(
int argc,
char *argv[])
1598 if (!yarp.checkNetwork())
1605 rf.setDefaultContext(
"cameraCalibration");
1606 rf.configure(argc, argv);
1608 if(rf.check(
"use640"))
1609 rf.setDefaultConfigFile(
"icubEyes_640x480.ini");
1611 rf.setDefaultConfigFile(
"icubEyes.ini");
1613 rf.configure(argc, argv);
1617 return mod.runModule(rf);
The base class defining stereo camera.