1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 07:43:03 +04:00

Merge pull request #20367 from augustinmanecy:features2d-rw

**Merge with contrib**: https://github.com/opencv/opencv_contrib/pull/3003

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or other license that is incompatible with OpenCV
- [x] The PR is proposed to proper branch
- [ ] There is reference to original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [ ] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
augustinmanecy
2022-12-21 14:03:00 +01:00
committed by GitHub
parent 63b6b24cd0
commit 0bd54a60e9
28 changed files with 845 additions and 555 deletions
+21
View File
@@ -7948,6 +7948,27 @@ public:
: threshold(_threshold), nonmaxSuppression(_nonmaxSuppression), type(_type)
{}
void read( const FileNode& fn) CV_OVERRIDE
{
// if node is empty, keep previous value
if (!fn["threshold"].empty())
fn["threshold"] >> threshold;
if (!fn["nonmaxSuppression"].empty())
fn["nonmaxSuppression"] >> nonmaxSuppression;
if (!fn["type"].empty())
fn["type"] >> type;
}
void write( FileStorage& fs) const CV_OVERRIDE
{
if(fs.isOpened())
{
fs << "name" << getDefaultName();
fs << "threshold" << threshold;
fs << "nonmaxSuppression" << nonmaxSuppression;
fs << "type" << type;
}
}
void detect( InputArray _image, std::vector<KeyPoint>& keypoints, InputArray _mask ) CV_OVERRIDE
{
CV_INSTRUMENT_REGION();
+16 -7
View File
@@ -207,6 +207,7 @@ namespace cv
void write(FileStorage& fs) const CV_OVERRIDE
{
writeFormat(fs);
fs << "name" << getDefaultName();
fs << "descriptor" << descriptor;
fs << "descriptor_channels" << descriptor_channels;
fs << "descriptor_size" << descriptor_size;
@@ -218,13 +219,21 @@ namespace cv
void read(const FileNode& fn) CV_OVERRIDE
{
descriptor = static_cast<DescriptorType>((int)fn["descriptor"]);
descriptor_channels = (int)fn["descriptor_channels"];
descriptor_size = (int)fn["descriptor_size"];
threshold = (float)fn["threshold"];
octaves = (int)fn["octaves"];
sublevels = (int)fn["sublevels"];
diffusivity = static_cast<KAZE::DiffusivityType>((int)fn["diffusivity"]);
// if node is empty, keep previous value
if (!fn["descriptor"].empty())
descriptor = static_cast<DescriptorType>((int)fn["descriptor"]);
if (!fn["descriptor_channels"].empty())
descriptor_channels = (int)fn["descriptor_channels"];
if (!fn["descriptor_size"].empty())
descriptor_size = (int)fn["descriptor_size"];
if (!fn["threshold"].empty())
threshold = (float)fn["threshold"];
if (!fn["octaves"].empty())
octaves = (int)fn["octaves"];
if (!fn["sublevels"].empty())
sublevels = (int)fn["sublevels"];
if (!fn["diffusivity"].empty())
diffusivity = static_cast<KAZE::DiffusivityType>((int)fn["diffusivity"]);
}
DescriptorType descriptor;
+36 -1
View File
@@ -71,6 +71,37 @@ public:
virtual void read( const FileNode& fn ) CV_OVERRIDE;
virtual void write( FileStorage& fs ) const CV_OVERRIDE;
void setParams(const SimpleBlobDetector::Params& _params ) CV_OVERRIDE {
SimpleBlobDetectorImpl::validateParameters(_params);
params = _params;
}
SimpleBlobDetector::Params getParams() const CV_OVERRIDE { return params; }
static void validateParameters(const SimpleBlobDetector::Params& p)
{
if (p.thresholdStep <= 0)
CV_Error(Error::StsBadArg, "thresholdStep>0");
if (p.minThreshold > p.maxThreshold || p.minThreshold <= 0)
CV_Error(Error::StsBadArg, "0<minThreshold<=maxThreshold");
if (p.minDistBetweenBlobs <=0 )
CV_Error(Error::StsBadArg, "minDistBetweenBlobs>0");
if (p.minArea > p.maxArea || p.minArea <=0)
CV_Error(Error::StsBadArg, "0<minArea<=maxArea");
if (p.minCircularity > p.maxCircularity || p.minCircularity <= 0)
CV_Error(Error::StsBadArg, "0<minCircularity<=maxCircularity");
if (p.minInertiaRatio > p.maxInertiaRatio || p.minInertiaRatio <= 0)
CV_Error(Error::StsBadArg, "0<minInertiaRatio<=maxInertiaRatio");
if (p.minConvexity > p.maxConvexity || p.minConvexity <= 0)
CV_Error(Error::StsBadArg, "0<minConvexity<=maxConvexity");
}
protected:
struct CV_EXPORTS Center
{
@@ -192,7 +223,10 @@ params(parameters)
void SimpleBlobDetectorImpl::read( const cv::FileNode& fn )
{
params.read(fn);
SimpleBlobDetector::Params rp;
rp.read(fn);
SimpleBlobDetectorImpl::validateParameters(rp);
params = rp;
}
void SimpleBlobDetectorImpl::write( cv::FileStorage& fs ) const
@@ -455,6 +489,7 @@ const std::vector<std::vector<Point> >& SimpleBlobDetectorImpl::getBlobContours(
Ptr<SimpleBlobDetector> SimpleBlobDetector::create(const SimpleBlobDetector::Params& params)
{
SimpleBlobDetectorImpl::validateParameters(params);
return makePtr<SimpleBlobDetectorImpl>(params);
}
+63 -25
View File
@@ -54,7 +54,7 @@ namespace cv
class BRISK_Impl CV_FINAL : public BRISK
{
public:
explicit BRISK_Impl(int thresh=30, int octaves=3, float patternScale=1.0f);
explicit BRISK_Impl(int _threshold=30, int _octaves=3, float _patternScale=1.0f);
// custom setup
explicit BRISK_Impl(const std::vector<float> &radiusList, const std::vector<int> &numberList,
float dMax=5.85f, float dMin=8.2f, const std::vector<int> indexChange=std::vector<int>());
@@ -65,6 +65,9 @@ public:
virtual ~BRISK_Impl();
void read( const FileNode& fn) CV_OVERRIDE;
void write( FileStorage& fs) const CV_OVERRIDE;
int descriptorSize() const CV_OVERRIDE
{
return strings_;
@@ -99,6 +102,35 @@ public:
{
return octaves;
}
virtual void setPatternScale(float _patternScale) CV_OVERRIDE
{
patternScale = _patternScale;
std::vector<float> rList;
std::vector<int> nList;
// this is the standard pattern found to be suitable also
rList.resize(5);
nList.resize(5);
const double f = 0.85 * patternScale;
rList[0] = (float)(f * 0.);
rList[1] = (float)(f * 2.9);
rList[2] = (float)(f * 4.9);
rList[3] = (float)(f * 7.4);
rList[4] = (float)(f * 10.8);
nList[0] = 1;
nList[1] = 10;
nList[2] = 14;
nList[3] = 15;
nList[4] = 20;
generateKernel(rList, nList, (float)(5.85 * patternScale), (float)(8.2 * patternScale));
}
virtual float getPatternScale() const CV_OVERRIDE
{
return patternScale;
}
// call this to generate the kernel:
// circle of radius r (pixels), with n points;
@@ -122,6 +154,7 @@ protected:
// Feature parameters
CV_PROP_RW int threshold;
CV_PROP_RW int octaves;
CV_PROP_RW float patternScale;
// some helper structures for the Brisk pattern representation
struct BriskPatternPoint{
@@ -309,32 +342,12 @@ const float BriskScaleSpace::safetyFactor_ = 1.0f;
const float BriskScaleSpace::basicSize_ = 12.0f;
// constructors
BRISK_Impl::BRISK_Impl(int thresh, int octaves_in, float patternScale)
BRISK_Impl::BRISK_Impl(int _threshold, int _octaves, float _patternScale)
{
threshold = thresh;
octaves = octaves_in;
threshold = _threshold;
octaves = _octaves;
std::vector<float> rList;
std::vector<int> nList;
// this is the standard pattern found to be suitable also
rList.resize(5);
nList.resize(5);
const double f = 0.85 * patternScale;
rList[0] = (float)(f * 0.);
rList[1] = (float)(f * 2.9);
rList[2] = (float)(f * 4.9);
rList[3] = (float)(f * 7.4);
rList[4] = (float)(f * 10.8);
nList[0] = 1;
nList[1] = 10;
nList[2] = 14;
nList[3] = 15;
nList[4] = 20;
generateKernel(rList, nList, (float)(5.85 * patternScale), (float)(8.2 * patternScale));
setPatternScale(_patternScale);
}
BRISK_Impl::BRISK_Impl(const std::vector<float> &radiusList,
@@ -359,6 +372,31 @@ BRISK_Impl::BRISK_Impl(int thresh,
octaves = octaves_in;
}
void BRISK_Impl::read( const FileNode& fn)
{
// if node is empty, keep previous value
if (!fn["threshold"].empty())
fn["threshold"] >> threshold;
if (!fn["octaves"].empty())
fn["octaves"] >> octaves;
if (!fn["patternScale"].empty())
{
float _patternScale;
fn["patternScale"] >> _patternScale;
setPatternScale(_patternScale);
}
}
void BRISK_Impl::write( FileStorage& fs) const
{
if(fs.isOpened())
{
fs << "name" << getDefaultName();
fs << "threshold" << threshold;
fs << "octaves" << octaves;
fs << "patternScale" << patternScale;
}
}
void
BRISK_Impl::generateKernel(const std::vector<float> &radiusList,
const std::vector<int> &numberList,
+21
View File
@@ -539,6 +539,27 @@ public:
: threshold(_threshold), nonmaxSuppression(_nonmaxSuppression), type(_type)
{}
void read( const FileNode& fn) CV_OVERRIDE
{
// if node is empty, keep previous value
if (!fn["threshold"].empty())
fn["threshold"] >> threshold;
if (!fn["nonmaxSuppression"].empty())
fn["nonmaxSuppression"] >> nonmaxSuppression;
if (!fn["type"].empty())
fn["type"] >> type;
}
void write( FileStorage& fs) const CV_OVERRIDE
{
if(fs.isOpened())
{
fs << "name" << getDefaultName();
fs << "threshold" << threshold;
fs << "nonmaxSuppression" << nonmaxSuppression;
fs << "type" << type;
}
}
void detect( InputArray _image, std::vector<KeyPoint>& keypoints, InputArray _mask ) CV_OVERRIDE
{
CV_INSTRUMENT_REGION();
+35 -2
View File
@@ -55,6 +55,39 @@ public:
{
}
void read( const FileNode& fn) CV_OVERRIDE
{
// if node is empty, keep previous value
if (!fn["nfeatures"].empty())
fn["nfeatures"] >> nfeatures;
if (!fn["qualityLevel"].empty())
fn["qualityLevel"] >> qualityLevel;
if (!fn["minDistance"].empty())
fn["minDistance"] >> minDistance;
if (!fn["blockSize"].empty())
fn["blockSize"] >> blockSize;
if (!fn["gradSize"].empty())
fn["gradSize"] >> gradSize;
if (!fn["useHarrisDetector"].empty())
fn["useHarrisDetector"] >> useHarrisDetector;
if (!fn["k"].empty())
fn["k"] >> k;
}
void write( FileStorage& fs) const CV_OVERRIDE
{
if(fs.isOpened())
{
fs << "name" << getDefaultName();
fs << "nfeatures" << nfeatures;
fs << "qualityLevel" << qualityLevel;
fs << "minDistance" << minDistance;
fs << "blockSize" << blockSize;
fs << "gradSize" << gradSize;
fs << "useHarrisDetector" << useHarrisDetector;
fs << "k" << k;
}
}
void setMaxFeatures(int maxFeatures) CV_OVERRIDE { nfeatures = maxFeatures; }
int getMaxFeatures() const CV_OVERRIDE { return nfeatures; }
@@ -67,8 +100,8 @@ public:
void setBlockSize(int blockSize_) CV_OVERRIDE { blockSize = blockSize_; }
int getBlockSize() const CV_OVERRIDE { return blockSize; }
//void setGradientSize(int gradientSize_) { gradSize = gradientSize_; }
//int getGradientSize() { return gradSize; }
void setGradientSize(int gradientSize_) CV_OVERRIDE { gradSize = gradientSize_; }
int getGradientSize() CV_OVERRIDE { return gradSize; }
void setHarrisDetector(bool val) CV_OVERRIDE { useHarrisDetector = val; }
bool getHarrisDetector() const CV_OVERRIDE { return useHarrisDetector; }
+14 -6
View File
@@ -163,6 +163,7 @@ namespace cv
void write(FileStorage& fs) const CV_OVERRIDE
{
writeFormat(fs);
fs << "name" << getDefaultName();
fs << "extended" << (int)extended;
fs << "upright" << (int)upright;
fs << "threshold" << threshold;
@@ -173,12 +174,19 @@ namespace cv
void read(const FileNode& fn) CV_OVERRIDE
{
extended = (int)fn["extended"] != 0;
upright = (int)fn["upright"] != 0;
threshold = (float)fn["threshold"];
octaves = (int)fn["octaves"];
sublevels = (int)fn["sublevels"];
diffusivity = static_cast<KAZE::DiffusivityType>((int)fn["diffusivity"]);
// if node is empty, keep previous value
if (!fn["extended"].empty())
extended = (int)fn["extended"] != 0;
if (!fn["upright"].empty())
upright = (int)fn["upright"] != 0;
if (!fn["threshold"].empty())
threshold = (float)fn["threshold"];
if (!fn["octaves"].empty())
octaves = (int)fn["octaves"];
if (!fn["sublevels"].empty())
sublevels = (int)fn["sublevels"];
if (!fn["diffusivity"].empty())
diffusivity = static_cast<KAZE::DiffusivityType>((int)fn["diffusivity"]);
}
bool extended;
+60
View File
@@ -87,6 +87,48 @@ public:
virtual ~MSER_Impl() CV_OVERRIDE {}
void read( const FileNode& fn) CV_OVERRIDE
{
// if node is empty, keep previous value
if (!fn["delta"].empty())
fn["delta"] >> params.delta;
if (!fn["minArea"].empty())
fn["minArea"] >> params.minArea;
if (!fn["maxArea"].empty())
fn["maxArea"] >> params.maxArea;
if (!fn["maxVariation"].empty())
fn["maxVariation"] >> params.maxVariation;
if (!fn["minDiversity"].empty())
fn["minDiversity"] >> params.minDiversity;
if (!fn["maxEvolution"].empty())
fn["maxEvolution"] >> params.maxEvolution;
if (!fn["areaThreshold"].empty())
fn["areaThreshold"] >> params.areaThreshold;
if (!fn["minMargin"].empty())
fn["minMargin"] >> params.minMargin;
if (!fn["edgeBlurSize"].empty())
fn["edgeBlurSize"] >> params.edgeBlurSize;
if (!fn["pass2Only"].empty())
fn["pass2Only"] >> params.pass2Only;
}
void write( FileStorage& fs) const CV_OVERRIDE
{
if(fs.isOpened())
{
fs << "name" << getDefaultName();
fs << "delta" << params.delta;
fs << "minArea" << params.minArea;
fs << "maxArea" << params.maxArea;
fs << "maxVariation" << params.maxVariation;
fs << "minDiversity" << params.minDiversity;
fs << "maxEvolution" << params.maxEvolution;
fs << "areaThreshold" << params.areaThreshold;
fs << "minMargin" << params.minMargin;
fs << "edgeBlurSize" << params.edgeBlurSize;
fs << "pass2Only" << params.pass2Only;
}
}
void setDelta(int delta) CV_OVERRIDE { params.delta = delta; }
int getDelta() const CV_OVERRIDE { return params.delta; }
@@ -96,6 +138,24 @@ public:
void setMaxArea(int maxArea) CV_OVERRIDE { params.maxArea = maxArea; }
int getMaxArea() const CV_OVERRIDE { return params.maxArea; }
void setMaxVariation(double maxVariation) CV_OVERRIDE { params.maxVariation = maxVariation; }
double getMaxVariation() const CV_OVERRIDE { return params.maxVariation; }
void setMinDiversity(double minDiversity) CV_OVERRIDE { params.minDiversity = minDiversity; }
double getMinDiversity() const CV_OVERRIDE { return params.minDiversity; }
void setMaxEvolution(int maxEvolution) CV_OVERRIDE { params.maxEvolution = maxEvolution; }
int getMaxEvolution() const CV_OVERRIDE { return params.maxEvolution; }
void setAreaThreshold(double areaThreshold) CV_OVERRIDE { params.areaThreshold = areaThreshold; }
double getAreaThreshold() const CV_OVERRIDE { return params.areaThreshold; }
void setMinMargin(double min_margin) CV_OVERRIDE { params.minMargin = min_margin; }
double getMinMargin() const CV_OVERRIDE { return params.minMargin; }
void setEdgeBlurSize(int edge_blur_size) CV_OVERRIDE { params.edgeBlurSize = edge_blur_size; }
int getEdgeBlurSize() const CV_OVERRIDE { return params.edgeBlurSize; }
void setPass2Only(bool f) CV_OVERRIDE { params.pass2Only = f; }
bool getPass2Only() const CV_OVERRIDE { return params.pass2Only; }
+42
View File
@@ -666,6 +666,9 @@ public:
scoreType(_scoreType), patchSize(_patchSize), fastThreshold(_fastThreshold)
{}
void read( const FileNode& fn) CV_OVERRIDE;
void write( FileStorage& fs) const CV_OVERRIDE;
void setMaxFeatures(int maxFeatures) CV_OVERRIDE { nfeatures = maxFeatures; }
int getMaxFeatures() const CV_OVERRIDE { return nfeatures; }
@@ -717,6 +720,45 @@ protected:
int fastThreshold;
};
void ORB_Impl::read( const FileNode& fn)
{
// if node is empty, keep previous value
if (!fn["nfeatures"].empty())
fn["nfeatures"] >> nfeatures;
if (!fn["scaleFactor"].empty())
fn["scaleFactor"] >> scaleFactor;
if (!fn["nlevels"].empty())
fn["nlevels"] >> nlevels;
if (!fn["edgeThreshold"].empty())
fn["edgeThreshold"] >> edgeThreshold;
if (!fn["firstLevel"].empty())
fn["firstLevel"] >> firstLevel;
if (!fn["wta_k"].empty())
fn["wta_k"] >> wta_k;
if (!fn["scoreType"].empty())
fn["scoreType"] >> scoreType;
if (!fn["patchSize"].empty())
fn["patchSize"] >> patchSize;
if (!fn["fastThreshold"].empty())
fn["fastThreshold"] >> fastThreshold;
}
void ORB_Impl::write( FileStorage& fs) const
{
if(fs.isOpened())
{
fs << "name" << getDefaultName();
fs << "nfeatures" << nfeatures;
fs << "scaleFactor" << scaleFactor;
fs << "nlevels" << nlevels;
fs << "edgeThreshold" << edgeThreshold;
fs << "firstLevel" << firstLevel;
fs << "wta_k" << wta_k;
fs << "scoreType" << scoreType;
fs << "patchSize" << patchSize;
fs << "fastThreshold" << fastThreshold;
}
}
int ORB_Impl::descriptorSize() const
{
return kBytes;
+48
View File
@@ -111,6 +111,24 @@ public:
void findScaleSpaceExtrema( const std::vector<Mat>& gauss_pyr, const std::vector<Mat>& dog_pyr,
std::vector<KeyPoint>& keypoints ) const;
void read( const FileNode& fn) CV_OVERRIDE;
void write( FileStorage& fs) const CV_OVERRIDE;
void setNFeatures(int maxFeatures) CV_OVERRIDE { nfeatures = maxFeatures; }
int getNFeatures() const CV_OVERRIDE { return nfeatures; }
void setNOctaveLayers(int nOctaveLayers_) CV_OVERRIDE { nOctaveLayers = nOctaveLayers_; }
int getNOctaveLayers() const CV_OVERRIDE { return nOctaveLayers; }
void setContrastThreshold(double contrastThreshold_) CV_OVERRIDE { contrastThreshold = contrastThreshold_; }
double getContrastThreshold() const CV_OVERRIDE { return contrastThreshold; }
void setEdgeThreshold(double edgeThreshold_) CV_OVERRIDE { edgeThreshold = edgeThreshold_; }
double getEdgeThreshold() const CV_OVERRIDE { return edgeThreshold; }
void setSigma(double sigma_) CV_OVERRIDE { sigma = sigma_; }
double getSigma() const CV_OVERRIDE { return sigma; }
protected:
CV_PROP_RW int nfeatures;
CV_PROP_RW int nOctaveLayers;
@@ -554,4 +572,34 @@ void SIFT_Impl::detectAndCompute(InputArray _image, InputArray _mask,
}
}
void SIFT_Impl::read( const FileNode& fn)
{
// if node is empty, keep previous value
if (!fn["nfeatures"].empty())
fn["nfeatures"] >> nfeatures;
if (!fn["nOctaveLayers"].empty())
fn["nOctaveLayers"] >> nOctaveLayers;
if (!fn["contrastThreshold"].empty())
fn["contrastThreshold"] >> contrastThreshold;
if (!fn["edgeThreshold"].empty())
fn["edgeThreshold"] >> edgeThreshold;
if (!fn["sigma"].empty())
fn["sigma"] >> sigma;
if (!fn["descriptorType"].empty())
fn["descriptorType"] >> descriptor_type;
}
void SIFT_Impl::write( FileStorage& fs) const
{
if(fs.isOpened())
{
fs << "name" << getDefaultName();
fs << "nfeatures" << nfeatures;
fs << "nOctaveLayers" << nOctaveLayers;
fs << "contrastThreshold" << contrastThreshold;
fs << "edgeThreshold" << edgeThreshold;
fs << "sigma" << sigma;
fs << "descriptorType" << descriptor_type;
}
}
}