You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
9.0 KiB
217 lines
9.0 KiB
/* |
|
* SemiGlobalMatcher.h |
|
* |
|
* Copyright (c) 2014-2015 SEACAVE |
|
* |
|
* Author(s): |
|
* |
|
* cDc <cdc.seacave@gmail.com> |
|
* |
|
* |
|
* This program is free software: you can redistribute it and/or modify |
|
* it under the terms of the GNU Affero General Public License as published by |
|
* the Free Software Foundation, either version 3 of the License, or |
|
* (at your option) any later version. |
|
* |
|
* This program is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU Affero General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU Affero General Public License |
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
* |
|
* |
|
* Additional Terms: |
|
* |
|
* You are required to preserve legal notices and author attributions in |
|
* that material or in the Appropriate Legal Notices displayed by works |
|
* containing it. |
|
*/ |
|
|
|
#ifndef _MVS_SEMIGLOBALMATCHER_H_ |
|
#define _MVS_SEMIGLOBALMATCHER_H_ |
|
|
|
|
|
// I N C L U D E S ///////////////////////////////////////////////// |
|
|
|
#include "DepthMap.h" |
|
|
|
|
|
// D E F I N E S /////////////////////////////////////////////////// |
|
|
|
// similarity method |
|
#define SGM_SIMILARITY_WZNCC 1 |
|
#define SGM_SIMILARITY_CENSUS 2 |
|
#define SGM_SIMILARITY SGM_SIMILARITY_WZNCC |
|
|
|
|
|
// S T R U C T S /////////////////////////////////////////////////// |
|
|
|
namespace MVS { |
|
|
|
class Scene; |
|
|
|
namespace STEREO { |
|
|
|
// An implementation of the popular Semi-Global Matching (SGM) algorithm. |
|
class MVS_API SemiGlobalMatcher |
|
{ |
|
public: |
|
typedef uint8_t Mask; // used to mark the valid region to be estimated |
|
typedef int16_t Disparity; // contains the allowable disparity range |
|
typedef uint8_t Cost; // used to describe a single disparity cost |
|
typedef uint16_t AccumCost; // used to accumulate CostType values |
|
typedef uint64_t Index; // index pointing to pixel costs/accumulated-costs |
|
|
|
enum : Mask { INVALID = 0, VALID = DECLARE_NO_INDEX(Mask) }; // invalid/valid mask value |
|
enum : Disparity { NO_DISP = DECLARE_NO_INDEX(Disparity) }; // invalid disparity value |
|
enum : AccumCost { NO_ACCUMCOST = DECLARE_NO_INDEX(AccumCost) }; // invalid accumulated cost value |
|
enum : Index { NO_INDEX = DECLARE_NO_INDEX(Index) }; // invalid index value |
|
|
|
struct Range { |
|
Disparity minDisp; |
|
Disparity maxDisp; |
|
Disparity avgDisp() const { return (minDisp+maxDisp)>>1; } |
|
Disparity numDisp() const { return maxDisp-minDisp; } |
|
Disparity isValid() const { return minDisp<maxDisp; } |
|
}; |
|
struct PixelData { |
|
Index idx; // index to pixel costs/accumulated-costs data |
|
Range range; // first and last disparity evaluated for this pixel |
|
}; |
|
|
|
typedef TImage<Mask> MaskMap; // image of accumulated disparity cost |
|
typedef TImage<Disparity> DisparityMap; // disparity image type |
|
typedef TImage<AccumCost> AccumCostMap; // image of accumulated disparity cost |
|
typedef CLISTDEF0IDX(PixelData,Index) PixelMap; // map of pixel data |
|
typedef CLISTDEF0IDX(Cost,Index) CostsMap; // map of pre-computed disparity costs |
|
typedef CLISTDEF0IDX(AccumCost,Index) AccumCostsMap; // map of accumulated disparity costs |
|
|
|
enum : int { numDirs = 4 }; // 2 or 4 directions accumulated per pixel pass |
|
#if SGM_SIMILARITY == SGM_SIMILARITY_CENSUS |
|
enum : int { halfWindowSizeX = 3, halfWindowSizeY = 4 }; // patch kernel size |
|
#else |
|
enum : int { halfWindowSizeX = 3, halfWindowSizeY = 3 }; // patch kernel size |
|
#endif |
|
enum : int { windowSizeX = halfWindowSizeX*2+1, windowSizeY = halfWindowSizeY*2+1, numTexels = windowSizeX*windowSizeY }; // patch kernel info |
|
|
|
#if SGM_SIMILARITY == SGM_SIMILARITY_CENSUS |
|
typedef uint64_t Census; // used to store Census transform |
|
typedef TImage<Census> CensusMap; // image of Census transforms |
|
typedef Image8U ImageGray; // used to store intensities image |
|
STATIC_ASSERT(sizeof(Census)*8 >= numTexels); |
|
#else |
|
typedef WeightedPatchFix<numTexels> WeightedPatch; // pre-computed patch weights |
|
typedef Image32F ImageGray; // used to store normalized float intensities image |
|
#endif |
|
|
|
|
|
// Available sub-pixel options |
|
enum SgmSubpixelMode { |
|
SUBPIXEL_NA = 0, // no sub-pixel processing |
|
SUBPIXEL_LINEAR, |
|
SUBPIXEL_POLY4, |
|
SUBPIXEL_PARABOLA, |
|
SUBPIXEL_SINE, |
|
SUBPIXEL_COSINE, |
|
SUBPIXEL_LC_BLEND // probably the best option |
|
}; |
|
|
|
struct ViewData { |
|
Image8U3 imageColor; // color image |
|
ImageGray imageGray; // intensity image |
|
#if SGM_SIMILARITY == SGM_SIMILARITY_CENSUS |
|
CensusMap imageCensus; // image of Census transforms (valid per scale) |
|
#endif |
|
ViewData GetImage(REAL scale) const { |
|
if (ISEQUAL(scale, REAL(1))) { |
|
#if SGM_SIMILARITY == SGM_SIMILARITY_CENSUS |
|
CensusTransform(imageGray, const_cast<CensusMap&>(imageCensus)); |
|
#endif |
|
return *this; |
|
} |
|
ASSERT(scale < 1); |
|
ViewData scaledView; |
|
cv::resize(imageColor, scaledView.imageColor, cv::Size(), scale, scale, cv::INTER_AREA); |
|
cv::resize(imageGray, scaledView.imageGray, cv::Size(), scale, scale, cv::INTER_AREA); |
|
#if SGM_SIMILARITY == SGM_SIMILARITY_CENSUS |
|
CensusTransform(scaledView.imageGray, scaledView.imageCensus); |
|
#endif |
|
return scaledView; |
|
} |
|
}; |
|
|
|
typedef Point2f DepthRange; |
|
typedef TImage<DepthRange> DepthRangeMap; |
|
|
|
public: |
|
SemiGlobalMatcher(SgmSubpixelMode subpixelMode=SUBPIXEL_LC_BLEND, Disparity subpixelSteps=4, AccumCost P1=3, AccumCost P2=4, float P2alpha=14, float P2beta=38); |
|
~SemiGlobalMatcher(); |
|
|
|
void Match(const Scene& scene, IIndex idxImage, IIndex numNeighbors, unsigned minResolution=320); |
|
void Fuse(const Scene& scene, IIndex idxImage, IIndex numNeighbors, unsigned minViews, DepthMap& depthMap, ConfidenceMap& confMap); |
|
|
|
static void CreateThreads(unsigned nMaxThreads=1); |
|
static void DestroyThreads(); |
|
static void* ThreadWorker(void*); |
|
static void WaitThreadWorkers(unsigned nJobs); |
|
|
|
static bool ExportDisparityDataRaw(const String& fileName, const DisparityMap&, const AccumCostMap&, const cv::Size& imageSize, const Matrix3x3& H, const Matrix4x4& Q, Disparity subpixelSteps); |
|
static bool ExportDisparityDataRawFull(const String& fileName, const DisparityMap&, const AccumCostMap&, const cv::Size& imageSize, const Matrix3x3& H, const Matrix4x4& Q, Disparity subpixelSteps); |
|
static bool ImportDisparityDataRaw(const String& fileName, DisparityMap&, AccumCostMap&, cv::Size& imageSize, Matrix3x3& H, Matrix4x4& Q, Disparity& subpixelSteps); |
|
static bool ImportDisparityDataRawFull(const String& fileName, DisparityMap&, AccumCostMap&, cv::Size& imageSize, Matrix3x3& H, Matrix4x4& Q, Disparity& subpixelSteps); |
|
static Image8U3 DisparityMap2Image(const DisparityMap&, Disparity minDisparity=NO_DISP, Disparity maxDisparity=NO_DISP); |
|
static bool ExportDisparityMap(const String& fileName, const DisparityMap&, Disparity minDisparity=NO_DISP, Disparity maxDisparity=NO_DISP); |
|
static bool ExportPointCloud(const String& fileName, const Image&, const DisparityMap&, const Matrix4x4& Q, Disparity subpixelSteps); |
|
static bool ImportPointCloud(const String& fileName, const ImageArr& images, PointCloud&); |
|
|
|
protected: |
|
void Match(const ViewData& leftImage, const ViewData& rightImage, DisparityMap& disparityMap, AccumCostMap& costMap); |
|
Index Disparity2RangeMap(const DisparityMap& disparityMap, const MaskMap& maskMap, Disparity minNumDisp=3, Disparity minNumDispInvalid=16); |
|
#if SGM_SIMILARITY == SGM_SIMILARITY_CENSUS |
|
static void CensusTransform(const Image8U& imageGray, CensusMap& imageCensus); |
|
#endif |
|
static void ConsistencyCrossCheck(DisparityMap& l2r, const DisparityMap& r2l, Disparity thCross=1); |
|
static void FilterByCost(DisparityMap&, const AccumCostMap&, AccumCost th); |
|
static void ExtractMask(const DisparityMap&, MaskMap&, int thValid=3); |
|
static void FlipDirection(const DisparityMap& l2r, DisparityMap& r2l); |
|
static void UpscaleMask(MaskMap& maskMap, const cv::Size& size2x); |
|
void RefineDisparityMap(DisparityMap& disparityMap) const; |
|
#ifndef _RELEASE |
|
void DisplayState(const cv::Size& size) const; |
|
#endif |
|
|
|
static CLISTDEF0IDX(AccumCost,int) GenerateP2s(AccumCost P2, float P2alpha, float P2beta); |
|
static void Depth2DisparityMap(const DepthMap&, const Matrix3x3& invH, const Matrix4x4& invQ, Disparity subpixelSteps, DisparityMap&); |
|
static void Disparity2DepthMap(const DisparityMap&, const AccumCostMap&, const Matrix3x3& H, const Matrix4x4& Q, Disparity subpixelSteps, DepthMap&, ConfidenceMap&); |
|
static bool ProjectDisparity2DepthMap(const DisparityMap&, const AccumCostMap&, const Matrix4x4& Q, Disparity subpixelSteps, DepthMap&, DepthRangeMap&, ConfidenceMap&); |
|
|
|
protected: |
|
// parameters |
|
SgmSubpixelMode subpixelMode; |
|
Disparity subpixelSteps; |
|
AccumCost P1; |
|
CLISTDEF0IDX(AccumCost,int) P2s; |
|
|
|
// main memory buffers that must be allocated |
|
PixelMap imagePixels; |
|
CostsMap imageCosts; |
|
AccumCostsMap imageAccumCosts; |
|
Disparity maxNumDisp; // maximum number of disparities per-pixel |
|
|
|
// multi-threading |
|
static EventThreadPool threads; // worker threads |
|
static Semaphore sem; // signal job end |
|
}; |
|
/*----------------------------------------------------------------*/ |
|
|
|
|
|
MVS_API bool ExportCamerasEngin(const Scene&, const String& fileName); |
|
/*----------------------------------------------------------------*/ |
|
|
|
} // namespace STEREO |
|
|
|
} // namespace MVS |
|
|
|
#endif // _MVS_SEMIGLOBALMATCHER_H_
|
|
|