|
IVT
|
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) 2013 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: StereoVision.cpp 00037 // Author: Pedram Azad 00038 // Date: 2005 00039 // **************************************************************************** 00040 00041 00042 // **************************************************************************** 00043 // Includes 00044 // **************************************************************************** 00045 00046 #include <new> // for explicitly using correct new/delete operators on VC DSPs 00047 00048 #include "StereoVision.h" 00049 00050 #include "ImageProcessor.h" 00051 #include "ByteImage.h" 00052 #include "Calibration/StereoCalibration.h" 00053 #include "Math/FloatMatrix.h" 00054 #include "Helpers/OptimizedFunctions.h" 00055 #include "Helpers/helpers.h" 00056 00057 #include <stdio.h> 00058 #include <stdlib.h> 00059 #include <string.h> 00060 #include <math.h> 00061 #include <limits.h> 00062 00063 00064 00065 // ***************************************************************** 00066 // Constructor / Destructor 00067 // ***************************************************************** 00068 00069 CStereoVision::CStereoVision() 00070 { 00071 } 00072 00073 CStereoVision::~CStereoVision() 00074 { 00075 } 00076 00077 00078 // **************************************************************************** 00079 // Methods 00080 // **************************************************************************** 00081 00082 bool CStereoVision::Process(const CByteImage *pLeftImage, const CByteImage *pRightImage, CByteImage *pDepthImage, 00083 int nWindowSize, int d1, int d2, int d_step, int nErrorThreshold) 00084 { 00085 if (pLeftImage->width != pRightImage->width || pLeftImage->height != pRightImage->height || 00086 pLeftImage->type != CByteImage::eGrayScale || pRightImage->type != CByteImage::eGrayScale || 00087 pDepthImage->width != pLeftImage->width || pDepthImage->height != pLeftImage->height || 00088 pDepthImage->type != CByteImage::eGrayScale) 00089 { 00090 printf("error: input images and/or output image do not match for CStereoVision::ProcessSSD\n"); 00091 return false; 00092 } 00093 00094 if (d_step == 0) 00095 { 00096 printf("error: d_step must not be zero for CStereoVision::ProcessSSD\n"); 00097 return false; 00098 } 00099 00100 if (d_step > 0 && d1 >= d2) 00101 { 00102 printf("error: if d_step > 0 then d2 must be greater than d1 for CStereoVision::ProcessSSD\n"); 00103 return false; 00104 } 00105 00106 if (d_step < 0 && d1 <= d2) 00107 { 00108 printf("error: if d_step < 0 then d1 must be greater than d2 for CStereoVision::ProcessSSD\n"); 00109 return false; 00110 } 00111 00112 ImageProcessor::Zero(pDepthImage); 00113 00114 nErrorThreshold *= nWindowSize * nWindowSize; 00115 00116 // adjust d2 so we can use != instead of <= or >= 00117 int d; 00118 if (d_step > 0) 00119 for (d = d1; d <= d2; d += d_step); 00120 else if (d_step < 0) 00121 for (d = d1; d >= d2; d += d_step); 00122 d2 = d + d_step; 00123 00124 const int width = pLeftImage->width; 00125 const int height = pLeftImage->height; 00126 00127 const unsigned char *pLeftImageData = pLeftImage->pixels; 00128 const unsigned char *pRightImageData = pRightImage->pixels; 00129 unsigned char *pDepthImageData = pDepthImage->pixels + (nWindowSize / 2) * (width + 1); 00130 00131 const int max_i = height - nWindowSize + 1; 00132 const int max_j = width - nWindowSize + 1; 00133 00134 const int start_j = MY_MAX(nWindowSize, d2); 00135 const int diff = width - (max_j - start_j); 00136 const int diff2 = width - nWindowSize; 00137 00138 for (int i = 0, offset = start_j; i < max_i; i++, offset += diff) 00139 { 00140 for (int j = start_j; j < max_j; j++, offset++) 00141 { 00142 int best_error = INT_MAX; 00143 int best_d = 0; 00144 00145 // find correlation 00146 for (int d = d1; d != d2; d += d_step) 00147 { 00148 int error = 0; 00149 00150 for (int y = 0, offset2 = offset; y < nWindowSize; y++, offset2 += diff2) 00151 for (int x = 0; x < nWindowSize; x++, offset2++) 00152 error += abs(pLeftImageData[offset2] - pRightImageData[offset2 - d]); 00153 00154 if (error < best_error) 00155 { 00156 best_error = error; 00157 best_d = d; 00158 } 00159 } 00160 00161 pDepthImageData[i * width + j] = best_error < nErrorThreshold ? best_d : 0; 00162 } 00163 } 00164 00165 return true; 00166 } 00167 00168 00169 bool CStereoVision::ProcessFast(const CByteImage *pLeftImage, const CByteImage *pRightImage, CByteImage *pDepthImage, 00170 int nWindowSize, int d1, int d2, int d_step, int nErrorThreshold) 00171 { 00172 if (pLeftImage->width != pRightImage->width || pLeftImage->height != pRightImage->height || 00173 pLeftImage->type != CByteImage::eGrayScale || pRightImage->type != CByteImage::eGrayScale || 00174 pDepthImage->width != pLeftImage->width || pDepthImage->height != pLeftImage->height || 00175 pDepthImage->type != CByteImage::eGrayScale) 00176 { 00177 printf("error: intput images and output image do not match in CStereoVision::ProcessFast\n"); 00178 return false; 00179 } 00180 00181 if (d_step == 0) 00182 { 00183 printf("error: d_step must not be zero for CStereoVision::ProcessFast\n"); 00184 return false; 00185 } 00186 00187 if (d_step > 0 && d1 >= d2) 00188 { 00189 printf("error: if d_step > 0 then d2 must be greater than d1 for CStereoVision::ProcessFast\n"); 00190 return false; 00191 } 00192 00193 if (d_step < 0 && d1 <= d2) 00194 { 00195 printf("error: if d_step < 0 then d1 must be greater than d2 for CStereoVision::ProcessFast\n"); 00196 return false; 00197 } 00198 00199 //OPTIMIZED_FUNCTION_HEADER_8(StereoVision, pLeftImage, pRightImage, pDepthImage, nWindowSize, d1, d2, d_step, nErrorThreshold) 00200 00201 _ProcessFast(pLeftImage, pRightImage, pDepthImage, nWindowSize, d1, d2, d_step, nErrorThreshold); 00202 00203 //OPTIMIZED_FUNCTION_FOOTER 00204 00205 return true; 00206 } 00207 00208 00209 void CStereoVision::_ProcessFast(const CByteImage *pLeftImage, const CByteImage *pRightImage, CByteImage *pDepthImage, 00210 int nWindowSize, int d1, int d2, int d_step, int nErrorThreshold) 00211 { 00212 ImageProcessor::Zero(pDepthImage); 00213 00214 nErrorThreshold *= nWindowSize * nWindowSize; 00215 00216 // adjust d2 so we can use != instead of <= or >= 00217 int d; 00218 if (d_step > 0) 00219 for (d = d1; d <= d2; d += d_step); 00220 else if (d_step < 0) 00221 for (d = d1; d >= d2; d += d_step); 00222 d2 = d + d_step; 00223 00224 const int width = pLeftImage->width; 00225 const int height = pLeftImage->height; 00226 const int nPixels = width * height; 00227 00228 // allocate memory 00229 int *H_SUM = new int[nWindowSize * width]; 00230 int *V_SUM = new int[width]; 00231 int *SAD = new int[width]; 00232 int *MIN_SSAD = new int[width * height]; 00233 00234 for (int i = 0; i < nPixels; i++) 00235 MIN_SSAD[i] = nErrorThreshold; 00236 00237 const int window_offset = - (nWindowSize / 2) * (width + 1); 00238 const int start_c = MY_MAX(nWindowSize, d2) + nWindowSize; 00239 00240 const unsigned char *pLeftImageData = pLeftImage->pixels; 00241 const unsigned char *pRightImageData = pRightImage->pixels; 00242 unsigned char *pDepthImageData = pDepthImage->pixels + window_offset; 00243 00244 // run correlation algorithm 00245 for (d = d1; d != d2; d += d_step) 00246 { 00247 int c, r; 00248 00249 // initialize 00250 for (r = 0; r < nWindowSize; r++) 00251 { 00252 const unsigned char *pLeftImageData_helper = pLeftImageData + r * width; 00253 const unsigned char *pRightImageData_helper = pRightImageData + r * width - d; 00254 00255 H_SUM[r * width + start_c - 1] = 0; 00256 00257 for (c = start_c - nWindowSize; c < start_c; c++) 00258 { 00259 SAD[c] = abs(pLeftImageData_helper[c] - pRightImageData_helper[c]); 00260 H_SUM[r * width + start_c - 1] += SAD[c]; 00261 } 00262 00263 for (c = start_c; c < width; c++) 00264 { 00265 SAD[c] = abs(pLeftImageData_helper[c] - pRightImageData_helper[c]); 00266 H_SUM[r * width + c] = H_SUM[r * width + c - 1] + SAD[c] - SAD[c - nWindowSize]; 00267 } 00268 } 00269 00270 int *pMinHelper = MIN_SSAD + (nWindowSize - 1) * width; // for topmost_row 00271 unsigned char *pDepthHelper = pDepthImageData + (nWindowSize - 1) * width; // for topmost_row 00272 for (c = start_c - 1; c < width; c++) 00273 { 00274 V_SUM[c] = 0; 00275 for (r = 0; r < nWindowSize; r++) 00276 V_SUM[c] += H_SUM[r * width + c]; 00277 00278 // required for writing topmost row 00279 // <topmost_row> 00280 if (V_SUM[c] < pMinHelper[c]) 00281 { 00282 pMinHelper[c] = V_SUM[c]; 00283 pDepthHelper[c] = abs(d); 00284 } 00285 // </topmost_row> 00286 } 00287 00288 // go 00289 for (r = nWindowSize; r < height; r++) 00290 { 00291 const unsigned char *pLeftImageData_helper = pLeftImageData + r * width; 00292 const unsigned char *pRightImageData_helper = pRightImageData + r * width - d; 00293 00294 int *hsum_helper = H_SUM + (r % nWindowSize) * width; 00295 int *pMinHelper = MIN_SSAD + r * width; 00296 unsigned char *pDepthHelper = pDepthImageData + r * width; 00297 00298 const int save = hsum_helper[start_c - 1]; // for leftmost_column 00299 hsum_helper[start_c - 1] = 0; 00300 for (c = start_c - nWindowSize; c < start_c; c++) 00301 { 00302 SAD[c] = abs(pLeftImageData_helper[c] - pRightImageData_helper[c]); 00303 hsum_helper[start_c - 1] += SAD[c]; 00304 } 00305 00306 // required for writing leftmost column 00307 // <leftmost_column> 00308 const int result = V_SUM[start_c - 1] = V_SUM[start_c - 1] + hsum_helper[start_c - 1] - save; 00309 if (result < pMinHelper[start_c - 1]) 00310 { 00311 pMinHelper[start_c - 1] = result; 00312 pDepthHelper[start_c - 1] = abs(d); 00313 } 00314 // </leftmost_column> 00315 00316 // core loop 00317 for (c = start_c; c < width; c++) 00318 { 00319 SAD[c] = abs(pLeftImageData_helper[c] - pRightImageData_helper[c]); 00320 00321 const int save = hsum_helper[c]; 00322 hsum_helper[c] = hsum_helper[c - 1] + SAD[c] - SAD[c - nWindowSize]; 00323 const int result = V_SUM[c] = V_SUM[c] + hsum_helper[c] - save; 00324 00325 if (result < pMinHelper[c]) 00326 { 00327 pMinHelper[c] = result; 00328 pDepthHelper[c] = abs(d); 00329 } 00330 } 00331 } 00332 } 00333 00334 // free memory 00335 delete [] H_SUM; 00336 delete [] V_SUM; 00337 delete [] SAD; 00338 delete [] MIN_SSAD; 00339 }