27 #include <opencv2/opencv.hpp>
34 #include <opencv2/calib3d.hpp>
36 #include <Calibration/Calibration.h>
37 #include <Calibration/Rectification.h>
38 #include <Calibration/StereoCalibration.h>
39 #include <Image/ByteImage.h>
40 #include <Image/ImageProcessor.h>
41 #include <Image/IplImageAdaptor.h>
42 #include <Image/StereoMatcher.h>
43 #include <Math/Math3d.h>
44 #include <Threading/Threading.h>
50 doStereoSGBM(
int minDisparity,
61 int uniquenessRatio = 0;
62 int speckleWindowSize = 0;
64 #if CV_MAJOR_VERSION == 2
66 cv::StereoSGBM stereoSGBM(minDisparity,
77 stereoSGBM(leftInput, rightInput, output);
79 cv::Ptr<cv::StereoSGBM> stereoSGBM = cv::StereoSGBM::create(minDisparity,
89 cv::StereoSGBM::MODE_SGBM);
90 stereoSGBM->compute(leftInput, rightInput, output);
96 const CByteImage* pImageRightColor,
97 const CByteImage* pImageLeftGrey,
98 const CByteImage* pImageRightGrey,
99 const int nDisparityPointDistance,
100 pcl::PointCloud<pcl::PointXYZRGBA>& aPointsFromDisparity,
101 CByteImage* pDisparityImage,
102 const int imageWidth,
103 const int imageHeight,
104 CStereoCalibration* pStereoCalibration,
105 bool imagesAreUndistorted,
106 const bool smoothDisparities)
109 CByteImage *pRectifiedImageLeftGrey, *pRectifiedImageRightGrey,
110 *pRectifiedImageLeftGreyHalfsize, *pRectifiedImageRightGreyHalfsize,
111 *pRectifiedImageLeftGreyQuartersize, *pRectifiedImageRightGreyQuartersize;
112 IplImage *pRectifiedIplImageLeft, *pRectifiedIplImageRight, *pRectifiedIplImageLeftHalfsize,
113 *pRectifiedIplImageRightHalfsize, *pRectifiedIplImageLeftQuartersize,
114 *pRectifiedIplImageRightQuartersize;
115 CByteImage* pRectifiedImageLeftColorGaussFiltered;
116 cv::Mat mDispImg, mDispImgHalfsize, mDispImgQuartersize;
117 bool bGreyImagesReady =
false;
118 bool bGreyImagesHalfsizeReady =
false;
119 bool bGreyImagesQuartersizeReady =
false;
120 const int nPenaltyDispDiffOneFactor = 8;
121 const int nPenaltyDispDiffBiggerOneFactor = 32;
123 CStereoMatcher* pStereoMatcher =
new CStereoMatcher();
124 CStereoCalibration* pStereoCalibrationCopy =
new CStereoCalibration(*pStereoCalibration);
125 pStereoMatcher->InitCameraParameters(pStereoCalibrationCopy,
false);
127 const int nDispMin = pStereoMatcher->GetDisparityEstimate(8000);
128 const int nDispMax = pStereoMatcher->GetDisparityEstimate(400);
130 const int imageOverlapCutoffLeft = 0;
131 const int imageOverlapCutoffRight = 0;
132 const int imageOverlapCutoffTop = 0;
133 const int imageOverlapCutoffBottom = 0;
135 const bool fillHoles =
false;
138 #pragma omp parallel sections
142 const CByteImage* ppOriginalImages[2];
143 ppOriginalImages[0] = pImageLeftGrey;
144 ppOriginalImages[1] = pImageRightGrey;
145 pRectifiedImageLeftGrey =
146 new CByteImage(imageWidth, imageHeight, CByteImage::eGrayScale);
147 pRectifiedImageRightGrey =
148 new CByteImage(imageWidth, imageHeight, CByteImage::eGrayScale);
149 CByteImage* ppRectifiedImages[2];
150 ppRectifiedImages[0] = pRectifiedImageLeftGrey;
151 ppRectifiedImages[1] = pRectifiedImageRightGrey;
153 CRectification* pRectification =
new CRectification(
true, !imagesAreUndistorted);
154 pRectification->Init(pStereoCalibration);
155 pRectification->Rectify(ppOriginalImages, ppRectifiedImages);
157 pRectifiedIplImageLeft = IplImageAdaptor::Adapt(pRectifiedImageLeftGrey);
158 pRectifiedIplImageRight = IplImageAdaptor::Adapt(pRectifiedImageRightGrey);
159 bGreyImagesReady =
true;
162 pRectifiedImageLeftGreyHalfsize =
163 new CByteImage(imageWidth / 2, imageHeight / 2, CByteImage::eGrayScale);
164 pRectifiedImageRightGreyHalfsize =
165 new CByteImage(imageWidth / 2, imageHeight / 2, CByteImage::eGrayScale);
166 ::ImageProcessor::Resize(pRectifiedImageLeftGrey, pRectifiedImageLeftGreyHalfsize);
167 ::ImageProcessor::Resize(pRectifiedImageRightGrey,
168 pRectifiedImageRightGreyHalfsize);
170 pRectifiedIplImageLeftHalfsize =
171 IplImageAdaptor::Adapt(pRectifiedImageLeftGreyHalfsize);
172 pRectifiedIplImageRightHalfsize =
173 IplImageAdaptor::Adapt(pRectifiedImageRightGreyHalfsize);
174 bGreyImagesHalfsizeReady =
true;
177 pRectifiedImageLeftGreyQuartersize =
178 new CByteImage(imageWidth / 4, imageHeight / 4, CByteImage::eGrayScale);
179 pRectifiedImageRightGreyQuartersize =
180 new CByteImage(imageWidth / 4, imageHeight / 4, CByteImage::eGrayScale);
181 ::ImageProcessor::Resize(pRectifiedImageLeftGrey,
182 pRectifiedImageLeftGreyQuartersize);
183 ::ImageProcessor::Resize(pRectifiedImageRightGrey,
184 pRectifiedImageRightGreyQuartersize);
186 pRectifiedIplImageLeftQuartersize =
187 IplImageAdaptor::Adapt(pRectifiedImageLeftGreyQuartersize);
188 pRectifiedIplImageRightQuartersize =
189 IplImageAdaptor::Adapt(pRectifiedImageRightGreyQuartersize);
190 bGreyImagesQuartersizeReady =
true;
192 delete pRectification;
197 const CByteImage* ppOriginalImages[2];
198 ppOriginalImages[0] = pImageLeftColor;
199 ppOriginalImages[1] = pImageRightColor;
200 CByteImage* pRectifiedImageLeftColor =
201 new CByteImage(imageWidth, imageHeight, CByteImage::eRGB24);
202 CByteImage* pRectifiedImageRightColor =
203 new CByteImage(imageWidth, imageHeight, CByteImage::eRGB24);
204 CByteImage* ppRectifiedImages[2];
205 ppRectifiedImages[0] = pRectifiedImageLeftColor;
206 ppRectifiedImages[1] = pRectifiedImageRightColor;
208 CRectification* pRectification =
new CRectification(
true, !imagesAreUndistorted);
209 pRectification->Init(pStereoCalibration);
210 pRectification->Rectify(ppOriginalImages, ppRectifiedImages);
212 pRectifiedImageLeftColorGaussFiltered =
213 new CByteImage(imageWidth, imageHeight, CByteImage::eRGB24);
214 ::ImageProcessor::GaussianSmooth3x3(pRectifiedImageLeftColor,
215 pRectifiedImageLeftColorGaussFiltered);
217 delete pRectifiedImageLeftColor;
218 delete pRectifiedImageRightColor;
219 delete pRectification;
227 while (!bGreyImagesReady)
229 Threading::YieldThread();
246 const cv::Mat mLeftImg = cv::cvarrToMat(pRectifiedIplImageLeft);
247 const cv::Mat mRightImg = cv::cvarrToMat(pRectifiedIplImageRight);
248 const int nSADWindowSize = 7;
249 const int nPenaltyDispDiffOne =
250 nPenaltyDispDiffOneFactor * 3 * nSADWindowSize * nSADWindowSize;
251 const int nPenaltyDispDiffBiggerOne =
252 nPenaltyDispDiffBiggerOneFactor * 3 * nSADWindowSize * nSADWindowSize;
258 nPenaltyDispDiffBiggerOne,
268 while (!bGreyImagesHalfsizeReady)
270 Threading::YieldThread();
273 const cv::Mat mLeftImg = cv::cvarrToMat(pRectifiedIplImageLeftHalfsize);
274 const cv::Mat mRightImg = cv::cvarrToMat(pRectifiedIplImageRightHalfsize);
275 const int nSADWindowSize = 7;
276 const int nPenaltyDispDiffOne =
277 nPenaltyDispDiffOneFactor * 3 * nSADWindowSize * nSADWindowSize;
278 const int nPenaltyDispDiffBiggerOne =
279 nPenaltyDispDiffBiggerOneFactor * 3 * nSADWindowSize * nSADWindowSize;
284 nPenaltyDispDiffBiggerOne,
294 while (!bGreyImagesQuartersizeReady)
296 Threading::YieldThread();
299 const cv::Mat mLeftImg = cv::cvarrToMat(pRectifiedIplImageLeftQuartersize);
300 const cv::Mat mRightImg = cv::cvarrToMat(pRectifiedIplImageRightQuartersize);
301 const int nSADWindowSize = 7;
302 const int nPenaltyDispDiffOne =
303 nPenaltyDispDiffOneFactor * 3 * nSADWindowSize * nSADWindowSize;
304 const int nPenaltyDispDiffBiggerOne =
305 nPenaltyDispDiffBiggerOneFactor * 3 * nSADWindowSize * nSADWindowSize;
311 nPenaltyDispDiffBiggerOne,
315 mDispImgQuartersize);
321 float* pDisparities =
new float[imageWidth * imageHeight];
322 #pragma omp parallel for schedule(static, 80)
323 for (
int i = 0; i < imageHeight; i++)
325 for (
int j = 0; j < imageWidth; j++)
327 int nDispFullsize = mDispImg.at<
short>(i, j) / 16;
328 int nDispHalfsize = 2 * mDispImgHalfsize.at<
short>(i / 2, j / 2) / 16;
329 int nDispQuartersize = 4 * mDispImgQuartersize.at<
short>(i / 4, j / 4) / 16;
333 int nNumValidDisparities = 0;
335 if ((nDispFullsize > nDispMin) && (nDispFullsize < nDispMax))
337 nDisp += nDispFullsize;
338 nNumValidDisparities++;
341 if ((nDispHalfsize > nDispMin) && (nDispHalfsize < nDispMax))
343 nDisp += nDispHalfsize;
344 nNumValidDisparities++;
347 if ((nDispQuartersize > nDispMin) && (nDispQuartersize < nDispMax))
349 nDisp += nDispQuartersize;
350 nNumValidDisparities++;
353 if (nNumValidDisparities > 0)
355 fDisp = (
float)nDisp / (
float)nNumValidDisparities;
358 pDisparities[i * imageWidth + j] = fDisp;
366 std::vector<int> pDisparitiesCopy(imageWidth * imageHeight);
368 for (
int i = 0; i < imageHeight * imageWidth; i++)
370 pDisparitiesCopy[i] = pDisparities[i];
373 const int nMargin = 10;
374 const int nHoleFillingAveragingRadius = 5;
376 for (
int i = nMargin; i < imageHeight - nMargin; i++)
378 for (
int j = nMargin; j < imageWidth - nMargin; j++)
380 if (pDisparitiesCopy[i * imageWidth + j] == 0)
383 int nNumValidDisparities = 0;
385 for (
int k = -nHoleFillingAveragingRadius; k <= nHoleFillingAveragingRadius;
388 for (
int l = -nHoleFillingAveragingRadius;
389 l <= nHoleFillingAveragingRadius;
392 if (pDisparitiesCopy[(i + k) * imageWidth + (j + l)] > 0)
394 nSum += pDisparitiesCopy[(i + k) * imageWidth + (j + l)];
395 nNumValidDisparities++;
400 if (nNumValidDisparities > 0)
402 pDisparities[i * imageWidth + j] = nSum / nNumValidDisparities;
411 float* pSmoothedDisparity = pDisparities;
413 if (smoothDisparities)
415 pSmoothedDisparity =
new float[imageWidth * imageHeight];
416 float* pSmoothedDisparity1 =
new float[imageWidth * imageHeight];
417 float* pSmoothedDisparity2 =
new float[imageWidth * imageHeight];
418 float* pSmoothedDisparity3 =
new float[imageWidth * imageHeight];
419 float* pSmoothedDisparity4 =
new float[imageWidth * imageHeight];
421 #pragma omp parallel sections
426 pDisparities, pSmoothedDisparity1, imageWidth, imageHeight, 1);
432 pDisparities, pSmoothedDisparity2, imageWidth, imageHeight, 2);
446 for (
int i = 0; i < imageWidth * imageHeight; i++)
448 pSmoothedDisparity[i] =
449 0.8f * pDisparities[i] + 0.15f * pSmoothedDisparity1[i] +
455 delete[] pSmoothedDisparity1;
456 delete[] pSmoothedDisparity2;
457 delete[] pSmoothedDisparity3;
458 delete[] pSmoothedDisparity4;
463 for (
int i = 0; i < imageHeight; i++)
465 for (
int j = 0; j < imageWidth; j++)
467 if (i < imageOverlapCutoffTop || i >= imageHeight - imageOverlapCutoffBottom ||
468 j < imageOverlapCutoffLeft || j > imageWidth - imageOverlapCutoffRight)
470 pSmoothedDisparity[i * imageWidth + j] = 0;
479 CByteImage* pRectifiedDisparityImage =
480 new CByteImage(imageWidth, imageHeight, CByteImage::eGrayScale);
482 for (
int i = 0; i < imageHeight; i++)
484 for (
int j = 0; j < imageWidth; j++)
486 int nDisp = pSmoothedDisparity[i * imageWidth + j];
487 pRectifiedDisparityImage->pixels[i * imageWidth + j] =
488 (nDisp > 255) ? 255 : nDisp;
493 ::ImageProcessor::Zero(pDisparityImage);
494 Vec2d vRectPos, vUnRectPos;
495 Mat3d mRectificationHomography = pStereoCalibration->rectificationHomographyLeft;
497 for (
int i = 0; i < imageHeight; i++)
499 for (
int j = 0; j < imageWidth; j++)
503 Math2d::ApplyHomography(mRectificationHomography, vRectPos, vUnRectPos);
505 if (0 <= vUnRectPos.y && vUnRectPos.y < imageHeight && 0 <= vUnRectPos.x &&
506 vUnRectPos.x < imageWidth)
509 ->pixels[(int)vUnRectPos.y * imageWidth + (
int)vUnRectPos.x] =
510 pRectifiedDisparityImage->pixels[i * imageWidth + j];
515 FillHolesGray(pDisparityImage, pRectifiedDisparityImage, imageWidth, imageHeight, 1);
516 FillHolesGray(pRectifiedDisparityImage, pDisparityImage, imageWidth, imageHeight, 1);
517 delete pRectifiedDisparityImage;
521 Vec2d vImgPointLeft, vImgPointRight;
523 const float fDispMin = nDispMin;
524 const float fDispMax = nDispMax;
525 aPointsFromDisparity.width = ceil((
float)imageWidth / (
float)nDisparityPointDistance);
526 aPointsFromDisparity.height = ceil((
float)imageHeight / (
float)nDisparityPointDistance);
527 aPointsFromDisparity.resize(aPointsFromDisparity.width * aPointsFromDisparity.height);
531 for (
int i = 0; i < imageHeight; i += nDisparityPointDistance)
533 for (
int j = 0; j < imageWidth; j += nDisparityPointDistance,
index++)
536 float fDisp = pSmoothedDisparity[i * imageWidth + j];
538 if ((fDisp > fDispMin) && (fDisp < fDispMax))
542 vImgPointRight.x = j - fDisp;
543 vImgPointRight.y = i;
545 pStereoCalibration->Calculate3DPoint(
546 vImgPointLeft, vImgPointRight, vPoint3D,
true,
false);
549 aPointsFromDisparity.points[
index].x = vPoint3D.x;
550 aPointsFromDisparity.points[
index].y = vPoint3D.y;
551 aPointsFromDisparity.points[
index].z = vPoint3D.z;
552 aPointsFromDisparity.points[
index].r =
553 pRectifiedImageLeftColorGaussFiltered->pixels[3 * (i * imageWidth + j)];
554 aPointsFromDisparity.points[
index].g =
555 pRectifiedImageLeftColorGaussFiltered->pixels[3 * (i * imageWidth + j) + 1];
556 aPointsFromDisparity.points[
index].b =
557 pRectifiedImageLeftColorGaussFiltered->pixels[3 * (i * imageWidth + j) + 2];
558 aPointsFromDisparity.points[
index].a = 1.0f;
572 aPointsFromDisparity.points[
index].x = 0;
573 aPointsFromDisparity.points[
index].y = 0;
574 aPointsFromDisparity.points[
index].z = 0;
575 aPointsFromDisparity.points[
index].r = 0;
576 aPointsFromDisparity.points[
index].g = 0;
577 aPointsFromDisparity.points[
index].b = 0;
578 aPointsFromDisparity.points[
index].a = 0;
583 delete pRectifiedImageLeftGrey;
584 delete pRectifiedImageRightGrey;
585 delete pRectifiedImageLeftGreyHalfsize;
586 delete pRectifiedImageRightGreyHalfsize;
587 delete pRectifiedImageLeftGreyQuartersize;
588 delete pRectifiedImageRightGreyQuartersize;
589 delete pRectifiedImageLeftColorGaussFiltered;
590 delete pStereoMatcher;
591 delete pStereoCalibrationCopy;
592 cvReleaseImageHeader(&pRectifiedIplImageLeft);
593 cvReleaseImageHeader(&pRectifiedIplImageRight);
595 if (pSmoothedDisparity != pDisparities)
597 delete[] pSmoothedDisparity;
600 delete[] pDisparities;
605 CByteImage* pOutputImage,
606 const int imageWidth,
607 const int imageHeight,
611 for (
int i = 0; i < imageWidth * imageHeight; i++)
613 pOutputImage->pixels[i] = pInputImage->pixels[i];
616 for (
int i = nRadius; i < imageHeight - nRadius; i++)
618 for (
int j = nRadius; j < imageWidth - nRadius; j++)
620 int nIndex = i * imageWidth + j;
622 if (pInputImage->pixels[nIndex] == 0)
627 for (
int l = -nRadius; l <= nRadius; l++)
629 for (
int k = -nRadius; k <= nRadius; k++)
631 int nTempIndex = nIndex + l * imageWidth + k;
633 if (pInputImage->pixels[nTempIndex] != 0)
635 nSum += pInputImage->pixels[nTempIndex];
643 pOutputImage->pixels[nIndex] = nSum / nNumPixels;
652 float* pSmoothedDisparity,
653 const int imageWidth,
654 const int imageHeight,
658 for (
int i = 0; i < imageWidth * imageHeight; i++)
660 pSmoothedDisparity[i] = pInputDisparity[i];
663 for (
int i = nRadius; i < imageHeight - nRadius; i++)
665 for (
int j = nRadius; j < imageWidth - nRadius; j++)
667 int nIndex = i * imageWidth + j;
669 if (pInputDisparity[nIndex] != 0)
674 for (
int l = -nRadius; l <= nRadius; l++)
676 for (
int k = -nRadius; k <= nRadius; k++)
678 int nTempIndex = nIndex + l * imageWidth + k;
680 if (pInputDisparity[nTempIndex] != 0)
682 fSum += pInputDisparity[nTempIndex];
688 pSmoothedDisparity[nIndex] = fSum / (
float)nNumPixels;