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")
|
||||
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
|
||||
struct CV_EXPORTS Match
|
||||
struct CV_EXPORTS_W_SIMPLE MatchQuasiDense
|
||||
{
|
||||
cv::Point2i p0;
|
||||
cv::Point2i p1;
|
||||
float corr;
|
||||
CV_PROP_RW cv::Point2i p0;
|
||||
CV_PROP_RW cv::Point2i p1;
|
||||
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;
|
||||
}
|
||||
};
|
||||
struct CV_EXPORTS PropagationParameters
|
||||
struct CV_EXPORTS_W_SIMPLE PropagationParameters
|
||||
{
|
||||
int corrWinSizeX; // similarity window
|
||||
int corrWinSizeY;
|
||||
CV_PROP_RW int corrWinSizeX; // similarity window
|
||||
CV_PROP_RW int corrWinSizeY;
|
||||
|
||||
int borderX; // border to ignore
|
||||
int borderY;
|
||||
CV_PROP_RW int borderX; // border to ignore
|
||||
CV_PROP_RW int borderY;
|
||||
|
||||
//matching
|
||||
float correlationThreshold; // correlation threshold
|
||||
float textrureThreshold; // texture threshold
|
||||
CV_PROP_RW float correlationThreshold; // correlation threshold
|
||||
CV_PROP_RW float textrureThreshold; // texture threshold
|
||||
|
||||
int neighborhoodSize; // neighborhood size
|
||||
int disparityGradient; // disparity gradient threshold
|
||||
CV_PROP_RW int neighborhoodSize; // neighborhood size
|
||||
CV_PROP_RW int disparityGradient; // disparity gradient threshold
|
||||
|
||||
// Parameters for LK flow algorithm
|
||||
int lkTemplateSize;
|
||||
int lkPyrLvl;
|
||||
int lkTermParam1;
|
||||
float lkTermParam2;
|
||||
CV_PROP_RW int lkTemplateSize;
|
||||
CV_PROP_RW int lkPyrLvl;
|
||||
CV_PROP_RW int lkTermParam1;
|
||||
CV_PROP_RW float lkTermParam2;
|
||||
|
||||
// Parameters for GFT algorithm.
|
||||
float gftQualityThres;
|
||||
int gftMinSeperationDist;
|
||||
int gftMaxNumFeatures;
|
||||
CV_PROP_RW float gftQualityThres;
|
||||
CV_PROP_RW int gftMinSeperationDist;
|
||||
CV_PROP_RW int gftMaxNumFeatures;
|
||||
|
||||
};
|
||||
|
||||
@@ -90,14 +92,14 @@ struct CV_EXPORTS PropagationParameters
|
||||
*
|
||||
*/
|
||||
|
||||
class CV_EXPORTS QuasiDenseStereo
|
||||
class CV_EXPORTS_W QuasiDenseStereo
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief destructor
|
||||
* 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.
|
||||
* @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.
|
||||
* @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 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 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 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.
|
||||
* @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 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
|
||||
|
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]
|
||||
vector<stereo::Match> matches;
|
||||
vector<stereo::MatchQuasiDense> matches;
|
||||
stereo->getDenseMatches(matches);
|
||||
std::ofstream dense("./dense.txt", std::ios::out);
|
||||
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)
|
||||
|
||||
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
|
||||
@@ -165,7 +165,7 @@ public:
|
||||
t_matchPriorityQueue Local;
|
||||
|
||||
// Get the best seed at the moment
|
||||
Match m = seeds.top();
|
||||
MatchQuasiDense m = seeds.top();
|
||||
seeds.pop();
|
||||
|
||||
// Ignore the border
|
||||
@@ -209,7 +209,7 @@ public:
|
||||
// push back if this is valid match
|
||||
if( corr > Param.correlationThreshold )
|
||||
{
|
||||
Match nm;
|
||||
MatchQuasiDense nm;
|
||||
nm.p0 = p0;
|
||||
nm.p1 = p1;
|
||||
nm.corr = corr;
|
||||
@@ -223,7 +223,7 @@ public:
|
||||
// Get seeds from the local
|
||||
while( !Local.empty() )
|
||||
{
|
||||
Match lm = Local.top();
|
||||
MatchQuasiDense lm = Local.top();
|
||||
Local.pop();
|
||||
// Check if its unique in both ref and dst.
|
||||
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++)
|
||||
{
|
||||
// Calculate correlation and store match in Seeds.
|
||||
Match m;
|
||||
MatchQuasiDense m;
|
||||
m.p0 = cv::Point2i(featuresLeft[i]);
|
||||
m.p1 = cv::Point2i(featuresRight[i]);
|
||||
m.corr = 0;
|
||||
@@ -442,7 +442,7 @@ public:
|
||||
* @retval true If the feature is in the border of the 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 ||
|
||||
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.reserve(leftFeatures.size());
|
||||
for (uint i=0; i<leftFeatures.size(); i++)
|
||||
@@ -594,9 +594,9 @@ public:
|
||||
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.reserve(dMatchesLen);
|
||||
for (int row=0; row<height; row++)
|
||||
|
Reference in New Issue
Block a user