|
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: ObjectFinderStereo.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 "ObjectFinderStereo.h" 00049 00050 #include "ObjectFinder.h" 00051 #include "Calibration/StereoCalibration.h" 00052 #include "Interfaces/ObjectClassifierInterface.h" 00053 #include "Interfaces/ObjectEntryFilterInterface.h" 00054 #include "Image/ByteImage.h" 00055 00056 #include <stdio.h> 00057 #include <math.h> 00058 00059 00060 00061 // **************************************************************************** 00062 // Constructor / Destructor 00063 // **************************************************************************** 00064 00065 CObjectFinderStereo::CObjectFinderStereo() 00066 { 00067 m_pObjectFinderLeft = new CObjectFinder(); 00068 m_pObjectFinderRight = new CObjectFinder(); 00069 00070 m_pStereoCalibration = new CStereoCalibration(); 00071 m_bOwnCalibration = true; 00072 00073 m_pObjectEntryFilter = 0; 00074 } 00075 00076 CObjectFinderStereo::~CObjectFinderStereo() 00077 { 00078 if(m_bOwnCalibration) 00079 delete m_pStereoCalibration; 00080 00081 delete m_pObjectFinderLeft; 00082 delete m_pObjectFinderRight; 00083 } 00084 00085 00086 // **************************************************************************** 00087 // Methods 00088 // **************************************************************************** 00089 00090 bool CObjectFinderStereo::Init(const char *pCameraParameterFileName) 00091 { 00092 if(!m_bOwnCalibration) 00093 m_pStereoCalibration = new CStereoCalibration(); 00094 00095 m_bOwnCalibration = true; 00096 00097 return m_pStereoCalibration->LoadCameraParameters(pCameraParameterFileName); 00098 } 00099 00100 void CObjectFinderStereo::Init(CStereoCalibration* pStereoCalibration) 00101 { 00102 if (m_bOwnCalibration) 00103 delete m_pStereoCalibration; 00104 00105 m_bOwnCalibration = false; 00106 00107 m_pStereoCalibration = pStereoCalibration; 00108 } 00109 00110 void CObjectFinderStereo::SetColorParameterSet(const CColorParameterSet *pColorParameterSet) 00111 { 00112 m_pObjectFinderLeft->SetColorParameterSet(pColorParameterSet); 00113 m_pObjectFinderRight->SetColorParameterSet(pColorParameterSet); 00114 } 00115 00116 void CObjectFinderStereo::SetRegionFilter(CRegionFilterInterface *pRegionFilter) 00117 { 00118 m_pObjectFinderLeft->SetRegionFilter(pRegionFilter); 00119 m_pObjectFinderRight->SetRegionFilter(pRegionFilter); 00120 } 00121 00122 CByteImage* CObjectFinderStereo::GetLeftSegmentationResult() 00123 { 00124 return m_pObjectFinderLeft->GetSegmentationResult(); 00125 } 00126 00127 CByteImage* CObjectFinderStereo::GetRightSegmentationResult() 00128 { 00129 return m_pObjectFinderRight->GetSegmentationResult(); 00130 } 00131 00132 00133 void CObjectFinderStereo::PrepareImages(const CByteImage * const *ppImages, float fROIFactor, bool bCalculateHSVImage) 00134 { 00135 m_pObjectFinderLeft->PrepareImages(ppImages[0], fROIFactor, bCalculateHSVImage); 00136 m_pObjectFinderRight->PrepareImages(ppImages[1], fROIFactor, bCalculateHSVImage); 00137 } 00138 00139 int CObjectFinderStereo::Finalize(float fMinZDistance, float fMaxZDistance, bool bInputImagesAreRectified, ObjectColor finalizeColor, float fMaxYDiff, bool bUseDistortionParameters) 00140 { 00141 m_pObjectFinderLeft->Finalize(); 00142 m_pObjectFinderRight->Finalize(); 00143 00144 const int nRet = DetermineMatches(m_pObjectFinderLeft->m_objectList, m_pObjectFinderRight->m_objectList, fMinZDistance, fMaxZDistance, bInputImagesAreRectified, bUseDistortionParameters, finalizeColor, fMaxYDiff); 00145 00146 // update object lists of (2D) CObjectFinder objects 00147 UpdateObjectFinderLists(m_pObjectFinderLeft->m_objectList, m_pObjectFinderRight->m_objectList); 00148 00149 return nRet; 00150 } 00151 00152 00153 void CObjectFinderStereo::FindObjects(const CByteImage * const *ppImages, CByteImage **ppResultImages, ObjectColor color, int nMinPointsPerRegion, bool bShowSegmentedImage) 00154 { 00155 CByteImage *pResultImageLeft = ppResultImages ? ppResultImages[0] : 0; 00156 CByteImage *pResultImageRight = ppResultImages ? ppResultImages[1] : 0; 00157 00158 m_pObjectFinderLeft->FindObjects(ppImages[0], pResultImageLeft, color, nMinPointsPerRegion, bShowSegmentedImage); 00159 m_pObjectFinderRight->FindObjects(ppImages[1], pResultImageRight, color, nMinPointsPerRegion, bShowSegmentedImage); 00160 } 00161 00162 void CObjectFinderStereo::FindObjects(const CByteImage * const *ppImages, CByteImage **ppResultImages, ObjectColor color, int nMinPointsPerRegion, CByteImage **ppSegmentedResultImages) 00163 { 00164 CByteImage *pResultImageLeft = ppResultImages ? ppResultImages[0] : 0; 00165 CByteImage *pResultImageRight = ppResultImages ? ppResultImages[1] : 0; 00166 00167 m_pObjectFinderLeft->FindObjects(ppImages[0], pResultImageLeft, color, nMinPointsPerRegion, ppSegmentedResultImages[0]); 00168 m_pObjectFinderRight->FindObjects(ppImages[1], pResultImageRight, color, nMinPointsPerRegion, ppSegmentedResultImages[1]); 00169 } 00170 00171 void CObjectFinderStereo::FindObjects(const CByteImage * const *ppImages, CByteImage **ppResultImages, ObjectColor colorName, int hue, int hue_tol, int min_sat, int max_sat, int min_v, int max_v, int nMinPointsPerRegion, bool bShowSegmentedImage) 00172 { 00173 CByteImage *pResultImageLeft = ppResultImages ? ppResultImages[0] : 0; 00174 CByteImage *pResultImageRight = ppResultImages ? ppResultImages[1] : 0; 00175 00176 m_pObjectFinderLeft->FindObjects(ppImages[0], pResultImageLeft, colorName, hue, hue_tol, min_sat, max_sat, min_v, max_v, nMinPointsPerRegion, bShowSegmentedImage); 00177 m_pObjectFinderRight->FindObjects(ppImages[1], pResultImageRight, colorName, hue, hue_tol, min_sat, max_sat, min_v, max_v, nMinPointsPerRegion, bShowSegmentedImage); 00178 } 00179 00180 void CObjectFinderStereo::FindObjectsInSegmentedImage(const CByteImage * const *ppImages, CByteImage **ppResultImages, ObjectColor color, int nMinPointsPerRegion, bool bShowSegmentedImage) 00181 { 00182 CByteImage *pResultImageLeft = ppResultImages ? ppResultImages[0] : 0; 00183 CByteImage *pResultImageRight = ppResultImages ? ppResultImages[1] : 0; 00184 00185 m_pObjectFinderLeft->FindObjectsInSegmentedImage(ppImages[0], pResultImageLeft, color, nMinPointsPerRegion, bShowSegmentedImage); 00186 m_pObjectFinderRight->FindObjectsInSegmentedImage(ppImages[1], pResultImageRight, color, nMinPointsPerRegion, bShowSegmentedImage); 00187 } 00188 00189 00190 int CObjectFinderStereo::DetermineMatches(Object2DList &resultListLeft, Object2DList &resultListRight, float fMinZDistance, float fMaxZDistance, bool bInputImagesAreRectified, bool bUseDistortionParameters, ObjectColor finalizeColor, float fMaxEpipolarDistance) 00191 { 00192 // create copy of current object list 00193 Object3DList oldObjectList = m_objectList; 00194 00195 if (finalizeColor == eNone) 00196 { 00197 m_objectList.clear(); 00198 } 00199 else 00200 { 00201 for (int i = 0; i < (int) m_objectList.size(); i++) 00202 { 00203 if (m_objectList.at(i).color == finalizeColor) 00204 { 00205 m_objectList.erase(m_objectList.begin() + i); 00206 i--; 00207 } 00208 } 00209 } 00210 00211 int i, j; 00212 00213 for (i = 0; i < (int) resultListLeft.size(); i++) 00214 resultListLeft.at(i).reserved = 0; 00215 00216 for (i = 0; i < (int) resultListRight.size(); i++) 00217 resultListRight.at(i).reserved = 0; 00218 00219 // add already existing region pairs 00220 for (i = 0; i < (int) oldObjectList.size(); i++) 00221 { 00222 Object3DEntry &objectEntry = oldObjectList.at(i); 00223 00224 if (finalizeColor != eNone && finalizeColor != objectEntry.color) 00225 continue; 00226 00227 const int region_left_id = objectEntry.region_id_left; 00228 const int region_right_id = objectEntry.region_id_right; 00229 int nMatchLeft = -1, nMatchRight = -1; 00230 00231 for (j = 0; j < (int) resultListLeft.size(); j++) 00232 { 00233 if (resultListLeft.at(j).id == region_left_id) 00234 { 00235 nMatchLeft = j; 00236 break; 00237 } 00238 } 00239 00240 for (j = 0; j < (int) resultListRight.size(); j++) 00241 if (resultListRight.at(j).id == region_right_id) 00242 { 00243 nMatchRight = j; 00244 break; 00245 } 00246 00247 if (nMatchLeft != -1 && nMatchRight != -1) 00248 { 00249 // calculate 3D point 00250 objectEntry.region_left = resultListLeft.at(nMatchLeft).region; 00251 objectEntry.region_right = resultListRight.at(nMatchRight).region; 00252 m_pStereoCalibration->Calculate3DPoint(objectEntry.region_left.centroid, objectEntry.region_right.centroid, objectEntry.pose.translation, bInputImagesAreRectified, bUseDistortionParameters); 00253 00254 Math3d::SetVec(objectEntry.world_point, objectEntry.pose.translation); 00255 00256 if (objectEntry.pose.translation.z >= fMinZDistance && objectEntry.pose.translation.z <= fMaxZDistance && 00257 (!m_pObjectEntryFilter || m_pObjectEntryFilter->CheckEntry(objectEntry))) 00258 { 00259 resultListLeft.at(nMatchLeft).reserved = 1; 00260 resultListRight.at(nMatchRight).reserved = 1; 00261 m_objectList.push_back(objectEntry); 00262 } 00263 } 00264 } 00265 00266 // add new region pairs 00267 for (i = 0; i < (int) resultListLeft.size(); i++) 00268 { 00269 Object2DEntry &entryLeft = resultListLeft.at(i); 00270 00271 if (!entryLeft.reserved && (finalizeColor == eNone || entryLeft.color == finalizeColor)) 00272 { 00273 // find best match in list for right image 00274 float best_diff = fMaxEpipolarDistance; 00275 int best_j = -1; 00276 00277 for (j = 0; j < (int) resultListRight.size(); j++) 00278 { 00279 Object2DEntry &entryRight = resultListRight.at(j); 00280 00281 if (!entryRight.reserved) 00282 { 00283 const float ratio = entryLeft.region.nPixels < entryRight.region.nPixels ? (float) entryLeft.region.nPixels / entryRight.region.nPixels : (float) entryRight.region.nPixels / entryLeft.region.nPixels; 00284 const float ratio2 = entryLeft.region.ratio < entryRight.region.ratio ? (float) entryLeft.region.ratio / entryRight.region.ratio : (float) entryRight.region.ratio / entryLeft.region.ratio; 00285 const float y_diff = bInputImagesAreRectified ? fabsf(entryLeft.region.centroid.y - entryRight.region.centroid.y) : fabsf(m_pStereoCalibration->CalculateEpipolarLineInLeftImageDistance(entryLeft.region.centroid, entryRight.region.centroid)); 00286 00287 Vec3d position; 00288 m_pStereoCalibration->Calculate3DPoint(entryLeft.region.centroid, entryRight.region.centroid, position, bInputImagesAreRectified, bUseDistortionParameters); 00289 00290 //printf("%.2f %.2f -- %.2f %.2f -- %.2f %.2f %.2f\n", entryLeft.region.centroid.x, entryLeft.region.centroid.y, entryRight.region.centroid.x, entryRight.region.centroid.y, ratio, y_diff, position.z); 00291 00292 if (ratio > 0.5f && ratio2 > 0.5f && y_diff < fMaxEpipolarDistance && 00293 (entryLeft.type == entryRight.type || entryLeft.type == eCompactObject || entryRight.type == eCompactObject) && entryLeft.color == entryRight.color && (finalizeColor == eNone || entryLeft.color == finalizeColor) && 00294 position.z >= fMinZDistance && position.z <= fMaxZDistance && y_diff < best_diff) 00295 { 00296 best_diff = y_diff; 00297 best_j = j; 00298 } 00299 } 00300 } 00301 00302 if (best_j != -1) 00303 { 00304 Object2DEntry &entryRight = resultListRight.at(best_j); 00305 Object3DEntry entry; 00306 00307 entry.region_left = entryLeft.region; 00308 entry.region_right = entryRight.region; 00309 entry.region_id_left = entryLeft.id; 00310 entry.region_id_right = entryRight.id; 00311 entry.color = entryLeft.color; 00312 entry.type = entryLeft.type == eCompactObject ? entryRight.type : entryLeft.type; 00313 entry.sName = "CompactObject"; 00314 entry.sOivFilePath = ""; 00315 00316 m_pStereoCalibration->Calculate3DPoint(entry.region_left.centroid, entry.region_right.centroid, entry.pose.translation, bInputImagesAreRectified, bUseDistortionParameters); 00317 00318 Math3d::SetVec(entry.world_point, entry.pose.translation); 00319 00320 if (!m_pObjectEntryFilter || m_pObjectEntryFilter->CheckEntry(entry)) 00321 { 00322 entryLeft.reserved = 1; 00323 entryRight.reserved = 1; 00324 m_objectList.push_back(entry); 00325 } 00326 } 00327 } 00328 } 00329 00330 // run object classifiers 00331 for (i = 0; i < (int) m_objectClassifierList.size(); i++) 00332 m_objectClassifierList.at(i)->Classify(m_objectList); 00333 00334 return (int) m_objectList.size(); 00335 } 00336 00337 void CObjectFinderStereo::UpdateObjectFinderLists(Object2DList &resultListLeft, Object2DList &resultListRight) 00338 { 00339 int i; 00340 00341 // delete unmatched entries in left 2D list 00342 for (i = 0; i < (int) resultListLeft.size(); i++) 00343 if (!resultListLeft.at(i).reserved) 00344 { 00345 resultListLeft.erase(resultListLeft.begin() + i); 00346 i--; 00347 } 00348 00349 // delete unmatched entries in right 2D list 00350 for (i = 0; i < (int) resultListRight.size(); i++) 00351 if (!resultListRight.at(i).reserved) 00352 { 00353 resultListRight.erase(resultListRight.begin() + i); 00354 i--; 00355 } 00356 00357 // assign types to 2D lists 00358 for (i = 0; i < (int) m_objectList.size(); i++) 00359 { 00360 int j; 00361 00362 const Object3DEntry &object = m_objectList.at(i); 00363 00364 for (j = 0; j < (int) resultListLeft.size(); j++) 00365 { 00366 Object2DEntry &entry = resultListLeft.at(j); 00367 00368 if (entry.color == object.color && entry.region.centroid.x == object.region_left.centroid.x && entry.region.centroid.y == object.region_left.centroid.y && entry.region.nPixels == object.region_left.nPixels) 00369 entry.type = object.type; 00370 } 00371 00372 for (j = 0; j < (int) resultListRight.size(); j++) 00373 { 00374 Object2DEntry &entry = resultListRight.at(j); 00375 00376 if (entry.color == object.color && entry.region.centroid.x == object.region_right.centroid.x && entry.region.centroid.y == object.region_right.centroid.y && entry.region.nPixels == object.region_right.nPixels) 00377 entry.type = object.type; 00378 } 00379 } 00380 } 00381 00382 void CObjectFinderStereo::ClearObjectList() 00383 { 00384 m_objectList.clear(); 00385 m_pObjectFinderLeft->ClearObjectList(); 00386 m_pObjectFinderRight->ClearObjectList(); 00387 } 00388 00389 void CObjectFinderStereo::AddObject(const Object3DEntry &entry) 00390 { 00391 m_objectList.push_back(entry); 00392 00393 Object2DEntry entry2D; 00394 entry2D.type = entry.type; 00395 entry2D.color = entry.color; 00396 00397 entry2D.id = entry.region_id_left; 00398 entry2D.region = entry.region_left; 00399 m_pObjectFinderLeft->AddObject(entry2D); 00400 00401 entry2D.id = entry.region_id_right; 00402 entry2D.region = entry.region_right; 00403 m_pObjectFinderRight->AddObject(entry2D); 00404 } 00405 00406 00407 void CObjectFinderStereo::AddObjectClassifier(CObjectClassifierInterface *pObjectClassifier) 00408 { 00409 m_objectClassifierList.push_back(pObjectClassifier); 00410 } 00411 00412 void CObjectFinderStereo::RemoveObjectClassifier(CObjectClassifierInterface *pObjectClassifier) 00413 { 00414 for (std::vector<CObjectClassifierInterface*>::iterator it = m_objectClassifierList.begin(); it != m_objectClassifierList.end(); it++) 00415 { 00416 if (*it == pObjectClassifier) 00417 { 00418 m_objectClassifierList.erase(it); 00419 break; 00420 } 00421 } 00422 } 00423 00424 void CObjectFinderStereo::ClearObjectClassifierList() 00425 { 00426 m_objectClassifierList.clear(); 00427 }