mirror of
https://github.com/opencv/opencv_contrib.git
synced 2025-10-19 19:44:14 +08:00
Merge pull request #2819 from LaurentBerger:pyb_qd
* solved issue 2813 * review
This commit is contained in:
@@ -1,2 +1,2 @@
|
|||||||
set(the_description "Stereo Correspondence")
|
set(the_description "Stereo Correspondence")
|
||||||
ocv_define_module(stereo opencv_imgproc opencv_features2d opencv_core opencv_tracking)
|
ocv_define_module(stereo opencv_imgproc opencv_features2d opencv_core opencv_tracking WRAP python)
|
||||||
|
@@ -24,42 +24,44 @@ namespace stereo
|
|||||||
|
|
||||||
|
|
||||||
// A basic match structure
|
// A basic match structure
|
||||||
struct CV_EXPORTS Match
|
struct CV_EXPORTS_W_SIMPLE MatchQuasiDense
|
||||||
{
|
{
|
||||||
cv::Point2i p0;
|
CV_PROP_RW cv::Point2i p0;
|
||||||
cv::Point2i p1;
|
CV_PROP_RW cv::Point2i p1;
|
||||||
float corr;
|
CV_PROP_RW float corr;
|
||||||
|
|
||||||
bool operator < (const Match & rhs) const//fixme may be used uninitialized in this function
|
CV_WRAP MatchQuasiDense() { corr = 0; }
|
||||||
|
|
||||||
|
CV_WRAP_AS(apply) bool operator < (const MatchQuasiDense & rhs) const//fixme may be used uninitialized in this function
|
||||||
{
|
{
|
||||||
return this->corr < rhs.corr;
|
return this->corr < rhs.corr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
struct CV_EXPORTS PropagationParameters
|
struct CV_EXPORTS_W_SIMPLE PropagationParameters
|
||||||
{
|
{
|
||||||
int corrWinSizeX; // similarity window
|
CV_PROP_RW int corrWinSizeX; // similarity window
|
||||||
int corrWinSizeY;
|
CV_PROP_RW int corrWinSizeY;
|
||||||
|
|
||||||
int borderX; // border to ignore
|
CV_PROP_RW int borderX; // border to ignore
|
||||||
int borderY;
|
CV_PROP_RW int borderY;
|
||||||
|
|
||||||
//matching
|
//matching
|
||||||
float correlationThreshold; // correlation threshold
|
CV_PROP_RW float correlationThreshold; // correlation threshold
|
||||||
float textrureThreshold; // texture threshold
|
CV_PROP_RW float textrureThreshold; // texture threshold
|
||||||
|
|
||||||
int neighborhoodSize; // neighborhood size
|
CV_PROP_RW int neighborhoodSize; // neighborhood size
|
||||||
int disparityGradient; // disparity gradient threshold
|
CV_PROP_RW int disparityGradient; // disparity gradient threshold
|
||||||
|
|
||||||
// Parameters for LK flow algorithm
|
// Parameters for LK flow algorithm
|
||||||
int lkTemplateSize;
|
CV_PROP_RW int lkTemplateSize;
|
||||||
int lkPyrLvl;
|
CV_PROP_RW int lkPyrLvl;
|
||||||
int lkTermParam1;
|
CV_PROP_RW int lkTermParam1;
|
||||||
float lkTermParam2;
|
CV_PROP_RW float lkTermParam2;
|
||||||
|
|
||||||
// Parameters for GFT algorithm.
|
// Parameters for GFT algorithm.
|
||||||
float gftQualityThres;
|
CV_PROP_RW float gftQualityThres;
|
||||||
int gftMinSeperationDist;
|
CV_PROP_RW int gftMinSeperationDist;
|
||||||
int gftMaxNumFeatures;
|
CV_PROP_RW int gftMaxNumFeatures;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -90,14 +92,14 @@ struct CV_EXPORTS PropagationParameters
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class CV_EXPORTS QuasiDenseStereo
|
class CV_EXPORTS_W QuasiDenseStereo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief destructor
|
* @brief destructor
|
||||||
* Method to free all the memory allocated by matrices and vectors in this class.
|
* Method to free all the memory allocated by matrices and vectors in this class.
|
||||||
*/
|
*/
|
||||||
virtual ~QuasiDenseStereo() = 0;
|
CV_WRAP virtual ~QuasiDenseStereo() = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -113,7 +115,7 @@ public:
|
|||||||
* in case of video processing.
|
* in case of video processing.
|
||||||
* @sa loadParameters
|
* @sa loadParameters
|
||||||
*/
|
*/
|
||||||
virtual int loadParameters(cv::String filepath) = 0;
|
CV_WRAP virtual int loadParameters(cv::String filepath) = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -124,7 +126,7 @@ public:
|
|||||||
* @note This method can be used to generate a template file for tuning the class.
|
* @note This method can be used to generate a template file for tuning the class.
|
||||||
* @sa loadParameters
|
* @sa loadParameters
|
||||||
*/
|
*/
|
||||||
virtual int saveParameters(cv::String filepath) = 0;
|
CV_WRAP virtual int saveParameters(cv::String filepath) = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,7 +135,7 @@ public:
|
|||||||
* @note The method clears the sMatches vector.
|
* @note The method clears the sMatches vector.
|
||||||
* @note The returned Match elements inside the sMatches vector, do not use corr member.
|
* @note The returned Match elements inside the sMatches vector, do not use corr member.
|
||||||
*/
|
*/
|
||||||
virtual void getSparseMatches(std::vector<stereo::Match> &sMatches) = 0;
|
CV_WRAP virtual void getSparseMatches(CV_OUT std::vector<MatchQuasiDense> &sMatches) = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -142,7 +144,7 @@ public:
|
|||||||
* @note The method clears the denseMatches vector.
|
* @note The method clears the denseMatches vector.
|
||||||
* @note The returned Match elements inside the sMatches vector, do not use corr member.
|
* @note The returned Match elements inside the sMatches vector, do not use corr member.
|
||||||
*/
|
*/
|
||||||
virtual void getDenseMatches(std::vector<stereo::Match> &denseMatches) = 0;
|
CV_WRAP virtual void getDenseMatches(CV_OUT std::vector<MatchQuasiDense> &denseMatches) = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -158,7 +160,7 @@ public:
|
|||||||
* @sa sparseMatching
|
* @sa sparseMatching
|
||||||
* @sa quasiDenseMatching
|
* @sa quasiDenseMatching
|
||||||
*/
|
*/
|
||||||
virtual void process(const cv::Mat &imgLeft ,const cv::Mat &imgRight) = 0;
|
CV_WRAP virtual void process(const cv::Mat &imgLeft ,const cv::Mat &imgRight) = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -169,7 +171,7 @@ public:
|
|||||||
* @retval cv::Point(0, 0) (NO_MATCH) if no match is found in the right image for the specified pixel location in the left image.
|
* @retval cv::Point(0, 0) (NO_MATCH) if no match is found in the right image for the specified pixel location in the left image.
|
||||||
* @note This method should be always called after process, otherwise the matches will not be correct.
|
* @note This method should be always called after process, otherwise the matches will not be correct.
|
||||||
*/
|
*/
|
||||||
virtual cv::Point2f getMatch(const int x, const int y) = 0;
|
CV_WRAP virtual cv::Point2f getMatch(const int x, const int y) = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -180,13 +182,13 @@ public:
|
|||||||
* @sa computeDisparity
|
* @sa computeDisparity
|
||||||
* @sa quantizeDisparity
|
* @sa quantizeDisparity
|
||||||
*/
|
*/
|
||||||
virtual cv::Mat getDisparity(uint8_t disparityLvls=50) = 0;
|
CV_WRAP virtual cv::Mat getDisparity(uint8_t disparityLvls=50) = 0;
|
||||||
|
|
||||||
|
|
||||||
static cv::Ptr<QuasiDenseStereo> create(cv::Size monoImgSize, cv::String paramFilepath = cv::String());
|
CV_WRAP static cv::Ptr<QuasiDenseStereo> create(cv::Size monoImgSize, cv::String paramFilepath = cv::String());
|
||||||
|
|
||||||
|
|
||||||
PropagationParameters Param;
|
CV_PROP_RW PropagationParameters Param;
|
||||||
};
|
};
|
||||||
|
|
||||||
} //namespace cv
|
} //namespace cv
|
||||||
|
17
modules/stereo/misc/python/pyopencv_stereo.hpp
Normal file
17
modules/stereo/misc/python/pyopencv_stereo.hpp
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#ifdef HAVE_OPENCV_STEREO
|
||||||
|
typedef std::vector<stereo::MatchQuasiDense> vector_MatchQuasiDense;
|
||||||
|
|
||||||
|
template<> struct pyopencvVecConverter<stereo::MatchQuasiDense>
|
||||||
|
{
|
||||||
|
static bool to(PyObject* obj, std::vector<stereo::MatchQuasiDense>& value, const ArgInfo& info)
|
||||||
|
{
|
||||||
|
return pyopencv_to_generic_vec(obj, value, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject* from(const std::vector<stereo::MatchQuasiDense>& value)
|
||||||
|
{
|
||||||
|
return pyopencv_from_generic_vec(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
20
modules/stereo/misc/python/test/test_stereo.py
Normal file
20
modules/stereo/misc/python/test/test_stereo.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import cv2 as cv
|
||||||
|
|
||||||
|
from tests_common import NewOpenCVTests
|
||||||
|
|
||||||
|
class quasi_dense_stereo_test(NewOpenCVTests):
|
||||||
|
|
||||||
|
def test_simple(self):
|
||||||
|
|
||||||
|
stereo = cv.stereo.QuasiDenseStereo_create((100, 100))
|
||||||
|
self.assertIsNotNone(stereo)
|
||||||
|
|
||||||
|
dense_matches = cv.stereo_MatchQuasiDense()
|
||||||
|
self.assertIsNotNone(dense_matches)
|
||||||
|
|
||||||
|
parameters = cv.stereo_PropagationParameters()
|
||||||
|
self.assertIsNotNone(parameters)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
NewOpenCVTests.bootstrap()
|
@@ -46,7 +46,7 @@ int main()
|
|||||||
|
|
||||||
|
|
||||||
//! [export]
|
//! [export]
|
||||||
vector<stereo::Match> matches;
|
vector<stereo::MatchQuasiDense> matches;
|
||||||
stereo->getDenseMatches(matches);
|
stereo->getDenseMatches(matches);
|
||||||
std::ofstream dense("./dense.txt", std::ios::out);
|
std::ofstream dense("./dense.txt", std::ios::out);
|
||||||
for (uint i=0; i< matches.size(); i++)
|
for (uint i=0; i< matches.size(); i++)
|
||||||
|
21
modules/stereo/samples/sample_quasi_dense.py
Normal file
21
modules/stereo/samples/sample_quasi_dense.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import numpy as np
|
||||||
|
import cv2 as cv
|
||||||
|
|
||||||
|
left_img = cv.imread(cv.samples.findFile("aloeL.jpg"), cv.IMREAD_COLOR)
|
||||||
|
right_img = cv.imread(cv.samples.findFile("aloeR.jpg"), cv.IMREAD_COLOR)
|
||||||
|
|
||||||
|
frame_size = leftImg.shape[0:2];
|
||||||
|
|
||||||
|
stereo = cv.stereo.QuasiDenseStereo_create(frame_size[::-1])
|
||||||
|
stereo.process(left_img, right_img)
|
||||||
|
disp = stereo.getDisparity(80)
|
||||||
|
cv.imshow("disparity", disp)
|
||||||
|
cv.waitKey()
|
||||||
|
dense_matches = stereo.getDenseMatches()
|
||||||
|
try:
|
||||||
|
with open("dense.txt", "wt") as f:
|
||||||
|
# if you want all matches use for idx in len(dense_matches): It can be a big file
|
||||||
|
for idx in range(0, min(10, len(dense_matches))):
|
||||||
|
nb = f.write(str(dense_matches[idx].p0) + "\t" + str(dense_matches[idx].p1) + "\t" + str(dense_matches[idx].corr) + "\n")
|
||||||
|
except:
|
||||||
|
print("Cannot open file")
|
@@ -13,7 +13,7 @@ namespace stereo {
|
|||||||
|
|
||||||
#define NO_MATCH cv::Point(0,0)
|
#define NO_MATCH cv::Point(0,0)
|
||||||
|
|
||||||
typedef std::priority_queue<Match, std::vector<Match>, std::less<Match> > t_matchPriorityQueue;
|
typedef std::priority_queue<MatchQuasiDense, std::vector<MatchQuasiDense>, std::less<MatchQuasiDense> > t_matchPriorityQueue;
|
||||||
|
|
||||||
|
|
||||||
class QuasiDenseStereoImpl : public QuasiDenseStereo
|
class QuasiDenseStereoImpl : public QuasiDenseStereo
|
||||||
@@ -165,7 +165,7 @@ public:
|
|||||||
t_matchPriorityQueue Local;
|
t_matchPriorityQueue Local;
|
||||||
|
|
||||||
// Get the best seed at the moment
|
// Get the best seed at the moment
|
||||||
Match m = seeds.top();
|
MatchQuasiDense m = seeds.top();
|
||||||
seeds.pop();
|
seeds.pop();
|
||||||
|
|
||||||
// Ignore the border
|
// Ignore the border
|
||||||
@@ -209,7 +209,7 @@ public:
|
|||||||
// push back if this is valid match
|
// push back if this is valid match
|
||||||
if( corr > Param.correlationThreshold )
|
if( corr > Param.correlationThreshold )
|
||||||
{
|
{
|
||||||
Match nm;
|
MatchQuasiDense nm;
|
||||||
nm.p0 = p0;
|
nm.p0 = p0;
|
||||||
nm.p1 = p1;
|
nm.p1 = p1;
|
||||||
nm.corr = corr;
|
nm.corr = corr;
|
||||||
@@ -223,7 +223,7 @@ public:
|
|||||||
// Get seeds from the local
|
// Get seeds from the local
|
||||||
while( !Local.empty() )
|
while( !Local.empty() )
|
||||||
{
|
{
|
||||||
Match lm = Local.top();
|
MatchQuasiDense lm = Local.top();
|
||||||
Local.pop();
|
Local.pop();
|
||||||
// Check if its unique in both ref and dst.
|
// Check if its unique in both ref and dst.
|
||||||
if(refMap.at<cv::Point2i>(lm.p0.y, lm.p0.x) != NO_MATCH)
|
if(refMap.at<cv::Point2i>(lm.p0.y, lm.p0.x) != NO_MATCH)
|
||||||
@@ -410,7 +410,7 @@ public:
|
|||||||
for(uint i=0; i < featuresLeft.size(); i++)
|
for(uint i=0; i < featuresLeft.size(); i++)
|
||||||
{
|
{
|
||||||
// Calculate correlation and store match in Seeds.
|
// Calculate correlation and store match in Seeds.
|
||||||
Match m;
|
MatchQuasiDense m;
|
||||||
m.p0 = cv::Point2i(featuresLeft[i]);
|
m.p0 = cv::Point2i(featuresLeft[i]);
|
||||||
m.p1 = cv::Point2i(featuresRight[i]);
|
m.p1 = cv::Point2i(featuresRight[i]);
|
||||||
m.corr = 0;
|
m.corr = 0;
|
||||||
@@ -442,7 +442,7 @@ public:
|
|||||||
* @retval true If the feature is in the border of the image.
|
* @retval true If the feature is in the border of the image.
|
||||||
* @retval false If the feature is not in the border of image.
|
* @retval false If the feature is not in the border of image.
|
||||||
*/
|
*/
|
||||||
bool CheckBorder(Match m, int bx, int by, int w, int h)
|
bool CheckBorder(MatchQuasiDense m, int bx, int by, int w, int h)
|
||||||
{
|
{
|
||||||
if(m.p0.x<bx || m.p0.x>w-bx || m.p0.y<by || m.p0.y>h-by ||
|
if(m.p0.x<bx || m.p0.x>w-bx || m.p0.y<by || m.p0.y>h-by ||
|
||||||
m.p1.x<bx || m.p1.x>w-bx || m.p1.y<by || m.p1.y>h-by)
|
m.p1.x<bx || m.p1.x>w-bx || m.p1.y<by || m.p1.y>h-by)
|
||||||
@@ -492,9 +492,9 @@ public:
|
|||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
void getSparseMatches(std::vector<stereo::Match> &sMatches) override
|
void getSparseMatches(std::vector<stereo::MatchQuasiDense> &sMatches) override
|
||||||
{
|
{
|
||||||
Match tmpMatch;
|
MatchQuasiDense tmpMatch;
|
||||||
sMatches.clear();
|
sMatches.clear();
|
||||||
sMatches.reserve(leftFeatures.size());
|
sMatches.reserve(leftFeatures.size());
|
||||||
for (uint i=0; i<leftFeatures.size(); i++)
|
for (uint i=0; i<leftFeatures.size(); i++)
|
||||||
@@ -594,9 +594,9 @@ public:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void getDenseMatches(std::vector<stereo::Match> &denseMatches) override
|
void getDenseMatches(std::vector<stereo::MatchQuasiDense> &denseMatches) override
|
||||||
{
|
{
|
||||||
Match tmpMatch;
|
MatchQuasiDense tmpMatch;
|
||||||
denseMatches.clear();
|
denseMatches.clear();
|
||||||
denseMatches.reserve(dMatchesLen);
|
denseMatches.reserve(dMatchesLen);
|
||||||
for (int row=0; row<height; row++)
|
for (int row=0; row<height; row++)
|
||||||
|
Reference in New Issue
Block a user