StereoMatcher.cpp
Go to the documentation of this file.
00001 // ****************************************************************************
00002 // This file is part of the Integrating Vision Toolkit (IVT).
00003 //
00004 // The IVT is maintained by the Karlsruhe Institute of Technology (KIT)
00005 // (www.kit.edu) in cooperation with the company Keyetech (www.keyetech.de).
00006 //
00007 // Copyright (C) 2014 Karlsruhe Institute of Technology (KIT).
00008 // All rights reserved.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are met:
00012 //
00013 // 1. Redistributions of source code must retain the above copyright
00014 //    notice, this list of conditions and the following disclaimer.
00015 //
00016 // 2. Redistributions in binary form must reproduce the above copyright
00017 //    notice, this list of conditions and the following disclaimer in the
00018 //    documentation and/or other materials provided with the distribution.
00019 //
00020 // 3. Neither the name of the KIT nor the names of its contributors may be
00021 //    used to endorse or promote products derived from this software
00022 //    without specific prior written permission.
00023 //
00024 // THIS SOFTWARE IS PROVIDED BY THE KIT AND CONTRIBUTORS “AS IS” AND ANY
00025 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00026 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00027 // DISCLAIMED. IN NO EVENT SHALL THE KIT OR CONTRIBUTORS BE LIABLE FOR ANY
00028 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00029 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00031 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00033 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034 // ****************************************************************************
00035 // ****************************************************************************
00036 // Filename:  StereoMatcher.cpp
00037 // Author:    Pedram Azad
00038 // Date:      12.03.2007
00039 // ****************************************************************************
00040 
00041 
00042 // ****************************************************************************
00043 // Includes
00044 // ****************************************************************************
00045 
00046 #include <new> // for explicitly using correct new/delete operators on VC DSPs
00047 
00048 #include "StereoMatcher.h"
00049 
00050 #include "Image/ByteImage.h"
00051 #include "Calibration/StereoCalibration.h"
00052 #include "Calibration/Calibration.h"
00053 #include "Math/Math2d.h"
00054 #include "Math/Math3d.h"
00055 
00056 #include <stdlib.h>
00057 #include <math.h>
00058 #include <stdio.h>
00059 #include <float.h>
00060 
00061 
00062 
00063 // ****************************************************************************
00064 // Constructor / Destructor
00065 // ****************************************************************************
00066 
00067 CStereoMatcher::CStereoMatcher()
00068 {
00069         m_pStereoCalibration = new CStereoCalibration();
00070         m_bOwnStereoCalibrationObject = true;
00071 }
00072 
00073 CStereoMatcher::~CStereoMatcher()
00074 {
00075         if (m_bOwnStereoCalibrationObject)
00076                 delete m_pStereoCalibration;
00077 }
00078 
00079 
00080 // ****************************************************************************
00081 // Methods
00082 // ****************************************************************************
00083 
00084 bool CStereoMatcher::LoadCameraParameters(const char *pFileName)
00085 {
00086         if (!m_bOwnStereoCalibrationObject)
00087                 m_pStereoCalibration = new CStereoCalibration();
00088         
00089         return m_pStereoCalibration->LoadCameraParameters(pFileName);
00090 }
00091 
00092 void CStereoMatcher::InitCameraParameters(CStereoCalibration *pStereoCalibration, bool bCloneCalibration)
00093 {
00094         if (bCloneCalibration)
00095         {
00096                 if (!m_bOwnStereoCalibrationObject)
00097                         m_pStereoCalibration = new CStereoCalibration();
00098                 
00099                 m_pStereoCalibration->Set(*pStereoCalibration);
00100                 m_bOwnStereoCalibrationObject = true;
00101         }
00102         else
00103         {
00104                 if (m_bOwnStereoCalibrationObject)
00105                         delete m_pStereoCalibration;
00106                 
00107                 m_pStereoCalibration = pStereoCalibration;
00108                 m_bOwnStereoCalibrationObject = false;
00109         }
00110 }
00111 
00112 int CStereoMatcher::GetDisparityEstimate(const float z)
00113 {
00114         const Vec3d z_vector = { 0, 0, z };
00115         Vec3d p;
00116         m_pStereoCalibration->GetLeftCalibration()->CameraToWorldCoordinates(z_vector, p);
00117 
00118         Vec2d left, right;
00119         m_pStereoCalibration->GetLeftCalibration()->WorldToImageCoordinates(p, left, false);
00120         m_pStereoCalibration->GetRightCalibration()->WorldToImageCoordinates(p, right, false);
00121         
00122         return int(fabsf(left.x - right.x));
00123 }
00124 
00125 int CStereoMatcher::Match(const CByteImage *pLeftImage, const CByteImage *pRightImage, int x, int y, int nWindowSize,
00126         int d1, int d2, Vec2d &result, Vec3d &result_3d, float fThreshold, bool bInputImagesAreUndistorted)
00127 {
00128         if (pLeftImage->width != pRightImage->width || pLeftImage->height != pRightImage->height ||
00129                 pLeftImage->type != CByteImage::eGrayScale || pRightImage->type != CByteImage::eGrayScale)
00130         {
00131                 printf("error: input images do not match for CStereoMatcher::Match\n");
00132                 return -100000;
00133         }
00134 
00135         float *values_ = new float[4 * pLeftImage->width];
00136         float *values = values_ + 2 * pLeftImage->width;
00137         
00138         int best_d = SingleZNCC(pLeftImage, pRightImage, x, y, nWindowSize, d1 - 1, d2 + 1, values);
00139         
00140         if (best_d > -100000 && best_d >= d1 && best_d <= d2 && values[best_d] > fThreshold)
00141         {
00142                 const float y0 = values[best_d - 1];
00143                 const float y1 = values[best_d];
00144                 const float y2 = values[best_d + 1];
00145                 const float xmin = (y0 - y2) / (2.0f * (y0 - 2.0f * y1 + y2));
00146                 const float disparity = fabsf(xmin) < 0.5f ? best_d + xmin : best_d;
00147                 
00148                 float m, c;
00149                 const Vec2d point_left = { float(x), float(y) };
00150                 m_pStereoCalibration->CalculateEpipolarLineInRightImage(point_left, m, c);
00151                 
00152                 result.x = x - disparity;
00153                 result.y = m * (x - disparity) + c;
00154                 
00155                 m_pStereoCalibration->Calculate3DPoint(point_left, result, result_3d, false, !bInputImagesAreUndistorted);
00156         }
00157         else
00158         {
00159                 // adjust return value if threshold constraint was not met
00160                 if (best_d > -100000 && best_d >= d1 && best_d <= d2)
00161                         best_d = -100003;
00162         }
00163         
00164         delete [] values_;
00165         
00166         return best_d;
00167 }
00168 
00169 int CStereoMatcher::MatchZSAD(const CByteImage *pLeftImage, const CByteImage *pRightImage, int x, int y, int nWindowSize,
00170         int d1, int d2, Vec2d &result, Vec3d &result_3d, float fThreshold, bool bInputImagesAreUndistorted)
00171 {
00172         if (pLeftImage->width != pRightImage->width || pLeftImage->height != pRightImage->height ||
00173                 pLeftImage->type != CByteImage::eGrayScale || pRightImage->type != CByteImage::eGrayScale)
00174         {
00175                 printf("error: input images do not match for CStereoMatcher::MatchSAD\n");
00176                 return -100000;
00177         }
00178 
00179         float *values_ = new float[4 * pLeftImage->width];
00180         float *values = values_ + 2 * pLeftImage->width;
00181         
00182         int best_d = SingleZSAD(pLeftImage, pRightImage, x, y, nWindowSize, d1 - 1, d2 + 1, values);
00183         
00184         if (best_d > -100000 && best_d >= d1 && best_d <= d2 && 255.0f * values[best_d] < fThreshold)
00185         {
00186                 const float y0 = values[best_d - 1];
00187                 const float y1 = values[best_d];
00188                 const float y2 = values[best_d + 1];
00189                 const float xmin = (y0 - y2) / (2.0f * (y0 - 2.0f * y1 + y2));
00190                 const float disparity = fabsf(xmin) < 0.5f ? best_d + xmin : best_d;
00191                 
00192                 float m, c;
00193                 const Vec2d point_left = { float(x), float(y) };
00194                 m_pStereoCalibration->CalculateEpipolarLineInRightImage(point_left, m, c);
00195                 
00196                 result.x = x - disparity;
00197                 result.y = m * (x - disparity) + c;
00198                 
00199                 m_pStereoCalibration->Calculate3DPoint(point_left, result, result_3d, false, !bInputImagesAreUndistorted);
00200         }
00201         else
00202         {
00203                 // adjust return value if threshold constraint was not met
00204                 if (best_d > -100000 && best_d >= d1 && best_d <= d2)
00205                         best_d = -100003;
00206         }
00207         
00208         delete [] values_;
00209         
00210         return best_d;
00211 }
00212 
00213 
00214 int CStereoMatcher::SingleZNCC(const CByteImage *pInputImageLeft, const CByteImage *pInputImageRight, int x, int y, int nWindowSize, int d1, int d2, float *values)
00215 {
00216         const int width = pInputImageLeft->width;
00217         const int height = pInputImageLeft->height;
00218         const int w2 = nWindowSize / 2;
00219         
00220         if (x < w2 || x >= width - w2 || y < w2 || y >= height - w2)
00221                 return -100001;
00222         
00223         const unsigned char *input_left = pInputImageLeft->pixels;
00224         const unsigned char *input_right = pInputImageRight->pixels;
00225         const int nVectorLength = nWindowSize * nWindowSize;
00226         
00227         float *vector1 = new float[nVectorLength];
00228         float *vector2 = new float[nVectorLength];
00229         
00230         const int offset = (y - w2) * width + (x - w2);
00231         const int diff = width - nWindowSize;
00232         const Vec2d camera_point = { float(x), float(y) };
00233         
00234         // calculate mean value
00235         float mean = 0.0f;
00236         for (int yy = 0, offset2 = offset, offset3 = 0; yy < nWindowSize; yy++, offset2 += diff)
00237                 for (int x = 0; x < nWindowSize; x++, offset2++, offset3++)
00238                 {
00239                         vector1[offset3] = input_left[offset2];
00240                         mean += vector1[offset3];
00241                 }
00242         mean /= nVectorLength;
00243         
00244         // apply additive and muliplicative normalization
00245         int k;
00246         float factor = 0.0f;
00247         for (k = 0; k < nVectorLength; k++)
00248         {
00249                 vector1[k] -= mean;
00250                 factor += vector1[k] * vector1[k];
00251         }
00252         
00253         if (factor < 60 * nVectorLength)
00254         {
00255                 delete [] vector1;
00256                 delete [] vector2;
00257                 return -100002;
00258         }
00259         
00260         factor = 1.0f / sqrtf(factor);
00261         for (k = 0; k < nVectorLength; k++)
00262                 vector1[k] *= factor;
00263         
00264         float best_value = -FLT_MAX;
00265         int d, best_d = -100004;
00266 
00267         const int max_d = d2 < x ? d2 : x;
00268         
00269         float m, c;
00270         m_pStereoCalibration->CalculateEpipolarLineInRightImage(camera_point, m, c);
00271         
00272         // determine correspondence
00273         for (d = d1; d <= max_d; d++)
00274         {
00275                 const int xx = x - d; // x-coordinate of center of window in right image
00276                 const int yy = int(m * xx + c + 0.5f); // y-coordinate of center of window in right image
00277                 
00278                 if (xx < w2 || xx >= width - w2 || yy < w2 || yy >= height - w2)
00279                         continue;
00280                 
00281                 const int offset_right = (yy - w2) * width + (xx - w2); // offset of top left corner of window in right image
00282                 
00283                 // determine mean value
00284                 float mean = 0.0f;
00285                 for (int y = 0, offset2 = offset_right, offset3 = 0; y < nWindowSize; y++, offset2 += diff)
00286                         for (int x = 0; x < nWindowSize; x++, offset2++, offset3++)
00287                         {
00288                                 vector2[offset3] = input_right[offset2];
00289                                 mean += vector2[offset3];
00290                                 
00291                         }
00292                 mean /= nVectorLength;
00293                 
00294                 // apply additive and multiplicative normalization
00295                 float factor = 0.0f;
00296                 for (k = 0; k < nVectorLength; k++)
00297                 {
00298                         vector2[k] -= mean;
00299                         factor += vector2[k] * vector2[k];
00300                 }
00301 
00302                 if (factor < 60 * nVectorLength)
00303                         continue;
00304 
00305                 factor = 1.0f / sqrtf(factor);
00306                 for (k = 0; k < nVectorLength; k++)
00307                         vector2[k] *= factor;
00308                 
00309                 float value = 0.0f;
00310                 for (k = 0; k < nVectorLength; k++)
00311                         value += vector1[k] * vector2[k];
00312 
00313                 // save correlation results for subpixel calculations
00314                 values[d] = value;
00315                 
00316                 // determine maximum correlation value
00317                 if (value > best_value)
00318                 {
00319                         best_value = value;
00320                         best_d = d;
00321                 }
00322         }
00323         
00324         delete [] vector1;
00325         delete [] vector2;
00326         
00327         return best_d;
00328 }
00329 
00330 int CStereoMatcher::SingleZSAD(const CByteImage *pInputImageLeft, const CByteImage *pInputImageRight, int x, int y, int nWindowSize, int d1, int d2, float *values)
00331 {
00332         const int width = pInputImageLeft->width;
00333         const int height = pInputImageLeft->height;
00334         const int w2 = nWindowSize / 2;
00335         
00336         if (x < w2 || x >= width - w2 || y < w2 || y >= height - w2)
00337                 return -100001;
00338         
00339         const unsigned char *input_left = pInputImageLeft->pixels;
00340         const unsigned char *input_right = pInputImageRight->pixels;
00341         const int nVectorLength = nWindowSize * nWindowSize;
00342         
00343         int *vector1 = new int[nVectorLength];
00344         int *vector2 = new int[nVectorLength];
00345         
00346         const int offset = (y - w2) * width + (x - w2);
00347         const int diff = width - nWindowSize;
00348         const Vec2d camera_point = { float(x), float(y) };
00349         
00350         // calculate mean value
00351         int mean1 = 0;
00352         for (int yy = 0, offset2 = offset, offset3 = 0; yy < nWindowSize; yy++, offset2 += diff)
00353                 for (int x = 0; x < nWindowSize; x++, offset2++, offset3++)
00354                 {
00355                         vector1[offset3] = input_left[offset2];
00356                         mean1 += vector1[offset3];
00357                 }
00358         mean1 /= nVectorLength;
00359         
00360         // apply additive and muliplicative normalization
00361         float best_value = FLT_MAX;
00362         int d, best_d = -100004;
00363 
00364         const int max_d = d2 < x ? d2 : x;
00365         
00366         float m, c;
00367         m_pStereoCalibration->CalculateEpipolarLineInRightImage(camera_point, m, c);
00368         
00369         // determine correspondence
00370         for (d = d1; d <= max_d; d++)
00371         {
00372                 const int xx = x - d; // x-coordinate of center of window in right image
00373                 const int yy = int(m * xx + c + 0.5f); // y-coordinate of center of window in right image
00374                 
00375                 if (xx < w2 || xx >= width - w2 || yy < w2 || yy >= height - w2)
00376                         continue;
00377                 
00378                 const int offset_right = (yy - w2) * width + (xx - w2); // offset of top left corner of window in right image
00379                 
00380                 // determine mean value
00381                 int mean2 = 0;
00382                 for (int y = 0, offset2 = offset_right, offset3 = 0; y < nWindowSize; y++, offset2 += diff)
00383                         for (int x = 0; x < nWindowSize; x++, offset2++, offset3++)
00384                         {
00385                                 vector2[offset3] = input_right[offset2];
00386                                 mean2 += vector2[offset3];
00387                                 
00388                         }
00389                 mean2 /= nVectorLength;
00390                 
00391                 int value_int = 0;
00392                 for (int k = 0; k < nVectorLength; k++)
00393                         value_int += abs((vector1[k] - mean1) - (vector2[k] - mean2));
00394                 const float value = float(value_int) / (nVectorLength * 255.0f);
00395 
00396                 // save correlation results for subpixel calculations
00397                 values[d] = value;
00398                 
00399                 // determine maximum correlation value
00400                 if (value < best_value)
00401                 {
00402                         best_value = value;
00403                         best_d = d;
00404                 }
00405         }
00406         
00407         delete [] vector1;
00408         delete [] vector2;
00409         
00410         return best_d;
00411 }


asr_ivt
Author(s): Allgeyer Tobias, Hutmacher Robin, Kleinert Daniel, Meißner Pascal, Scholz Jonas, Stöckle Patrick
autogenerated on Thu Jun 6 2019 21:46:58