29 #include <Calibration/Calibration.h>
30 #include <Calibration/StereoCalibration.h>
31 #include <Image/ByteImage.h>
32 #include <Image/ImageProcessor.h>
33 #include <Image/IplImageAdaptor.h>
52 const CByteImage* pHSVImage,
53 std::vector<CMSERDescriptor*>& aMSERDescriptors)
55 #if (CV_MAJOR_VERSION == 2)
56 #if (CV_MINOR_VERSION < 4)
72 cv::MSER pMSERDetector = cv::MSER();
78 pMSERDetector.maxArea *= 10;
79 pMSERDetector.maxVariation *= 3;
80 pMSERDetector.maxEvolution *= 3;
81 pMSERDetector.minMargin *= 0.33;
85 pIplImage = IplImageAdaptor::Adapt(pRGBImage);
87 std::vector<std::vector<cv::Point>> aContoursCVLeft;
88 std::vector<std::vector<Vec2d>> aContoursLeft;
92 cv::Seq<CvSeq*> contoursLeft;
93 cv::MemStorage storageLeft(cvCreateMemStorage(0));
94 cvExtractMSER(pIplImage, NULL, &contoursLeft.seq, storageLeft, pMSERDetector);
96 cv::SeqIterator<CvSeq*> itLeft = contoursLeft.begin();
97 size_t i, ncontours = contoursLeft.size();
98 aContoursCVLeft.resize(ncontours);
100 for (i = 0; i < ncontours; i++, ++itLeft)
102 while (cv::Seq<cv::Point>(*itLeft).size() > 0)
104 aContoursCVLeft[i].push_back(cv::Seq<cv::Point>(*itLeft).front());
105 cv::Seq<cv::Point>(*itLeft).pop_front();
112 for (
int i = 0; i < (int)aContoursCVLeft.size(); i++)
114 std::vector<Vec2d> aPoints;
115 aContoursLeft.push_back(aPoints);
117 for (
int j = 0; j < (int)aContoursCVLeft.at(i).size(); j++)
119 Vec2d vTemp = {(
float)aContoursCVLeft.at(i).at(j).x,
120 (
float)aContoursCVLeft.at(i).at(j).y};
121 aContoursLeft.at(i).push_back(vTemp);
131 for (
int i = 0; i < (int)aContoursLeft.size(); i++)
134 aMSERDescriptors.push_back(pDescriptor);
145 cvReleaseImageHeader(&pIplImage);
146 storageLeft.release();
148 #elif (CV_MINOR_VERSION == 4)
149 cv::MSER pMSERDetector = cv::MSER();
151 pIplImage = IplImageAdaptor::Adapt(pRGBImage);
152 std::vector<std::vector<cv::Point>> aContoursCVLeft;
154 pMSERDetector(pIplImage, aContoursCVLeft, cv::Mat());
156 std::vector<std::vector<Vec2d>> aContoursLeft;
158 for (
int i = 0; i < (int)aContoursCVLeft.size(); i++)
160 std::vector<Vec2d> aPoints;
161 aContoursLeft.push_back(aPoints);
163 for (
int j = 0; j < (int)aContoursCVLeft.at(i).size(); j++)
165 Vec2d vTemp = {(
float)aContoursCVLeft.at(i).at(j).x,
166 (
float)aContoursCVLeft.at(i).at(j).y};
167 aContoursLeft.at(i).push_back(vTemp);
171 for (
int i = 0; i < (int)aContoursLeft.size(); i++)
174 aMSERDescriptors.push_back(pDescriptor);
177 cvReleaseImageHeader(&pIplImage);
179 ARMARX_WARNING_S <<
"This code is not implemented for OpenCV Version " << CV_VERSION
180 <<
" (CV_MINOR_VERSION = " << CV_MINOR_VERSION <<
")";
183 ARMARX_WARNING_S <<
"This code is not implemented for OpenCV Version " << CV_VERSION
184 <<
" (CV_MAJOR_VERSION = " << CV_MAJOR_VERSION <<
")";
190 const std::vector<CMSERDescriptor*>& aMSERDescriptorsRight,
191 CStereoCalibration* pStereoCalibration,
192 const float fToleranceFactor,
193 std::vector<CMSERDescriptor3D*>& aRegions3D)
196 const float fRatioThresholdHigh = 1.0f + fToleranceFactor * 0.25f;
197 const float fRatioThresholdLow = 1.0f / fRatioThresholdHigh;
198 const float fRatioThresholdHigh2 = fRatioThresholdHigh * fRatioThresholdHigh;
199 const float fRatioThresholdLow2 = fRatioThresholdLow * fRatioThresholdLow;
201 for (
int i = 0; i < (int)aMSERDescriptorsLeft.size(); i++)
203 float fMinEpipolarDistance = fToleranceFactor * 2.0f;
204 int nCorrespondenceIndex = -1;
205 const float fOwnEVRatio =
206 aMSERDescriptorsLeft.at(i)->fEigenvalue2 / aMSERDescriptorsLeft.at(i)->fEigenvalue1;
208 for (
int j = 0; j < (int)aMSERDescriptorsRight.size(); j++)
210 const float fSizeRatio = (
float)aMSERDescriptorsLeft.at(i)->nSize /
211 (
float)aMSERDescriptorsRight.at(j)->nSize;
213 if ((fRatioThresholdLow < fSizeRatio) && (fSizeRatio < fRatioThresholdHigh))
215 const float fEV1Ratio = aMSERDescriptorsLeft.at(i)->fEigenvalue1 /
216 aMSERDescriptorsRight.at(j)->fEigenvalue1;
217 const float fEV2Ratio = aMSERDescriptorsLeft.at(i)->fEigenvalue2 /
218 aMSERDescriptorsRight.at(j)->fEigenvalue2;
219 const float fRatioRatio = (aMSERDescriptorsRight.at(j)->fEigenvalue2 /
220 aMSERDescriptorsRight.at(j)->fEigenvalue1) /
223 if ((fRatioThresholdLow2 < fEV1Ratio) && (fEV1Ratio < fRatioThresholdHigh2) &&
224 (fRatioThresholdLow2 < fEV2Ratio) && (fEV2Ratio < fRatioThresholdHigh2) &&
225 (fRatioThresholdLow2 < fRatioRatio) && (fRatioRatio < fRatioThresholdHigh2))
227 const float fEpipolarDistance =
228 fabsf(pStereoCalibration->CalculateEpipolarLineInLeftImageDistance(
229 aMSERDescriptorsLeft.at(i)->vMean, aMSERDescriptorsRight.at(j)->vMean));
231 if (fEpipolarDistance < fMinEpipolarDistance)
234 pStereoCalibration->Calculate3DPoint(aMSERDescriptorsLeft.at(i)->vMean,
235 aMSERDescriptorsRight.at(j)->vMean,
242 fMinEpipolarDistance = fEpipolarDistance;
243 nCorrespondenceIndex = j;
250 if (nCorrespondenceIndex != -1)
254 aMSERDescriptorsRight.at(nCorrespondenceIndex),
256 aRegions3D.push_back(pDescr3D);
263 const CByteImage* pByteImageRight,
264 CStereoCalibration* pStereoCalibration,
265 const float fToleranceFactor,
266 std::vector<CMSERDescriptor3D*>& aRegions3D)
274 ImageProcessor::CalculateHSVImage(pByteImageLeft, pHSVImageLeft);
275 ImageProcessor::CalculateHSVImage(pByteImageRight, pHSVImageRight);
282 std::vector<CMSERDescriptor*> aMSERDescriptorsLeft;
283 std::vector<CMSERDescriptor*> aMSERDescriptorsRight;
284 FindMSERs2D(pByteImageLeft, pHSVImageLeft, aMSERDescriptorsLeft);
285 FindMSERs2D(pByteImageRight, pHSVImageRight, aMSERDescriptorsRight);
290 aMSERDescriptorsRight,
318 for (
size_t i = 0; i < aMSERDescriptorsLeft.size(); i++)
320 aMSERDescriptorsLeft.at(i)->pPoints2D->clear();
321 delete aMSERDescriptorsLeft.at(i)->pPoints2D;
322 delete aMSERDescriptorsLeft.at(i);
325 for (
size_t i = 0; i < aMSERDescriptorsRight.size(); i++)
327 aMSERDescriptorsRight.at(i)->pPoints2D->clear();
328 delete aMSERDescriptorsRight.at(i)->pPoints2D;
329 delete aMSERDescriptorsRight.at(i);
333 delete pHSVImageLeft;
334 delete pHSVImageRight;
349 if (aPoints2D.size() < 2)
357 for (
int i = 0; i < (int)aPoints2D.size(); i++)
359 vMean.x += (
float)aPoints2D.at(i).x;
360 vMean.y += (
float)aPoints2D.at(i).y;
363 vMean.x /= aPoints2D.size();
364 vMean.y /= aPoints2D.size();
366 for (
int i = 0; i < (int)aPoints2D.size(); i++)
369 (vMean.x - (
float)aPoints2D.at(i).x) * (vMean.x - (
float)aPoints2D.at(i).x);
371 (vMean.x - (
float)aPoints2D.at(i).x) * (vMean.y - (
float)aPoints2D.at(i).y);
373 (vMean.y - (
float)aPoints2D.at(i).y) * (vMean.y - (
float)aPoints2D.at(i).y);
376 mCovariance.r1 /= aPoints2D.size() - 1;
377 mCovariance.r2 /= aPoints2D.size() - 1;
378 mCovariance.r3 = mCovariance.r2;
379 mCovariance.r4 /= aPoints2D.size() - 1;
389 float fTemp1 = 0.5f * (mMatrix2D.r1 + mMatrix2D.r4);
391 sqrtf(fTemp1 * fTemp1 - mMatrix2D.r1 * mMatrix2D.r4 + mMatrix2D.r2 * mMatrix2D.r3);
393 fLambda1 = fTemp1 + fTemp2;
394 fLambda2 = fTemp1 - fTemp2;
396 vE1.x = fLambda1 - mMatrix2D.r4;
397 vE1.y = mMatrix2D.r3;
398 Math2d::NormalizeVec(vE1);
400 vE2.x = fLambda2 - mMatrix2D.r4;
401 vE2.y = mMatrix2D.r3;
402 Math2d::NormalizeVec(vE2);
408 if (aPoints2D->size() < 2)
415 pDescr->
nSize = (int)aPoints2D->size();
417 pDescr->
pPoints2D =
new std::vector<Vec2d>;
419 for (
int i = 0; i < (int)aPoints2D->size(); i++)
421 pDescr->
pPoints2D->push_back(aPoints2D->at(i));
442 CStereoCalibration* pStereoCalibration)
468 pStereoCalibration->Calculate3DPoint(
472 Vec2d vSigmaPointLeft, vSigmaPointRight, vTemp;
474 const float fSigmaPointFactor = 1.0f;
476 Math2d::MulVecScalar(
478 Math2d::AddVecVec(pMSERLeft->
vMean, vTemp, vSigmaPointLeft);
479 Math2d::MulVecScalar(
481 Math2d::AddVecVec(pMSERRight->
vMean, vTemp, vSigmaPointRight);
482 pStereoCalibration->Calculate3DPoint(
483 vSigmaPointLeft, vSigmaPointRight, pDescr3D->
vSigmaPoint1a,
false,
false);
485 Math2d::MulVecScalar(
487 Math2d::AddVecVec(pMSERLeft->
vMean, vTemp, vSigmaPointLeft);
488 Math2d::MulVecScalar(
490 Math2d::AddVecVec(pMSERRight->
vMean, vTemp, vSigmaPointRight);
491 pStereoCalibration->Calculate3DPoint(
492 vSigmaPointLeft, vSigmaPointRight, pDescr3D->
vSigmaPoint1b,
false,
false);
494 Math2d::MulVecScalar(
496 Math2d::AddVecVec(pMSERLeft->
vMean, vTemp, vSigmaPointLeft);
497 Math2d::MulVecScalar(
499 Math2d::AddVecVec(pMSERRight->
vMean, vTemp, vSigmaPointRight);
500 pStereoCalibration->Calculate3DPoint(
501 vSigmaPointLeft, vSigmaPointRight, pDescr3D->
vSigmaPoint2a,
false,
false);
503 Math2d::MulVecScalar(
505 Math2d::AddVecVec(pMSERLeft->
vMean, vTemp, vSigmaPointLeft);
506 Math2d::MulVecScalar(
508 Math2d::AddVecVec(pMSERRight->
vMean, vTemp, vSigmaPointRight);
509 pStereoCalibration->Calculate3DPoint(
510 vSigmaPointLeft, vSigmaPointRight, pDescr3D->
vSigmaPoint2b,
false,
false);
530 int nPixelIndex, nSaturationValue, nHistogramIndex;
532 int nSaturationSum = 0;
534 for (
int i = 0; i < (int)pDescriptor->
pPoints2D->size(); i++)
538 nSaturationValue = pHSVImage->pixels[nPixelIndex + 1];
539 nSaturationSum += nSaturationValue;
540 nHistogramIndex = pHSVImage->pixels[nPixelIndex] / nBucketSize;
541 fWeight = 1.0f - 1.0f / (1.0f + 0.0025f * (nSaturationValue * nSaturationValue));
563 const float fOneBySum = 1.0f / fSum;
589 Vec2d vTemp1, vTemp2;
590 const float fStdDevFactor = 2.5f;
591 const float fAdditionalPixels = 2.0f;
592 const float fRegionSize =
593 (fStdDevFactor * sqrtf(pDescriptor->
fEigenvalue1) + fAdditionalPixels) *
594 (fStdDevFactor * sqrtf(pDescriptor->
fEigenvalue2) + fAdditionalPixels);
606 (fStdDevFactor * sqrtf(pDescriptor->
fEigenvalue1) + fAdditionalPixels),
609 (fStdDevFactor * sqrtf(pDescriptor->
fEigenvalue2) + fAdditionalPixels),
611 Math2d::SubtractVecVec(pDescriptor->
vMean, vTemp1, pCorners[0]);
612 Math2d::SubtractVecVec(pCorners[0], vTemp2, pCorners[0]);
613 Math2d::AddVecVec(pDescriptor->
vMean, vTemp1, pCorners[1]);
614 Math2d::SubtractVecVec(pCorners[1], vTemp2, pCorners[1]);
615 Math2d::SubtractVecVec(pDescriptor->
vMean, vTemp1, pCorners[2]);
616 Math2d::AddVecVec(pCorners[2], vTemp2, pCorners[2]);
617 Math2d::AddVecVec(pDescriptor->
vMean, vTemp1, pCorners[3]);
618 Math2d::AddVecVec(pCorners[3], vTemp2, pCorners[3]);
622 Vec2d vUp, vLow, vLeft, vRight;
702 int nUp1, nUp2, nLow1, nLow2, nTemp;
704 if (pCorners[0].y < pCorners[1].y)
715 if (pCorners[2].y < pCorners[3].y)
726 if (pCorners[nUp1].y > pCorners[nUp2].y)
733 if (pCorners[nLow1].y < pCorners[nLow2].y)
740 Math2d::SetVec(vUp, pCorners[nUp1]);
741 Math2d::SetVec(vLow, pCorners[nLow1]);
743 if (pCorners[nUp2].x < pCorners[nLow2].x)
745 Math2d::SetVec(vLeft, pCorners[nUp2]);
746 Math2d::SetVec(vRight, pCorners[nLow2]);
750 Math2d::SetVec(vLeft, pCorners[nLow2]);
751 Math2d::SetVec(vRight, pCorners[nUp2]);
760 const CByteImage* pHSVImage,
762 const int nHistogramSize,
766 const int nBucketSize = (int)(ceil(256.0f / (
float)nHistogramSize));
767 int nPixelIndex, nSaturationValue, nHistogramIndex;
845 float fDeltaLeft, fDeltaRight;
847 const int nUp = (int)vUp.y;
848 const int nLow = (
int)vLow.y;
850 if (vLeft.y < vRight.y)
852 const int nMiddle1 = (int)vLeft.y;
853 const int nMiddle2 = (
int)vRight.y;
854 fDeltaLeft = (vLeft.x - vUp.x) / (vLeft.y - vUp.y);
855 fDeltaRight = (vRight.x - vUp.x) / (vRight.y - vUp.y);
857 for (
int i = nUp; i < nMiddle1; i++)
859 nLeft = (int)(vUp.x + (i - nUp) * fDeltaLeft);
860 nRight = (int)(vUp.x + (i - nUp) * fDeltaRight);
862 for (
int j = nLeft; j <= nRight; j++)
865 nSaturationValue = pHSVImage->pixels[nPixelIndex + 1];
866 nSaturationSum += nSaturationValue;
867 nHistogramIndex = pHSVImage->pixels[nPixelIndex] / nBucketSize;
868 fWeight = 1.0f - 1.0f / (1.0f + 0.0025f * (nSaturationValue * nSaturationValue));
869 pHistogram[nHistogramIndex] += 0.4f * fWeight;
870 pHistogram[(nHistogramIndex + nHistogramSize + 1) % nHistogramSize] +=
872 pHistogram[(nHistogramIndex + nHistogramSize - 1) % nHistogramSize] +=
874 pHistogram[(nHistogramIndex + nHistogramSize + 2) % nHistogramSize] +=
876 pHistogram[(nHistogramIndex + nHistogramSize - 2) % nHistogramSize] +=
881 fDeltaLeft = (vLow.x - vLeft.x) / (vLow.y - vLeft.y);
883 for (
int i = nMiddle1; i < nMiddle2; i++)
885 nLeft = (int)(vLeft.x + (i - nMiddle1) * fDeltaLeft);
886 nRight = (int)(vUp.x + (i - nUp) * fDeltaRight);
888 for (
int j = nLeft; j <= nRight; j++)
891 nSaturationValue = pHSVImage->pixels[nPixelIndex + 1];
892 nSaturationSum += nSaturationValue;
893 nHistogramIndex = pHSVImage->pixels[nPixelIndex] / nBucketSize;
894 fWeight = 1.0f - 1.0f / (1.0f + 0.0025f * (nSaturationValue * nSaturationValue));
895 pHistogram[nHistogramIndex] += 0.4f * fWeight;
896 pHistogram[(nHistogramIndex + nHistogramSize + 1) % nHistogramSize] +=
898 pHistogram[(nHistogramIndex + nHistogramSize - 1) % nHistogramSize] +=
900 pHistogram[(nHistogramIndex + nHistogramSize + 2) % nHistogramSize] +=
902 pHistogram[(nHistogramIndex + nHistogramSize - 2) % nHistogramSize] +=
907 fDeltaRight = (vLow.x - vRight.x) / (vLow.y - vRight.y);
909 for (
int i = nMiddle2; i < nLow; i++)
911 nLeft = (int)(vLeft.x + (i - nMiddle1) * fDeltaLeft);
912 nRight = (int)(vRight.x + (i - nMiddle2) * fDeltaRight);
914 for (
int j = nLeft; j <= nRight; j++)
917 nSaturationValue = pHSVImage->pixels[nPixelIndex + 1];
918 nSaturationSum += nSaturationValue;
919 nHistogramIndex = pHSVImage->pixels[nPixelIndex] / nBucketSize;
920 fWeight = 1.0f - 1.0f / (1.0f + 0.0025f * (nSaturationValue * nSaturationValue));
921 pHistogram[nHistogramIndex] += 0.4f * fWeight;
922 pHistogram[(nHistogramIndex + nHistogramSize + 1) % nHistogramSize] +=
924 pHistogram[(nHistogramIndex + nHistogramSize - 1) % nHistogramSize] +=
926 pHistogram[(nHistogramIndex + nHistogramSize + 2) % nHistogramSize] +=
928 pHistogram[(nHistogramIndex + nHistogramSize - 2) % nHistogramSize] +=
935 const int nMiddle1 = (int)vRight.y;
936 const int nMiddle2 = (
int)vLeft.y;
937 fDeltaLeft = (vLeft.x - vUp.x) / (vLeft.y - vUp.y);
938 fDeltaRight = (vRight.x - vUp.x) / (vRight.y - vUp.y);
940 for (
int i = nUp; i < nMiddle1; i++)
942 nLeft = (int)(vUp.x + (i - nUp) * fDeltaLeft);
943 nRight = (int)(vUp.x + (i - nUp) * fDeltaRight);
945 for (
int j = nLeft; j <= nRight; j++)
948 nSaturationValue = pHSVImage->pixels[nPixelIndex + 1];
949 nSaturationSum += nSaturationValue;
950 nHistogramIndex = pHSVImage->pixels[nPixelIndex] / nBucketSize;
951 fWeight = 1.0f - 1.0f / (1.0f + 0.0025f * (nSaturationValue * nSaturationValue));
952 pHistogram[nHistogramIndex] += 0.4f * fWeight;
953 pHistogram[(nHistogramIndex + nHistogramSize + 1) % nHistogramSize] +=
955 pHistogram[(nHistogramIndex + nHistogramSize - 1) % nHistogramSize] +=
957 pHistogram[(nHistogramIndex + nHistogramSize + 2) % nHistogramSize] +=
959 pHistogram[(nHistogramIndex + nHistogramSize - 2) % nHistogramSize] +=
964 fDeltaRight = (vLow.x - vRight.x) / (vLow.y - vRight.y);
966 for (
int i = nMiddle1; i < nMiddle2; i++)
968 nLeft = (int)(vUp.x + (i - nUp) * fDeltaLeft);
969 nRight = (int)(vRight.x + (i - nMiddle1) * fDeltaRight);
971 for (
int j = nLeft; j <= nRight; j++)
974 nSaturationValue = pHSVImage->pixels[nPixelIndex + 1];
975 nSaturationSum += nSaturationValue;
976 nHistogramIndex = pHSVImage->pixels[nPixelIndex] / nBucketSize;
977 fWeight = 1.0f - 1.0f / (1.0f + 0.0025f * (nSaturationValue * nSaturationValue));
978 pHistogram[nHistogramIndex] += 0.4f * fWeight;
979 pHistogram[(nHistogramIndex + nHistogramSize + 1) % nHistogramSize] +=
981 pHistogram[(nHistogramIndex + nHistogramSize - 1) % nHistogramSize] +=
983 pHistogram[(nHistogramIndex + nHistogramSize + 2) % nHistogramSize] +=
985 pHistogram[(nHistogramIndex + nHistogramSize - 2) % nHistogramSize] +=
990 fDeltaLeft = (vLow.x - vLeft.x) / (vLow.y - vLeft.y);
992 for (
int i = nMiddle2; i < nLow; i++)
994 nLeft = (int)(vLeft.x + (i - nMiddle2) * fDeltaLeft);
995 nRight = (int)(vRight.x + (i - nMiddle1) * fDeltaRight);
997 for (
int j = nLeft; j <= nRight; j++)
1000 nSaturationValue = pHSVImage->pixels[nPixelIndex + 1];
1001 nSaturationSum += nSaturationValue;
1002 nHistogramIndex = pHSVImage->pixels[nPixelIndex] / nBucketSize;
1003 fWeight = 1.0f - 1.0f / (1.0f + 0.0025f * (nSaturationValue * nSaturationValue));
1004 pHistogram[nHistogramIndex] += 0.4f * fWeight;
1005 pHistogram[(nHistogramIndex + nHistogramSize + 1) % nHistogramSize] +=
1007 pHistogram[(nHistogramIndex + nHistogramSize - 1) % nHistogramSize] +=
1009 pHistogram[(nHistogramIndex + nHistogramSize + 2) % nHistogramSize] +=
1011 pHistogram[(nHistogramIndex + nHistogramSize - 2) % nHistogramSize] +=
1021 for (
int i = 0; i < nHistogramSize; i++)
1023 fSum += pHistogram[i];
1028 const float fOneBySum = 1.0f / fSum;
1030 for (
int i = 0; i < nHistogramSize; i++)
1032 pHistogram[i] *= fOneBySum;
1037 const float fDummy = 1.0f / (
float)nHistogramSize;
1039 for (
int i = 0; i < nHistogramSize; i++)
1041 pHistogram[i] = fDummy;