37 #include <opencv2/calib3d/calib3d.hpp> 38 #include <opencv2/imgproc/imgproc.hpp> 39 #include <opencv2/video/tracking.hpp> 40 #include <opencv2/highgui/highgui.hpp> 41 #include <opencv2/imgproc/types_c.h> 45 #if CV_MAJOR_VERSION >= 3 46 #include <opencv2/photo/photo.hpp> 56 float ssd(
const cv::Mat & windowLeft,
const cv::Mat & windowRight)
58 UASSERT_MSG(windowLeft.type() == CV_8UC1 || windowLeft.type() == CV_32FC1 || windowLeft.type() == CV_16SC2,
uFormat(
"Type=%d", windowLeft.type()).c_str());
59 UASSERT(windowLeft.type() == windowRight.type());
60 UASSERT_MSG(windowLeft.rows == windowRight.rows,
uFormat(
"%d vs %d", windowLeft.rows, windowRight.rows).c_str());
61 UASSERT_MSG(windowLeft.cols == windowRight.cols,
uFormat(
"%d vs %d", windowLeft.cols, windowRight.cols).c_str());
64 for(
int v=0; v<windowLeft.rows; ++v)
66 for(
int u=0; u<windowLeft.cols; ++u)
69 if(windowLeft.type() == CV_8UC1)
71 s = float(windowLeft.at<
unsigned char>(v,u))-float(windowRight.at<
unsigned char>(v,u));
73 else if(windowLeft.type() == CV_32FC1)
75 s = windowLeft.at<
float>(v,u)-windowRight.at<
float>(v,u);
77 else if(windowLeft.type() == CV_16SC2)
79 float sL = float(windowLeft.at<cv::Vec2s>(v,u)[0])*0.5f+float(windowLeft.at<cv::Vec2s>(v,u)[1])*0.5f;
80 float sR = float(windowRight.at<cv::Vec2s>(v,u)[0])*0.5f+float(windowRight.at<cv::Vec2s>(v,u)[1])*0.5f;
91 float sad(
const cv::Mat & windowLeft,
const cv::Mat & windowRight)
93 UASSERT_MSG(windowLeft.type() == CV_8UC1 || windowLeft.type() == CV_32FC1 || windowLeft.type() == CV_16SC2,
uFormat(
"Type=%d", windowLeft.type()).c_str());
94 UASSERT(windowLeft.type() == windowRight.type());
95 UASSERT_MSG(windowLeft.rows == windowRight.rows,
uFormat(
"%d vs %d", windowLeft.rows, windowRight.rows).c_str());
96 UASSERT_MSG(windowLeft.cols == windowRight.cols,
uFormat(
"%d vs %d", windowLeft.cols, windowRight.cols).c_str());
99 for(
int v=0; v<windowLeft.rows; ++v)
101 for(
int u=0; u<windowLeft.cols; ++u)
103 if(windowLeft.type() == CV_8UC1)
105 score += fabs(
float(windowLeft.at<
unsigned char>(v,u))-
float(windowRight.at<
unsigned char>(v,u)));
107 else if(windowLeft.type() == CV_32FC1)
109 score += fabs(windowLeft.at<
float>(v,u)-windowRight.at<
float>(v,u));
111 else if(windowLeft.type() == CV_16SC2)
113 float sL = float(windowLeft.at<cv::Vec2s>(v,u)[0])*0.5f+float(windowLeft.at<cv::Vec2s>(v,u)[1])*0.5f;
114 float sR = float(windowRight.at<cv::Vec2s>(v,u)[0])*0.5f+float(windowRight.at<cv::Vec2s>(v,u)[1])*0.5f;
115 score += fabs(sL - sR);
123 const cv::Mat & leftImage,
124 const cv::Mat & rightImage,
125 const std::vector<cv::Point2f> & leftCorners,
126 std::vector<unsigned char> & status,
134 UDEBUG(
"winSize=(%d,%d)", winSize.width, winSize.height);
135 UDEBUG(
"maxLevel=%d", maxLevel);
136 UDEBUG(
"minDisparity=%f", minDisparityF);
137 UDEBUG(
"maxDisparity=%f", maxDisparityF);
138 UDEBUG(
"iterations=%d", iterations);
139 UDEBUG(
"ssdApproach=%d", ssdApproach?1:0);
142 if(winSize.width%2 == 0)
146 if(winSize.height%2 == 0)
151 cv::Size halfWin((winSize.width-1)/2, (winSize.height-1)/2);
154 double pyramidTime = 0.0;
155 double disparityTime = 0.0;
156 double subpixelTime = 0.0;
158 std::vector<cv::Point2f> rightCorners(leftCorners.size());
159 std::vector<cv::Mat> leftPyramid, rightPyramid;
160 maxLevel = cv::buildOpticalFlowPyramid( leftImage, leftPyramid, winSize, maxLevel,
false);
161 maxLevel = cv::buildOpticalFlowPyramid( rightImage, rightPyramid, winSize, maxLevel,
false);
162 pyramidTime = timer.
ticks();
164 status = std::vector<unsigned char>(leftCorners.size(), 0);
165 int totalIterations = 0;
170 for(
unsigned int i=0; i<leftCorners.size(); ++i)
173 float bestScore = -1.0f;
174 int bestScoreIndex = -1;
175 int tmpMinDisparity = minDisparity;
176 int tmpMaxDisparity = maxDisparity;
179 for(
int level=maxLevel; level>=0; --level)
181 UASSERT(level < (
int)leftPyramid.size());
183 cv::Point2i center(
int(leftCorners[i].x/
float(1<<level)),
int(leftCorners[i].y/
float(1<<level)));
188 int localMaxDisparity = -tmpMaxDisparity / (1<<level);
189 int localMinDisparity = -tmpMinDisparity / (1<<level);
191 if(center.x-halfWin.width-(level==0?1:0) >=0 && center.x+halfWin.width+(level==0?1:0) < leftPyramid[level].cols &&
192 center.y-halfWin.height >=0 && center.y+halfWin.height < leftPyramid[level].rows)
194 cv::Mat windowLeft(leftPyramid[level],
195 cv::Range(center.y-halfWin.height,center.y+halfWin.height+1),
196 cv::Range(center.x-halfWin.width,center.x+halfWin.width+1));
197 int minCol = center.x+localMaxDisparity-halfWin.width-1;
200 localMaxDisparity -= minCol;
203 int maxCol = center.x+localMinDisparity+halfWin.width+1;
204 if(maxCol >= leftPyramid[level].cols)
206 localMinDisparity += maxCol-leftPyramid[level].cols-1;
209 if(localMinDisparity < localMaxDisparity)
211 localMaxDisparity = localMinDisparity;
213 int length = localMinDisparity-localMaxDisparity+1;
214 std::vector<float> scores = std::vector<float>(
length, 0.0f);
216 for(
int d=localMinDisparity;
d>localMaxDisparity; --
d)
219 cv::Mat windowRight(rightPyramid[level],
220 cv::Range(center.y-halfWin.height,center.y+halfWin.height+1),
221 cv::Range(center.x+
d-halfWin.width,center.x+
d+halfWin.width+1));
222 scores[oi] = ssdApproach?
ssd(windowLeft, windowRight):
sad(windowLeft, windowRight);
223 if(scores[oi] > 0 && (bestScore < 0.0
f || scores[oi] < bestScore))
226 bestScore = scores[oi];
231 if(bestScoreIndex>=0)
235 tmpMaxDisparity = tmpMinDisparity+(bestScoreIndex+1)*(1<<level);
236 tmpMaxDisparity+=tmpMaxDisparity%level;
237 if(tmpMaxDisparity > maxDisparity)
239 tmpMaxDisparity = maxDisparity;
241 tmpMinDisparity = tmpMinDisparity+(bestScoreIndex-1)*(1<<level);
242 tmpMinDisparity -= tmpMinDisparity%level;
243 if(tmpMinDisparity < minDisparity)
245 tmpMinDisparity = minDisparity;
251 disparityTime+=timer.
ticks();
252 totalIterations+=iterations;
254 if(bestScoreIndex>=0)
257 int d = -(tmpMinDisparity+bestScoreIndex);
259 cv::Mat windowLeft(winSize, CV_32FC1);
260 cv::Mat windowRight(winSize, CV_32FC1);
261 cv::getRectSubPix(leftPyramid[0],
266 if(leftCorners[i].x !=
float(
int(leftCorners[i].x)))
269 cv::getRectSubPix(rightPyramid[0],
271 cv::Point2f(leftCorners[i].x+
float(d), leftCorners[i].y),
274 bestScore = ssdApproach?
ssd(windowLeft, windowRight):
sad(windowLeft, windowRight);
277 float xc = leftCorners[i].x+float(d);
278 float vc = bestScore;
280 std::map<float, float> cache;
282 for(
int it=0; it<iterations; ++it)
286 float v1 =
uValue(cache, x1, 0.0
f);
287 float v2 =
uValue(cache, x2, 0.0
f);
290 cv::getRectSubPix(rightPyramid[0],
292 cv::Point2f(x1, leftCorners[i].y),
295 v1 = ssdApproach?
ssd(windowLeft, windowRight):
sad(windowLeft, windowRight);
299 cv::getRectSubPix(rightPyramid[0],
301 cv::Point2f(x2, leftCorners[i].y),
304 v2 = ssdApproach?
ssd(windowLeft, windowRight):
sad(windowLeft, windowRight);
307 float previousXc = xc;
308 float previousVc = vc;
310 xc = v1<vc&&v1<v2?x1:v2<vc&&v2<v1?x2:xc;
311 vc = v1<vc&&v1<v2?v1:v2<vc&&v2<v1?v2:vc;
319 cache.insert(std::make_pair(previousXc, previousVc));
323 float(leftCorners[i].x - xc) <= minDisparityF)
330 rightCorners[i] = cv::Point2f(xc, leftCorners[i].y);
331 status[i] = reject?0:1;
334 if(leftCorners[i].x+
float(d) != xc)
341 subpixelTime+=timer.
ticks();
343 UDEBUG(
"SubPixel=%d/%d added (total=%d)", noSubPixel, added, (
int)status.size());
344 UDEBUG(
"totalIterations=%d", totalIterations);
345 UDEBUG(
"Time pyramid = %f s", pyramidTime);
346 UDEBUG(
"Time disparity = %f s", disparityTime);
347 UDEBUG(
"Time sub-pixel = %f s", subpixelTime);
354 #define CV_DESCALE(x,n) (((x) + (1 << ((n)-1))) >> (n)) 368 cv::InputArray _prevPts, cv::InputOutputArray _nextPts,
369 cv::OutputArray _status, cv::OutputArray _err,
370 cv::Size winSize,
int maxLevel,
371 cv::TermCriteria criteria,
372 int flags,
double minEigThreshold )
374 cv::Mat prevPtsMat = _prevPts.getMat();
375 const int derivDepth = cv::DataType<short>::depth;
377 CV_Assert( maxLevel >= 0 && winSize.width > 2 && winSize.height > 2 );
379 int level=0, i, npoints;
380 CV_Assert( (npoints = prevPtsMat.checkVector(2, CV_32F,
true)) >= 0 );
390 if( !(flags & cv::OPTFLOW_USE_INITIAL_FLOW) )
391 _nextPts.create(prevPtsMat.size(), prevPtsMat.type(), -1,
true);
393 cv::Mat nextPtsMat = _nextPts.getMat();
394 CV_Assert( nextPtsMat.checkVector(2, CV_32F,
true) == npoints );
396 const cv::Point2f* prevPts = prevPtsMat.ptr<cv::Point2f>();
397 cv::Point2f* nextPts = nextPtsMat.ptr<cv::Point2f>();
399 _status.create((
int)npoints, 1, CV_8U, -1,
true);
400 cv::Mat statusMat = _status.getMat(), errMat;
401 CV_Assert( statusMat.isContinuous() );
402 uchar* status = statusMat.ptr();
405 for( i = 0; i < npoints; i++ )
410 _err.create((
int)npoints, 1, CV_32F, -1,
true);
411 errMat = _err.getMat();
412 CV_Assert( errMat.isContinuous() );
413 err = errMat.ptr<
float>();
416 std::vector<cv::Mat> prevPyr, nextPyr;
423 if(_prevImg.kind() != cv::_InputArray::STD_VECTOR_MAT)
426 maxLevel = cv::buildOpticalFlowPyramid(_prevImg, prevPyr, winSize, maxLevel,
true);
428 else if(_prevImg.kind() == cv::_InputArray::STD_VECTOR_MAT)
430 _prevImg.getMatVector(prevPyr);
433 levels1 = int(prevPyr.size()) - 1;
434 CV_Assert(levels1 >= 0);
436 if (levels1 % 2 == 1 && prevPyr[0].channels() * 2 == prevPyr[1].channels() && prevPyr[1].depth() == derivDepth)
447 prevPyr[lvlStep1].locateROI(fullSize, ofs);
448 CV_Assert(ofs.x >= winSize.width && ofs.y >= winSize.height
449 && ofs.x + prevPyr[lvlStep1].cols + winSize.width <= fullSize.width
450 && ofs.y + prevPyr[lvlStep1].rows + winSize.height <= fullSize.height);
453 if(levels1 < maxLevel)
456 if(_nextImg.kind() != cv::_InputArray::STD_VECTOR_MAT)
459 maxLevel = cv::buildOpticalFlowPyramid(_nextImg, nextPyr, winSize, maxLevel,
false);
461 else if(_nextImg.kind() == cv::_InputArray::STD_VECTOR_MAT)
463 _nextImg.getMatVector(nextPyr);
466 levels2 = int(nextPyr.size()) - 1;
467 CV_Assert(levels2 >= 0);
469 if (levels2 % 2 == 1 && nextPyr[0].channels() * 2 == nextPyr[1].channels() && nextPyr[1].depth() == derivDepth)
480 nextPyr[lvlStep2].locateROI(fullSize, ofs);
481 CV_Assert(ofs.x >= winSize.width && ofs.y >= winSize.height
482 && ofs.x + nextPyr[lvlStep2].cols + winSize.width <= fullSize.width
483 && ofs.y + nextPyr[lvlStep2].rows + winSize.height <= fullSize.height);
486 if(levels2 < maxLevel)
489 if( (criteria.type & cv::TermCriteria::COUNT) == 0 )
490 criteria.maxCount = 30;
493 if( (criteria.type & cv::TermCriteria::EPS) == 0 )
494 criteria.epsilon = 0.01;
497 criteria.epsilon *= criteria.epsilon;
500 for( level = maxLevel; level >= 0; level-- )
502 cv::Mat derivI = prevPyr[level * lvlStep1 + 1];
504 CV_Assert(prevPyr[level * lvlStep1].size() == nextPyr[level * lvlStep2].size());
505 CV_Assert(prevPyr[level * lvlStep1].type() == nextPyr[level * lvlStep2].type());
507 const cv::Mat & prevImg = prevPyr[level * lvlStep1];
508 const cv::Mat & prevDeriv = derivI;
509 const cv::Mat & nextImg = nextPyr[level * lvlStep2];
513 cv::Point2f halfWin((winSize.width-1)*0.5f, (winSize.height-1)*0.5f);
514 const cv::Mat& I = prevImg;
515 const cv::Mat& J = nextImg;
516 const cv::Mat& derivI = prevDeriv;
518 int j, cn = I.channels(), cn2 = cn*2;
519 cv::AutoBuffer<short> _buf(winSize.area()*(cn + cn2));
520 int derivDepth = cv::DataType<short>::depth;
522 cv::Mat IWinBuf(winSize, CV_MAKETYPE(derivDepth, cn), (
short*)_buf);
523 cv::Mat derivIWinBuf(winSize, CV_MAKETYPE(derivDepth, cn2), (
short*)_buf + winSize.area()*cn);
525 for(
int ptidx = 0; ptidx < npoints; ptidx++ )
527 cv::Point2f prevPt = prevPts[ptidx]*(float)(1./(1 << level));
529 if( level == maxLevel )
531 if( flags & cv::OPTFLOW_USE_INITIAL_FLOW )
532 nextPt = nextPts[ptidx]*(float)(1./(1 << level));
537 nextPt = nextPts[ptidx]*2.f;
538 nextPts[ptidx] = nextPt;
540 cv::Point2i iprevPt, inextPt;
542 iprevPt.x = cvFloor(prevPt.x);
543 iprevPt.y = cvFloor(prevPt.y);
545 if( iprevPt.x < -winSize.width || iprevPt.x >= derivI.cols ||
546 iprevPt.y < -winSize.height || iprevPt.y >= derivI.rows )
551 status[ptidx] =
false;
558 float a = prevPt.x - iprevPt.x;
559 float b = prevPt.y - iprevPt.y;
560 const int W_BITS = 14, W_BITS1 = 14;
561 const float FLT_SCALE = 1.f/(1 << 20);
562 int iw00 = cvRound((1.
f - a)*(1.
f - b)*(1 << W_BITS));
563 int iw01 = cvRound(a*(1.
f - b)*(1 << W_BITS));
564 int iw10 = cvRound((1.
f - a)*b*(1 << W_BITS));
565 int iw11 = (1 << W_BITS) - iw00 - iw01 - iw10;
567 int dstep = (int)(derivI.step/derivI.elemSize1());
568 int stepI = (int)(I.step/I.elemSize1());
569 int stepJ = (int)(J.step/J.elemSize1());
570 acctype iA11 = 0, iA12 = 0, iA22 = 0;
575 for( y = 0; y < winSize.height; y++ )
577 const uchar* src = I.ptr() + (y + iprevPt.y)*stepI + iprevPt.x*cn;
578 const short* dsrc = derivI.ptr<
short>() + (y + iprevPt.y)*dstep + iprevPt.x*cn2;
580 short* Iptr = IWinBuf.ptr<
short>(y);
581 short* dIptr = derivIWinBuf.ptr<
short>(y);
585 for( ; x < winSize.width*cn; x++, dsrc += 2, dIptr += 2 )
587 int ival =
CV_DESCALE(src[x]*iw00 + src[x+cn]*iw01 +
588 src[x+stepI]*iw10 + src[x+stepI+cn]*iw11, W_BITS1-5);
589 int ixval =
CV_DESCALE(dsrc[0]*iw00 + dsrc[cn2]*iw01 +
590 dsrc[dstep]*iw10 + dsrc[dstep+cn2]*iw11, W_BITS1);
591 int iyval =
CV_DESCALE(dsrc[1]*iw00 + dsrc[cn2+1]*iw01 + dsrc[dstep+1]*iw10 +
592 dsrc[dstep+cn2+1]*iw11, W_BITS1);
594 Iptr[x] = (short)ival;
595 dIptr[0] = (short)ixval;
596 dIptr[1] = (short)iyval;
604 A11 = iA11*FLT_SCALE;
605 A12 = iA12*FLT_SCALE;
606 A22 = iA22*FLT_SCALE;
608 float D = A11*A22 - A12*A12;
609 float minEig = (A22 + A11 -
std::sqrt((A11-A22)*(A11-A22) +
610 4.
f*A12*A12))/(2*winSize.width*winSize.height);
612 if( err && (flags & cv::OPTFLOW_LK_GET_MIN_EIGENVALS) != 0 )
613 err[ptidx] = (
float)minEig;
615 if( minEig < minEigThreshold || D < FLT_EPSILON )
617 if( level == 0 && status )
618 status[ptidx] =
false;
625 cv::Point2f prevDelta;
627 for( j = 0; j < criteria.maxCount; j++ )
629 inextPt.x = cvFloor(nextPt.x);
630 inextPt.y = cvFloor(nextPt.y);
632 if( inextPt.x < -winSize.width || inextPt.x >= J.cols ||
633 inextPt.y < -winSize.height || inextPt.y >= J.rows )
635 if( level == 0 && status )
636 status[ptidx] =
false;
640 a = nextPt.x - inextPt.x;
641 b = nextPt.y - inextPt.y;
642 iw00 = cvRound((1.
f - a)*(1.
f - b)*(1 << W_BITS));
643 iw01 = cvRound(a*(1.
f - b)*(1 << W_BITS));
644 iw10 = cvRound((1.
f - a)*b*(1 << W_BITS));
645 iw11 = (1 << W_BITS) - iw00 - iw01 - iw10;
646 acctype ib1 = 0, ib2 = 0;
649 for( y = 0; y < winSize.height; y++ )
651 const uchar* Jptr = J.ptr() + (y + inextPt.y)*stepJ + inextPt.x*cn;
652 const short* Iptr = IWinBuf.ptr<
short>(y);
653 const short* dIptr = derivIWinBuf.ptr<
short>(y);
657 for( ; x < winSize.width*cn; x++, dIptr += 2 )
659 int diff =
CV_DESCALE(Jptr[x]*iw00 + Jptr[x+cn]*iw01 +
660 Jptr[x+stepJ]*iw10 + Jptr[x+stepJ+cn]*iw11,
661 W_BITS1-5) - Iptr[x];
670 cv::Point2f delta( (
float)((A12*b2 - A22*b1) * D),
675 nextPts[ptidx] = nextPt + halfWin;
677 if( delta.ddot(delta) <= criteria.epsilon )
680 if( j > 0 &&
std::abs(delta.x + prevDelta.x) < 0.01 &&
681 std::abs(delta.y + prevDelta.y) < 0.01 )
683 nextPts[ptidx] -= delta*0.5f;
689 if( status[ptidx] && err && level == 0 && (flags & cv::OPTFLOW_LK_GET_MIN_EIGENVALS) == 0 )
691 cv::Point2f nextPoint = nextPts[ptidx] - halfWin;
692 cv::Point inextPoint;
694 inextPoint.x = cvFloor(nextPoint.x);
695 inextPoint.y = cvFloor(nextPoint.y);
697 if( inextPoint.x < -winSize.width || inextPoint.x >= J.cols ||
698 inextPoint.y < -winSize.height || inextPoint.y >= J.rows )
701 status[ptidx] =
false;
705 float aa = nextPoint.x - inextPoint.x;
706 float bb = nextPoint.y - inextPoint.y;
707 iw00 = cvRound((1.
f - aa)*(1.
f - bb)*(1 << W_BITS));
708 iw01 = cvRound(aa*(1.
f - bb)*(1 << W_BITS));
709 iw10 = cvRound((1.
f - aa)*bb*(1 << W_BITS));
710 iw11 = (1 << W_BITS) - iw00 - iw01 - iw10;
713 for( y = 0; y < winSize.height; y++ )
715 const uchar* Jptr = J.ptr() + (y + inextPoint.y)*stepJ + inextPoint.x*cn;
716 const short* Iptr = IWinBuf.ptr<
short>(y);
718 for( x = 0; x < winSize.width*cn; x++ )
720 int diff =
CV_DESCALE(Jptr[x]*iw00 + Jptr[x+cn]*iw01 +
721 Jptr[x+stepJ]*iw10 + Jptr[x+stepJ+cn]*iw11,
722 W_BITS1-5) - Iptr[x];
726 err[ptidx] = errval * 1.f/(32*winSize.width*cn*winSize.height);
735 const cv::Mat & leftImage,
736 const cv::Mat & rightImage,
739 UASSERT(!leftImage.empty() && !rightImage.empty());
740 UASSERT(leftImage.cols == rightImage.cols && leftImage.rows == rightImage.rows);
741 UASSERT((leftImage.type() == CV_8UC1 || leftImage.type() == CV_8UC3) && rightImage.type() == CV_8UC1);
744 if(leftImage.channels() == 3)
746 cv::cvtColor(leftImage, leftMono, CV_BGR2GRAY);
750 leftMono = leftImage;
759 float fx,
float baseline,
762 UASSERT(!disparity.empty() && (disparity.type() == CV_32FC1 || disparity.type() == CV_16SC1));
763 UASSERT(type == CV_32FC1 || type == CV_16UC1);
764 cv::Mat depth = cv::Mat::zeros(disparity.rows, disparity.cols, type);
765 int countOverMax = 0;
766 for (
int i = 0; i < disparity.rows; i++)
768 for (
int j = 0; j < disparity.cols; j++)
770 float disparity_value = disparity.type() == CV_16SC1?float(disparity.at<
short>(i,j))/16.0f:disparity.at<
float>(i,j);
771 if (disparity_value > 0.0
f)
774 float d = baseline * fx / disparity_value;
777 if(depth.type() == CV_32FC1)
779 depth.at<
float>(i,j) = d;
783 if(d*1000.0
f <= (
float)USHRT_MAX)
785 depth.at<
unsigned short>(i,j) = (
unsigned short)(d*1000.0f);
798 UWARN(
"Depth conversion error, %d depth values ignored because they are over the maximum depth allowed (65535 mm).", countOverMax);
804 const cv::Mat & leftImage,
805 const cv::Mat & rightImage,
806 const std::vector<cv::Point2f> & leftCorners,
814 UASSERT(!leftImage.empty() && !rightImage.empty() &&
815 leftImage.type() == CV_8UC1 && rightImage.type() == CV_8UC1 &&
816 leftImage.cols == rightImage.cols &&
817 leftImage.rows == rightImage.rows);
821 std::vector<unsigned char> status;
822 std::vector<float> err;
823 std::vector<cv::Point2f> rightCorners;
824 UDEBUG(
"cv::calcOpticalFlowPyrLK() begin");
825 cv::calcOpticalFlowPyrLK(
832 cv::Size(flowWinSize, flowWinSize), flowMaxLevel,
833 cv::TermCriteria(cv::TermCriteria::COUNT+cv::TermCriteria::EPS, flowIterations, flowEps),
834 cv::OPTFLOW_LK_GET_MIN_EIGENVALS, 1
e-4);
835 UDEBUG(
"cv::calcOpticalFlowPyrLK() end");
841 const cv::Size & disparitySize,
842 const std::vector<cv::Point2f> & leftCorners,
843 const std::vector<cv::Point2f> & rightCorners,
844 const std::vector<unsigned char> &
mask)
846 UASSERT(leftCorners.size() == rightCorners.size());
847 UASSERT(mask.size() == 0 || mask.size() == leftCorners.size());
848 cv::Mat disparity = cv::Mat::zeros(disparitySize, CV_32FC1);
849 for(
unsigned int i=0; i<leftCorners.size(); ++i)
851 if(mask.empty() || mask[i])
853 cv::Point2i dispPt(
int(leftCorners[i].y+0.5
f),
int(leftCorners[i].x+0.5
f));
854 UASSERT(dispPt.x >= 0 && dispPt.x < disparitySize.width);
855 UASSERT(dispPt.y >= 0 && dispPt.y < disparitySize.height);
856 disparity.at<
float>(dispPt.y, dispPt.x) = leftCorners[i].x - rightCorners[i].x;
863 const cv::Mat & leftImage,
864 const std::vector<cv::Point2f> & leftCorners,
865 const std::vector<cv::Point2f> & rightCorners,
866 const std::vector<unsigned char> &
mask,
867 float fx,
float baseline)
869 UASSERT(!leftImage.empty() && leftCorners.size() == rightCorners.size());
870 UASSERT(mask.size() == 0 || mask.size() == leftCorners.size());
871 cv::Mat depth = cv::Mat::zeros(leftImage.rows, leftImage.cols, CV_32FC1);
872 for(
unsigned int i=0; i<leftCorners.size(); ++i)
874 if(mask.size() == 0 || mask[i])
876 float disparity = leftCorners[i].x - rightCorners[i].x;
879 float d = baseline * fx / disparity;
880 depth.at<
float>(int(leftCorners[i].y+0.5
f), int(leftCorners[i].x+0.5
f)) = d;
889 UASSERT(depth32F.empty() || depth32F.type() == CV_32FC1);
891 if(!depth32F.empty())
893 depth16U = cv::Mat(depth32F.rows, depth32F.cols, CV_16UC1);
894 int countOverMax = 0;
895 for(
int i=0; i<depth32F.rows; ++i)
897 for(
int j=0; j<depth32F.cols; ++j)
899 float depth = (depth32F.at<
float>(i,j)*1000.0
f);
900 unsigned short depthMM = 0;
901 if(depth > 0 && depth <= (
float)USHRT_MAX)
903 depthMM = (
unsigned short)depth;
905 else if(depth > (
float)USHRT_MAX)
909 depth16U.at<
unsigned short>(i, j) = depthMM;
914 UWARN(
"Depth conversion error, %d depth values ignored because " 915 "they are over the maximum depth allowed (65535 mm). Is the depth " 916 "image really in meters? 32 bits images should be in meters, " 917 "and 16 bits should be in mm.", countOverMax);
925 UASSERT(depth16U.empty() || depth16U.type() == CV_16UC1);
927 if(!depth16U.empty())
929 depth32F = cv::Mat(depth16U.rows, depth16U.cols, CV_32FC1);
930 for(
int i=0; i<depth16U.rows; ++i)
932 for(
int j=0; j<depth16U.cols; ++j)
934 float depth = float(depth16U.at<
unsigned short>(i,j))/1000.0f;
935 depth32F.at<
float>(i, j) = depth;
943 const cv::Mat & depthImage,
946 float depthErrorRatio,
947 bool estWithNeighborsIfNull)
950 UASSERT(depthImage.type() == CV_16UC1 || depthImage.type() == CV_32FC1);
954 if(u == depthImage.cols && x<
float(depthImage.cols))
956 u = depthImage.cols - 1;
958 if(v == depthImage.rows && y<
float(depthImage.rows))
960 v = depthImage.rows - 1;
963 if(!(u >=0 && u<depthImage.cols && v >=0 && v<depthImage.rows))
965 UDEBUG(
"!(x >=0 && x<depthImage.cols && y >=0 && y<depthImage.rows) cond failed! returning bad point. (x=%f (u=%d), y=%f (v=%d), cols=%d, rows=%d)",
966 x,u,y,v,depthImage.cols, depthImage.rows);
970 bool isInMM = depthImage.type() == CV_16UC1;
980 int u_end =
std::min(u+1, depthImage.cols-1);
981 int v_end =
std::min(v+1, depthImage.rows-1);
986 if(depthImage.at<
unsigned short>(v,u) > 0 &&
989 depth = float(depthImage.at<
unsigned short>(v,u))*0.001f;
994 depth = depthImage.at<
float>(v,u);
997 if((depth==0.0
f || !
uIsFinite(depth)) && estWithNeighborsIfNull)
1002 for(
int uu = u_start; uu <= u_end; ++uu)
1004 for(
int vv = v_start; vv <= v_end; ++vv)
1006 if((uu == u && vv!=v) || (uu != u && vv==v))
1011 if(depthImage.at<
unsigned short>(vv,uu) > 0 &&
1014 d = float(depthImage.at<
unsigned short>(vv,uu))*0.001f;
1019 d = depthImage.at<
float>(vv,uu);
1030 float depthError = depthErrorRatio * tmp;
1031 if(fabs(d - tmp/
float(count)) < depthError)
1044 depth = tmp/float(count);
1052 float sumWeights = 0.0f;
1053 float sumDepths = 0.0f;
1054 for(
int uu = u_start; uu <= u_end; ++uu)
1056 for(
int vv = v_start; vv <= v_end; ++vv)
1058 if(!(uu == u && vv == v))
1063 if(depthImage.at<
unsigned short>(vv,uu) > 0 &&
1066 d = float(depthImage.at<
unsigned short>(vv,uu))*0.001f;
1071 d = depthImage.at<
float>(vv,uu);
1074 float depthError = depthErrorRatio * depth;
1077 if(d != 0.0
f &&
uIsFinite(d) && fabs(d - depth) < depthError)
1079 if(uu == u || vv == v)
1098 depth = (depth+sumDepths)/sumWeights;
1108 cv::Rect
computeRoi(
const cv::Mat & image,
const std::string & roiRatios)
1113 cv::Rect
computeRoi(
const cv::Size & imageSize,
const std::string & roiRatios)
1115 std::list<std::string> strValues =
uSplit(roiRatios,
' ');
1116 if(strValues.size() != 4)
1118 UERROR(
"The number of values must be 4 (roi=\"%s\")", roiRatios.c_str());
1122 std::vector<float> values(4);
1124 for(std::list<std::string>::iterator iter = strValues.begin(); iter!=strValues.end(); ++iter)
1130 if(values[0] >= 0 && values[0] < 1 && values[0] < 1.0
f-values[1] &&
1131 values[1] >= 0 && values[1] < 1 && values[1] < 1.0
f-values[0] &&
1132 values[2] >= 0 && values[2] < 1 && values[2] < 1.0
f-values[3] &&
1133 values[3] >= 0 && values[3] < 1 && values[3] < 1.0
f-values[2])
1139 UERROR(
"The roi ratios are not valid (roi=\"%s\")", roiRatios.c_str());
1145 cv::Rect
computeRoi(
const cv::Mat & image,
const std::vector<float> & roiRatios)
1150 cv::Rect
computeRoi(
const cv::Size & imageSize,
const std::vector<float> & roiRatios)
1152 if(imageSize.height!=0 && imageSize.width!= 0 && roiRatios.size() == 4)
1154 float width = imageSize.width;
1155 float height = imageSize.height;
1156 cv::Rect roi(0, 0, width, height);
1157 UDEBUG(
"roi ratios = %f, %f, %f, %f", roiRatios[0],roiRatios[1],roiRatios[2],roiRatios[3]);
1158 UDEBUG(
"roi = %d, %d, %d, %d", roi.x, roi.y, roi.width, roi.height);
1161 if(roiRatios[0] > 0 && roiRatios[0] < 1.0
f - roiRatios[1])
1163 roi.x = width * roiRatios[0];
1167 if(roiRatios[1] > 0 && roiRatios[1] < 1.0
f - roiRatios[0])
1169 roi.width -= width * roiRatios[1];
1174 if(roiRatios[2] > 0 && roiRatios[2] < 1.0
f - roiRatios[3])
1176 roi.y = height * roiRatios[2];
1180 if(roiRatios[3] > 0 && roiRatios[3] < 1.0
f - roiRatios[2])
1182 roi.height -= height * roiRatios[3];
1184 roi.height -= roi.y;
1185 UDEBUG(
"roi = %d, %d, %d, %d", roi.x, roi.y, roi.width, roi.height);
1191 UERROR(
"Image is null or _roiRatios(=%d) != 4", roiRatios.size());
1196 cv::Mat
decimate(
const cv::Mat & image,
int decimation)
1204 if((image.type() == CV_32FC1 || image.type()==CV_16UC1))
1206 UASSERT_MSG(image.rows % decimation == 0 && image.cols % decimation == 0,
1207 uFormat(
"Decimation of depth images should be exact! (decimation=%d, size=%dx%d)",
1208 decimation, image.cols, image.rows).c_str());
1210 out = cv::Mat(image.rows/decimation, image.cols/decimation, image.type());
1211 if(image.type() == CV_32FC1)
1213 for(
int j=0; j<out.rows; ++j)
1215 for(
int i=0; i<out.cols; ++i)
1217 out.at<
float>(j, i) = image.at<
float>(j*decimation, i*decimation);
1223 for(
int j=0; j<out.rows; ++j)
1225 for(
int i=0; i<out.cols; ++i)
1227 out.at<
unsigned short>(j, i) = image.at<
unsigned short>(j*decimation, i*decimation);
1234 cv::resize(image, out, cv::Size(), 1.0
f/
float(decimation), 1.0
f/
float(decimation), cv::INTER_AREA);
1245 cv::Mat
interpolate(
const cv::Mat & image,
int factor,
float depthErrorRatio)
1253 if((image.type() == CV_32FC1 || image.type()==CV_16UC1))
1256 out = cv::Mat::zeros(image.rows*factor, image.cols*factor, image.type());
1257 for(
int j=0; j<out.rows; j+=factor)
1259 for(
int i=0; i<out.cols; i+=factor)
1267 if(image.type() == CV_32FC1)
1269 dTopLeft = image.at<
float>(j/factor-1, i/factor-1);
1270 dTopRight = image.at<
float>(j/factor-1, i/factor);
1271 dBottomLeft = image.at<
float>(j/factor, i/factor-1);
1272 dBottomRight = image.at<
float>(j/factor, i/factor);
1276 dTopLeft = image.at<
unsigned short>(j/factor-1, i/factor-1);
1277 dTopRight = image.at<
unsigned short>(j/factor-1, i/factor);
1278 dBottomLeft = image.at<
unsigned short>(j/factor, i/factor-1);
1279 dBottomRight = image.at<
unsigned short>(j/factor, i/factor);
1282 if(dTopLeft>0 && dTopRight>0 && dBottomLeft>0 && dBottomRight > 0)
1284 float depthError = depthErrorRatio*(dTopLeft+dTopRight+dBottomLeft+dBottomRight)/4.0
f;
1285 if(fabs(dTopLeft-dTopRight) <= depthError &&
1286 fabs(dTopLeft-dBottomLeft) <= depthError &&
1287 fabs(dTopLeft-dBottomRight) <= depthError)
1291 float slopeTop = (dTopRight-dTopLeft)/
float(factor);
1292 float slopeBottom = (dBottomRight-dBottomLeft)/
float(factor);
1293 if(image.type() == CV_32FC1)
1295 for(
int z=i-factor; z<=i; ++z)
1297 out.at<
float>(j-factor, z) = dTopLeft+(slopeTop*
float(z-(i-factor)));
1298 out.at<
float>(j, z) = dBottomLeft+(slopeBottom*
float(z-(i-factor)));
1303 for(
int z=i-factor; z<=i; ++z)
1305 out.at<
unsigned short>(j-factor, z) = (
unsigned short)(dTopLeft+(slopeTop*float(z-(i-factor))));
1306 out.at<
unsigned short>(j, z) = (
unsigned short)(dBottomLeft+(slopeBottom*float(z-(i-factor))));
1311 if(image.type() == CV_32FC1)
1313 for(
int z=i-factor; z<=i; ++z)
1315 float top = out.at<
float>(j-factor, z);
1316 float bottom = out.at<
float>(j, z);
1317 float slope = (bottom-top)/
float(factor);
1318 for(
int d=j-factor+1;
d<j; ++
d)
1320 out.at<
float>(
d, z) = top+(slope*
float(d-(j-factor)));
1326 for(
int z=i-factor; z<=i; ++z)
1328 float top = out.at<
unsigned short>(j-factor, z);
1329 float bottom = out.at<
unsigned short>(j, z);
1330 float slope = (bottom-top)/
float(factor);
1331 for(
int d=j-factor+1;
d<j; ++
d)
1333 out.at<
unsigned short>(
d, z) = (
unsigned short)(top+(slope*float(d-(j-factor))));
1345 cv::resize(image, out, cv::Size(),
float(factor),
float(factor));
1358 const cv::Mat & depth,
1359 const cv::Mat & depthK,
1360 const cv::Size & colorSize,
1361 const cv::Mat & colorK,
1366 UASSERT(depth.type() == CV_16UC1 || depth.type() == CV_32FC1);
1367 UASSERT(depthK.type() == CV_64FC1 && depthK.cols == 3 && depthK.cols == 3);
1368 UASSERT(colorK.type() == CV_64FC1 && colorK.cols == 3 && colorK.cols == 3);
1370 float fx = depthK.at<
double>(0,0);
1371 float fy = depthK.at<
double>(1,1);
1372 float cx = depthK.at<
double>(0,2);
1373 float cy = depthK.at<
double>(1,2);
1375 float rfx = colorK.at<
double>(0,0);
1376 float rfy = colorK.at<
double>(1,1);
1377 float rcx = colorK.at<
double>(0,2);
1378 float rcy = colorK.at<
double>(1,2);
1384 Eigen::Vector4f P4,P3;
1386 cv::Mat registered = cv::Mat::zeros(colorSize, depth.type());
1388 bool depthInMM = depth.type() == CV_16UC1;
1389 for(
int y=0; y<depth.rows; ++y)
1391 for(
int x=0; x<depth.cols; ++x)
1394 float dz = depthInMM?float(depth.at<
unsigned short>(y,x))*0.001f:depth.at<
float>(y,x);
1398 P4[0] = (x - cx) * dz / fx;
1399 P4[1] = (y - cy) * dz / fy;
1404 float invZ = 1.0f/z;
1405 int dx = (rfx*P3[0])*invZ + rcx;
1406 int dy = (rfy*P3[1])*invZ + rcy;
1412 unsigned short z16 = z * 1000;
1413 unsigned short &zReg = registered.at<
unsigned short>(dy, dx);
1414 if(zReg == 0 || z16 < zReg)
1421 float &zReg = registered.at<
float>(dy, dx);
1422 if(zReg == 0 || z < zReg)
1436 UASSERT(depth.type() == CV_16UC1 || depth.type() == CV_32FC1);
1438 cv::Mat output = depth.clone();
1439 bool isMM = depth.type() == CV_16UC1;
1440 for(
int y=0; y<depth.rows-2; ++y)
1442 for(
int x=0; x<depth.cols-2; ++x)
1444 float a, bRight, bDown;
1447 a = depth.at<
unsigned short>(y, x);
1448 bRight = depth.at<
unsigned short>(y, x+1);
1449 bDown = depth.at<
unsigned short>(y+1, x);
1453 a = depth.at<
float>(y, x);
1454 bRight = depth.at<
float>(y, x+1);
1455 bDown = depth.at<
float>(y+1, x);
1458 if(a > 0.0
f && (bRight == 0.0
f || bDown == 0.0
f))
1460 bool horizontalSet = bRight != 0.0f;
1461 bool verticalSet = bDown != 0.0f;
1463 for(
int h=1; h<=maximumHoleSize && (!horizontalSet || !verticalSet); ++h)
1468 if(x+1+h >= depth.cols)
1470 horizontalSet =
true;
1474 float c = isMM?depth.at<
unsigned short>(y, x+1+h):depth.at<
float>(y, x+1+h);
1482 float depthError = errorRatio*float(a+c)/2.0f;
1483 if(fabs(a-c) <= depthError)
1486 float slope = (c-a)/
float(h+1);
1489 for(
int z=x+1; z<x+1+h; ++z)
1491 unsigned short & value = output.at<
unsigned short>(y, z);
1494 value = (
unsigned short)(a+(slope*
float(z-x)));
1499 value = (value+(
unsigned short)(a+(slope*
float(z-x))))/2;
1505 for(
int z=x+1; z<x+1+h; ++z)
1507 float & value = output.at<
float>(y, z);
1510 value = a+(slope*float(z-x));
1515 value = (value+(a+(slope*float(z-x))))/2;
1520 horizontalSet =
true;
1529 if(y+1+h >= depth.rows)
1535 float c = isMM?depth.at<
unsigned short>(y+1+h, x):depth.at<
float>(y+1+h, x);
1543 float depthError = errorRatio*float(a+c)/2.0f;
1544 if(fabs(a-c) <= depthError)
1547 float slope = (c-a)/
float(h+1);
1550 for(
int z=y+1; z<y+1+h; ++z)
1552 unsigned short & value = output.at<
unsigned short>(z, x);
1555 value = (
unsigned short)(a+(slope*
float(z-y)));
1560 value = (value+(
unsigned short)(a+(slope*
float(z-y))))/2;
1566 for(
int z=y+1; z<y+1+h; ++z)
1568 float & value = output.at<
float>(z, x);
1571 value = (a+(slope*float(z-y)));
1576 value = (value+(a+(slope*float(z-y))))/2;
1595 UASSERT(registeredDepth.type() == CV_16UC1);
1596 int margin = fillDoubleHoles?2:1;
1597 for(
int x=1; x<registeredDepth.cols-margin; ++x)
1599 for(
int y=1; y<registeredDepth.rows-margin; ++y)
1601 unsigned short & b = registeredDepth.at<
unsigned short>(y, x);
1605 const unsigned short & a = registeredDepth.at<
unsigned short>(y-1, x);
1606 unsigned short & c = registeredDepth.at<
unsigned short>(y+1, x);
1609 unsigned short error = 0.01*((a+c)/2);
1610 if(((b == 0 && a && c) || (b > a+error && b > c+error)) &&
1611 (a>c?a-c<=error:c-a<=error))
1621 if(!
set && fillDoubleHoles)
1623 const unsigned short &
d = registeredDepth.at<
unsigned short>(y+2, x);
1624 if(a && d && (b==0 || c==0))
1626 unsigned short error = 0.01*((a+d)/2);
1627 if(((b == 0 && a && d) || (b > a+error && b > d+error)) &&
1628 ((c == 0 && a && d) || (c > a+error && c > d+error)) &&
1629 (a>d?a-d<=error:d-a<=error))
1633 unsigned short tmp = (a-d)/4;
1639 unsigned short tmp = (d-a)/4;
1652 if(!
set && horizontal)
1654 const unsigned short & a = registeredDepth.at<
unsigned short>(y, x-1);
1655 unsigned short & c = registeredDepth.at<
unsigned short>(y, x+1);
1658 unsigned short error = 0.01*((a+c)/2);
1659 if(((b == 0 && a && c) || (b > a+error && b > c+error)) &&
1660 (a>c?a-c<=error:c-a<=error))
1666 if(!
set && fillDoubleHoles)
1668 const unsigned short &
d = registeredDepth.at<
unsigned short>(y, x+2);
1669 if(a && d && (b==0 || c==0))
1671 unsigned short error = 0.01*((a+d)/2);
1672 if(((b == 0 && a && d) || (b > a+error && b > d+error)) &&
1673 ((c == 0 && a && d) || (c > a+error && c > d+error)) &&
1674 (a>d?a-d<=error:d-a<=error))
1678 unsigned short tmp = (a-d)/4;
1684 unsigned short tmp = (d-a)/4;
1700 Array3D (
const size_t width,
const size_t height,
const size_t depth)
1705 v_ = std::vector<Eigen::Vector2f> (width*height*depth, Eigen::Vector2f (0.0
f, 0.0
f));
1708 inline Eigen::Vector2f&
1712 inline const Eigen::Vector2f&
1717 resize (
const size_t width,
const size_t height,
const size_t depth)
1730 const size_t x_index =
clamp (0,
x_dim_ - 1, static_cast<size_t> (x));
1731 const size_t xx_index =
clamp (0,
x_dim_ - 1, x_index + 1);
1733 const size_t y_index =
clamp (0,
y_dim_ - 1, static_cast<size_t> (y));
1734 const size_t yy_index =
clamp (0,
y_dim_ - 1, y_index + 1);
1736 const size_t z_index =
clamp (0,
z_dim_ - 1, static_cast<size_t> (z));
1737 const size_t zz_index =
clamp (0,
z_dim_ - 1, z_index + 1);
1739 const float x_alpha = x -
static_cast<float> (x_index);
1740 const float y_alpha = y -
static_cast<float> (y_index);
1741 const float z_alpha = z -
static_cast<float> (z_index);
1744 (1.0
f-x_alpha) * (1.0f-y_alpha) * (1.0
f-z_alpha) * (*this)(x_index, y_index, z_index) +
1745 x_alpha * (1.0
f-y_alpha) * (1.0f-z_alpha) * (*
this)(xx_index, y_index, z_index) +
1746 (1.0
f-x_alpha) * y_alpha * (1.0f-z_alpha) * (*
this)(x_index, yy_index, z_index) +
1747 x_alpha * y_alpha * (1.0
f-z_alpha) * (*this)(xx_index, yy_index, z_index) +
1748 (1.0
f-x_alpha) * (1.0f-y_alpha) * z_alpha * (*
this)(x_index, y_index, zz_index) +
1749 x_alpha * (1.0
f-y_alpha) * z_alpha * (*this)(xx_index, y_index, zz_index) +
1750 (1.0
f-x_alpha) * y_alpha * z_alpha * (*this)(x_index, yy_index, zz_index) +
1751 x_alpha * y_alpha * z_alpha * (*
this)(xx_index, yy_index, zz_index);
1754 static inline size_t 1756 const size_t max_value,
1759 if (x >= min_value && x <= max_value)
1763 else if (x < min_value)
1785 inline std::vector<Eigen::Vector2f >::iterator
1787 {
return v_.begin (); }
1789 inline std::vector<Eigen::Vector2f >::iterator
1791 {
return v_.end (); }
1793 inline std::vector<Eigen::Vector2f >::const_iterator
1795 {
return v_.begin (); }
1797 inline std::vector<Eigen::Vector2f >::const_iterator
1799 {
return v_.end (); }
1802 std::vector<Eigen::Vector2f >
v_;
1811 UASSERT(!depth.empty() && (depth.type() == CV_32FC1 || depth.type() == CV_16UC1));
1812 UDEBUG(
"Begin: depth float=%d %dx%d sigmaS=%f sigmaR=%f earlDivision=%d",
1813 depth.type()==CV_32FC1?1:0, depth.cols, depth.rows, sigmaS, sigmaR, earlyDivision?1:0);
1815 cv::Mat output = cv::Mat::zeros(depth.size(), CV_32FC1);
1819 bool found_finite =
false;
1820 for (
int x = 0; x < depth.cols; ++x)
1821 for (
int y = 0; y < depth.rows; ++y)
1823 float z = depth.type()==CV_32FC1?depth.at<
float>(y, x):
float(depth.at<
unsigned short>(y, x))/1000.0
f;
1830 found_finite =
true;
1835 UWARN(
"Given an empty depth image. Doing nothing.");
1838 UDEBUG(
"base_min=%f base_max=%f", base_min, base_max);
1840 const float base_delta = base_max - base_min;
1842 const size_t padding_xy = 2;
1843 const size_t padding_z = 2;
1845 const size_t small_width =
static_cast<size_t> (
static_cast<float> (depth.cols - 1) / sigmaS) + 1 + 2 * padding_xy;
1846 const size_t small_height =
static_cast<size_t> (
static_cast<float> (depth.rows - 1) / sigmaS) + 1 + 2 * padding_xy;
1847 const size_t small_depth =
static_cast<size_t> (base_delta / sigmaR) + 1 + 2 * padding_z;
1849 UDEBUG(
"small_width=%d small_height=%d small_depth=%d", (
int)small_width, (
int)small_height, (
int)small_depth);
1850 Array3D data (small_width, small_height, small_depth);
1851 for (
int x = 0; x < depth.cols; ++x)
1853 const size_t small_x =
static_cast<size_t> (
static_cast<float> (x) / sigmaS + 0.5
f) + padding_xy;
1854 for (
int y = 0; y < depth.rows; ++y)
1856 float v = depth.type()==CV_32FC1?depth.at<
float>(y,x):
float(depth.at<
unsigned short>(y,x))/1000.0
f;
1859 float z = v - base_min;
1861 const size_t small_y =
static_cast<size_t> (
static_cast<float> (y) / sigmaS + 0.5
f) + padding_xy;
1862 const size_t small_z =
static_cast<size_t> (
static_cast<float> (z) / sigmaR + 0.5
f) + padding_z;
1864 Eigen::Vector2f&
d = data (small_x, small_y, small_z);
1871 std::vector<long int> offset (3);
1872 offset[0] = &(data (1,0,0)) - &(data (0,0,0));
1873 offset[1] = &(data (0,1,0)) - &(data (0,0,0));
1874 offset[2] = &(data (0,0,1)) - &(data (0,0,0));
1876 Array3D buffer (small_width, small_height, small_depth);
1878 for (
size_t dim = 0; dim < 3; ++dim)
1880 const long int off = offset[dim];
1881 for (
size_t n_iter = 0; n_iter < 2; ++n_iter)
1883 std::swap (buffer, data);
1884 for(
size_t x = 1; x < small_width - 1; ++x)
1885 for(
size_t y = 1; y < small_height - 1; ++y)
1887 Eigen::Vector2f* d_ptr = &(data (x,y,1));
1888 Eigen::Vector2f* b_ptr = &(buffer (x,y,1));
1890 for(
size_t z = 1; z < small_depth - 1; ++z, ++d_ptr, ++b_ptr)
1891 *d_ptr = (*(b_ptr - off) + *(b_ptr + off) + 2.0 * (*b_ptr)) / 4.0;
1898 for (std::vector<Eigen::Vector2f>::iterator
d = data.
begin ();
d != data.
end (); ++
d)
1899 *
d /= ((*
d)[0] != 0) ? (*
d)[1] : 1;
1902 for (
int x = 0; x < depth.cols; ++x)
1903 for (
int y = 0; y < depth.rows; ++y)
1905 float z = depth.type()==CV_32FC1?depth.at<
float>(y,x):
float(depth.at<
unsigned short>(y,x))/1000.0
f;
1910 static_cast<float> (y) / sigmaS + padding_xy,
1911 z / sigmaR + padding_z);
1912 float v = earlyDivision ? D[0] : D[0] / D[1];
1913 if(v < base_min || v >= base_max)
1917 if(depth.type()==CV_16UC1 && v>65.5350f)
1921 output.at<
float>(y,x) = v;
1940 CV_Assert(clipLowHistPercent >= 0 && clipHighHistPercent>=0);
1941 CV_Assert((src.type() == CV_8UC1) || (src.type() == CV_8UC3) || (src.type() == CV_8UC4));
1945 double minGray = 0, maxGray = 0;
1949 if (src.type() == CV_8UC1) gray = src;
1950 else if (src.type() == CV_8UC3)
cvtColor(src, gray, CV_BGR2GRAY);
1951 else if (src.type() == CV_8UC4)
cvtColor(src, gray, CV_BGRA2GRAY);
1952 if (clipLowHistPercent == 0 && clipHighHistPercent == 0)
1955 cv::minMaxLoc(gray, &minGray, &maxGray, 0, 0, mask);
1961 float range[] = { 0, 256 };
1962 const float* histRange = { range };
1963 bool uniform =
true;
1964 bool accumulate =
false;
1965 calcHist(&gray, 1, 0, mask, hist, 1, &histSize, &histRange, uniform, accumulate);
1968 std::vector<float> accumulator(histSize);
1969 accumulator[0] = hist.at<
float>(0);
1970 for (
int i = 1; i < histSize; i++)
1972 accumulator[i] = accumulator[i - 1] + hist.at<
float>(i);
1976 float max = accumulator.back();
1977 clipLowHistPercent *= (max / 100.0);
1978 clipHighHistPercent *= (max / 100.0);
1981 while (accumulator[minGray] < clipLowHistPercent)
1985 maxGray = histSize - 1;
1986 while (accumulator[maxGray] >= (max - clipHighHistPercent))
1991 float inputRange = maxGray - minGray;
1993 alpha = (histSize - 1) / inputRange;
1994 beta = -minGray * alpha;
1996 UINFO(
"minGray=%f maxGray=%f alpha=%f beta=%f", minGray, maxGray, alpha, beta);
2001 src.convertTo(dst, -1, alpha, beta);
2004 if (dst.type() == CV_8UC4)
2006 int from_to[] = { 3, 3};
2007 cv::mixChannels(&src, 4, &dst,1, from_to, 1);
2016 #if CV_MAJOR_VERSION >= 3 2017 cv::createMergeMertens()->process(images, fusion);
2019 UASSERT(fusion.channels() == 3);
2020 fusion.convertTo(rgb8, CV_8UC3, 255.0);
2023 UWARN(
"Exposure fusion is only available when rtabmap is built with OpenCV3.");
2026 fusion = images[0].clone();
cv::Mat RTABMAP_EXP disparityFromStereoImages(const cv::Mat &leftImage, const cv::Mat &rightImage, const ParametersMap ¶meters=ParametersMap())
GLM_FUNC_DECL genIType mask(genIType const &count)
cv::Mat RTABMAP_EXP depthFromStereoCorrespondences(const cv::Mat &leftImage, const std::vector< cv::Point2f > &leftCorners, const std::vector< cv::Point2f > &rightCorners, const std::vector< unsigned char > &mask, float fx, float baseline)
std::vector< Eigen::Vector2f >::const_iterator end() const
std::vector< Eigen::Vector2f >::iterator end()
cv::Mat RTABMAP_EXP cvtDepthToFloat(const cv::Mat &depth16U)
GLM_FUNC_DECL genType min(genType const &x, genType const &y)
bool uIsInBounds(const T &value, const T &low, const T &high)
GLM_FUNC_DECL vecType< T, P > sqrt(vecType< T, P > const &x)
Eigen::Vector2f trilinear_interpolation(const float x, const float y, const float z)
cv::Mat RTABMAP_EXP depthFromDisparity(const cv::Mat &disparity, float fx, float baseline, int type=CV_32FC1)
GLM_FUNC_DECL genType e()
float UTILITE_EXP uStr2Float(const std::string &str)
std::map< std::string, std::string > ParametersMap
cv::Mat RTABMAP_EXP fastBilateralFiltering(const cv::Mat &depth, float sigmaS=15.0f, float sigmaR=0.05f, bool earlyDivision=false)
Basic mathematics functions.
Some conversion functions.
cv::Mat RTABMAP_EXP registerDepth(const cv::Mat &depth, const cv::Mat &depthK, const cv::Size &colorSize, const cv::Mat &colorK, const rtabmap::Transform &transform)
cv::Mat RTABMAP_EXP depthFromStereoImages(const cv::Mat &leftImage, const cv::Mat &rightImage, const std::vector< cv::Point2f > &leftCorners, float fx, float baseline, int flowWinSize=9, int flowMaxLevel=4, int flowIterations=20, double flowEps=0.02)
std::vector< Eigen::Vector2f > v_
std::vector< Eigen::Vector2f >::const_iterator begin() const
GLM_FUNC_DECL genType step(genType const &edge, genType const &x)
std::list< std::string > uSplit(const std::string &str, char separator= ' ')
cv::Mat RTABMAP_EXP interpolate(const cv::Mat &image, int factor, float depthErrorRatio=0.02f)
float RTABMAP_EXP ssd(const cv::Mat &windowLeft, const cv::Mat &windowRight)
Array3D(const size_t width, const size_t height, const size_t depth)
bool uIsFinite(const T &value)
#define UASSERT(condition)
Wrappers of STL for convenient functions.
virtual cv::Mat computeDisparity(const cv::Mat &leftImage, const cv::Mat &rightImage) const
GLM_FUNC_DECL genType floor(genType const &x)
#define UASSERT_MSG(condition, msg_str)
CvImagePtr cvtColor(const CvImageConstPtr &source, const std::string &encoding)
GLM_FUNC_DECL vecType proj(vecType const &x, vecType const &Normal)
cv::Mat RTABMAP_EXP decimate(const cv::Mat &image, int d)
cv::Mat RTABMAP_EXP brightnessAndContrastAuto(const cv::Mat &src, const cv::Mat &mask, float clipLowHistPercent=0, float clipHighHistPercent=0)
Automatic brightness and contrast optimization with optional histogram clipping.
cv::Mat RTABMAP_EXP disparityFromStereoCorrespondences(const cv::Size &disparitySize, const std::vector< cv::Point2f > &leftCorners, const std::vector< cv::Point2f > &rightCorners, const std::vector< unsigned char > &mask)
GLM_FUNC_DECL genType abs(genType const &x)
cv::Rect RTABMAP_EXP computeRoi(const cv::Mat &image, const std::string &roiRatios)
void RTABMAP_EXP fillRegisteredDepthHoles(cv::Mat &depthRegistered, bool vertical, bool horizontal, bool fillDoubleHoles=false)
std::vector< Eigen::Vector2f >::iterator begin()
cv::Mat RTABMAP_EXP exposureFusion(const std::vector< cv::Mat > &images)
GLM_FUNC_DECL genType max(genType const &x, genType const &y)
cv::Mat RTABMAP_EXP fillDepthHoles(const cv::Mat &depth, int maximumHoleSize=1, float errorRatio=0.02f)
void resize(const size_t width, const size_t height, const size_t depth)
ULogger class and convenient macros.
static size_t clamp(const size_t min_value, const size_t max_value, const size_t x)
float RTABMAP_EXP sad(const cv::Mat &windowLeft, const cv::Mat &windowRight)
cv::Mat RTABMAP_EXP cvtDepthFromFloat(const cv::Mat &depth32F)
float RTABMAP_EXP getDepth(const cv::Mat &depthImage, float x, float y, bool smoothing, float depthErrorRatio=0.02f, bool estWithNeighborsIfNull=false)
GLM_FUNC_DECL genType::value_type length(genType const &x)
std::string UTILITE_EXP uFormat(const char *fmt,...)
std::vector< cv::Point2f > RTABMAP_EXP calcStereoCorrespondences(const cv::Mat &leftImage, const cv::Mat &rightImage, const std::vector< cv::Point2f > &leftCorners, std::vector< unsigned char > &status, cv::Size winSize=cv::Size(6, 3), int maxLevel=3, int iterations=5, float minDisparity=0.0f, float maxDisparity=64.0f, bool ssdApproach=true)
V uValue(const std::map< K, V > &m, const K &key, const V &defaultValue=V())
Eigen::Vector2f & operator()(const size_t x, const size_t y, const size_t z)
void RTABMAP_EXP calcOpticalFlowPyrLKStereo(cv::InputArray _prevImg, cv::InputArray _nextImg, cv::InputArray _prevPts, cv::InputOutputArray _nextPts, cv::OutputArray _status, cv::OutputArray _err, cv::Size winSize=cv::Size(15, 3), int maxLevel=3, cv::TermCriteria criteria=cv::TermCriteria(cv::TermCriteria::COUNT+cv::TermCriteria::EPS, 30, 0.01), int flags=0, double minEigThreshold=1e-4)