vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e

This commit is contained in:
Gitea Mirror Bot
2026-08-22 00:11:13 +08:00
commit 12022378a3
3872 changed files with 2513409 additions and 0 deletions
+115
View File
@@ -0,0 +1,115 @@
#include <iostream>
#include "opencv2/opencv_modules.hpp"
#ifdef HAVE_OPENCV_XFEATURES2D
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/features.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/imgcodecs.hpp>
#include <vector>
// If you find this code useful, please add a reference to the following paper in your work:
// Gil Levi and Tal Hassner, "LATCH: Learned Arrangements of Three Patch Codes", arXiv preprint arXiv:1501.03719, 15 Jan. 2015
using namespace std;
using namespace cv;
const float inlier_threshold = 2.5f; // Distance threshold to identify inliers
const float nn_match_ratio = 0.8f; // Nearest neighbor matching ratio
int main(int argc, char* argv[])
{
CommandLineParser parser(argc, argv,
"{@img1 | graf1.png | input image 1}"
"{@img2 | graf3.png | input image 2}"
"{@homography | H1to3p.xml | homography matrix}");
Mat img1 = imread( samples::findFile( parser.get<String>("@img1") ), IMREAD_GRAYSCALE);
Mat img2 = imread( samples::findFile( parser.get<String>("@img2") ), IMREAD_GRAYSCALE);
Mat homography;
FileStorage fs( samples::findFile( parser.get<String>("@homography") ), FileStorage::READ);
fs.getFirstTopLevelNode() >> homography;
vector<KeyPoint> kpts1, kpts2;
Mat desc1, desc2;
Ptr<cv::ORB> orb_detector = cv::ORB::create(10000);
Ptr<xfeatures2d::LATCH> latch = xfeatures2d::LATCH::create();
orb_detector->detect(img1, kpts1);
latch->compute(img1, kpts1, desc1);
orb_detector->detect(img2, kpts2);
latch->compute(img2, kpts2, desc2);
BFMatcher matcher(NORM_HAMMING);
vector< vector<DMatch> > nn_matches;
matcher.knnMatch(desc1, desc2, nn_matches, 2);
vector<KeyPoint> matched1, matched2, inliers1, inliers2;
vector<DMatch> good_matches;
for (size_t i = 0; i < nn_matches.size(); i++) {
DMatch first = nn_matches[i][0];
float dist1 = nn_matches[i][0].distance;
float dist2 = nn_matches[i][1].distance;
if (dist1 < nn_match_ratio * dist2) {
matched1.push_back(kpts1[first.queryIdx]);
matched2.push_back(kpts2[first.trainIdx]);
}
}
for (unsigned i = 0; i < matched1.size(); i++) {
Mat col = Mat::ones(3, 1, CV_64F);
col.at<double>(0) = matched1[i].pt.x;
col.at<double>(1) = matched1[i].pt.y;
col = homography * col;
col /= col.at<double>(2);
double dist = sqrt(pow(col.at<double>(0) - matched2[i].pt.x, 2) +
pow(col.at<double>(1) - matched2[i].pt.y, 2));
if (dist < inlier_threshold) {
int new_i = static_cast<int>(inliers1.size());
inliers1.push_back(matched1[i]);
inliers2.push_back(matched2[i]);
good_matches.push_back(DMatch(new_i, new_i, 0));
}
}
Mat res;
drawMatches(img1, inliers1, img2, inliers2, good_matches, res);
imwrite("latch_result.png", res);
double inlier_ratio = inliers1.size() * 1.0 / matched1.size();
cout << "LATCH Matching Results" << endl;
cout << "*******************************" << endl;
cout << "# Keypoints 1: \t" << kpts1.size() << endl;
cout << "# Keypoints 2: \t" << kpts2.size() << endl;
cout << "# Matches: \t" << matched1.size() << endl;
cout << "# Inliers: \t" << inliers1.size() << endl;
cout << "# Inliers Ratio: \t" << inlier_ratio << endl;
cout << endl;
imshow("result", res);
waitKey();
return 0;
}
#else
int main()
{
std::cerr << "OpenCV was built without xfeatures2d module" << std::endl;
return 0;
}
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,293 @@
#!/usr/bin/python
"""
/*********************************************************************
* Software License Agreement (BSD License)
*
* Copyright (c) 2016
*
* Balint Cristian <cristian dot balint at gmail dot com>
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/
/* export-boostdesc.py */
/* Export C headers from binary data */
// [http://infoscience.epfl.ch/record/186246/files/boostDesc_1.0.tar.gz]
"""
import sys
import struct
def float_to_hex(f):
return struct.unpack( '<I', struct.pack('<f', f) )[0]
def main():
# usage
if ( len(sys.argv) < 3 ):
print( "Usage: %s <binary-type (BGM, LBGM, BINBOOST)> <boostdesc-binary-filename>" % sys.argv[0] )
sys.exit(0)
if ( ( sys.argv[1] != "BGM" ) and
( sys.argv[1] != "LBGM" ) and
( sys.argv[1] != "BINBOOST" ) ):
print( "Invalid type [%s]" % sys.argv[1] )
sys.exit(0)
# enum literals
Assign = [ "ASSIGN_HARD",
"ASSIGN_BILINEAR",
"ASSIGN_SOFT",
"ASSIGN_HARD_MAGN",
"ASSIGN_SOFT_MAGN" ]
# open binary data file
f = open( sys.argv[2], 'rb' )
# header
print "/*"
print " *"
print " * Header exported from binary."
print " * [%s %s %s]" % ( sys.argv[0], sys.argv[1], sys.argv[2] )
print " *"
print " */"
# ini
nDim = 1;
nWLs = 0;
# dimensionality (where is the case)
if ( ( sys.argv[1] == "LBGM" ) or
( sys.argv[1] == "BINBOOST" ) ):
nDim = struct.unpack( '<i', f.read(4) )[0]
print
print "// dimensionality of learner"
print "static const int nDim = %i;" % nDim
# week learners (where is the case)
if ( sys.argv[1] != "BINBOOST" ):
nWLs = struct.unpack( '<i', f.read(4) )[0]
# common header
orientQuant = struct.unpack( '<i', f.read(4) )[0]
patchSize = struct.unpack( '<i', f.read(4) )[0]
iGradAssignType = struct.unpack( '<i', f.read(4) )[0]
print
print "// orientations"
print "static const int orientQuant = %i;" % orientQuant
print
print "// patch size"
print "static const int patchSize = %i;" % patchSize
print
print "// gradient assignment type"
print "static const int iGradAssignType = %s;" % Assign[iGradAssignType]
arr_thresh = ""
arr_orient = ""
arr__y_min = ""
arr__y_max = ""
arr__x_min = ""
arr__x_max = ""
arr__alpha = ""
arr___beta = ""
dims = nDim
if ( sys.argv[1] == "LBGM" ):
dims = 1
# iterate each dimension
for d in range( 0, dims ):
if ( sys.argv[1] == "BINBOOST" ):
nWLs = struct.unpack( '<i', f.read(4) )[0]
if ( d == 0 ):
print
print "// number of weak learners"
print "static const int nWLs = %i;" % nWLs
# iterate each members
for i in range( 0, nWLs ):
# unpack structure array
thresh = struct.unpack( '<f', f.read(4) )[0]
orient = struct.unpack( '<i', f.read(4) )[0]
y_min = struct.unpack( '<i', f.read(4) )[0]
y_max = struct.unpack( '<i', f.read(4) )[0]
x_min = struct.unpack( '<i', f.read(4) )[0]
x_max = struct.unpack( '<i', f.read(4) )[0]
alpha = struct.unpack( '<f', f.read(4) )[0]
beta = 0
if ( sys.argv[1] == "BINBOOST" ):
beta = struct.unpack( '<f', f.read(4) )[0]
# first entry
if ( d*dims + i == 0 ):
arr_thresh += "\n"
arr_thresh += "// threshold array (%s x %s)\n" % (dims,nWLs)
arr_thresh += "static const unsigned int thresh[] =\n{\n"
arr_orient += "\n"
arr_orient += "// orientation array (%s x %s)\n" % (dims,nWLs)
arr_orient += "static const int orient[] =\n{\n"
arr__y_min += "\n"
arr__y_min += "// Y min array (%s x %s)\n" % (dims,nWLs)
arr__y_min += "static const int y_min[] =\n{\n"
arr__y_max += "\n"
arr__y_max += "// Y max array (%s x %s)\n" % (dims,nWLs)
arr__y_max += "static const int y_max[] =\n{\n"
arr__x_min += "\n"
arr__x_min += "// X min array (%s x %s)\n" % (dims,nWLs)
arr__x_min += "static const int x_min[] =\n{\n"
arr__x_max += "\n"
arr__x_max += "// X max array (%s x %s)\n" % (dims,nWLs)
arr__x_max += "static const int x_max[] =\n{\n"
arr__alpha += "\n"
arr__alpha += "// alpha array (%s x %s)\n" % (dims,nWLs)
arr__alpha += "static const unsigned int alpha[] =\n{\n"
if ( sys.argv[1] == "BINBOOST" ):
arr___beta += "\n"
arr___beta += "// beta array (%s x %s)\n" % (dims,nWLs)
arr___beta += "static const unsigned int beta[] =\n{\n"
# last entry
if ( i == nWLs - 1 ) and ( d == dims - 1):
arr_thresh += " 0x%08x\n};" % float_to_hex(thresh)
arr_orient += " 0x%02x\n};" % orient
arr__y_min += " 0x%02x\n};" % y_min
arr__y_max += " 0x%02x\n};" % y_max
arr__x_min += " 0x%02x\n};" % x_min
arr__x_max += " 0x%02x\n};" % x_max
arr__alpha += " 0x%08x\n};" % float_to_hex(alpha)
if ( sys.argv[1] == "BINBOOST" ):
arr___beta += " 0x%08x\n};" % float_to_hex(beta)
break
# align entries
if ( (d*dims + i + 1) % 8 ):
arr_thresh += " 0x%08x," % float_to_hex(thresh)
arr_orient += " 0x%02x," % orient
arr__y_min += " 0x%02x," % y_min
arr__y_max += " 0x%02x," % y_max
arr__x_min += " 0x%02x," % x_min
arr__x_max += " 0x%02x," % x_max
arr__alpha += " 0x%08x," % float_to_hex(alpha)
if ( sys.argv[1] == "BINBOOST" ):
arr___beta += " 0x%08x," % float_to_hex(beta)
else:
arr_thresh += " 0x%08x,\n" % float_to_hex(thresh)
arr_orient += " 0x%02x,\n" % orient
arr__y_min += " 0x%02x,\n" % y_min
arr__y_max += " 0x%02x,\n" % y_max
arr__x_min += " 0x%02x,\n" % x_min
arr__x_max += " 0x%02x,\n" % x_max
arr__alpha += " 0x%08x,\n" % float_to_hex(alpha)
if ( sys.argv[1] == "BINBOOST" ):
arr___beta += " 0x%08x,\n" % float_to_hex(beta)
# extra array (when LBGM)
if ( sys.argv[1] == "LBGM" ):
arr___beta += "\n"
arr___beta += "// beta array (%s x %s)\n" % (nWLs,nDim)
arr___beta += "static const unsigned int beta[] =\n{\n"
for i in range( 0, nWLs ):
for d in range( 0, nDim ):
beta = struct.unpack( '<f', f.read(4) )[0]
# last entry
if ( i == nWLs-1 ) and ( d == nDim-1 ):
arr___beta += " 0x%08x\n};" % float_to_hex(beta)
break
# align entries
if ( (i*nDim + d + 1) % 8 ):
arr___beta += " 0x%08x," % float_to_hex(beta)
else:
arr___beta += " 0x%08x,\n" % float_to_hex(beta)
# release
f.close()
# dump on screen
print arr_thresh
print arr_orient
print arr__y_min
print arr__y_max
print arr__x_min
print arr__x_max
print arr__alpha
if ( ( sys.argv[1] == "LBGM" ) or
( sys.argv[1] == "BINBOOST" ) ):
print arr___beta
if __name__ == "__main__":
main()
+138
View File
@@ -0,0 +1,138 @@
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/features.hpp>
#include <opencv2/flann.hpp>
#include <opencv2/xfeatures2d.hpp>
using namespace cv;
using namespace cv::xfeatures2d;
////////////////////////////////////////////////////
// This program demonstrates the GMS matching strategy.
int main(int argc, char* argv[])
{
const char* keys =
"{ h help | | print help message }"
"{ l left | | specify left (reference) image }"
"{ r right | | specify right (query) image }"
"{ camera | 0 | specify the camera device number }"
"{ nfeatures | 10000 | specify the maximum number of ORB features }"
"{ fastThreshold | 20 | specify the FAST threshold }"
"{ drawSimple | true | do not draw not matched keypoints }"
"{ withRotation | false | take rotation into account }"
"{ withScale | false | take scale into account }";
CommandLineParser cmd(argc, argv, keys);
if (cmd.has("help"))
{
std::cout << "Usage: gms_matcher [options]" << std::endl;
std::cout << "Available options:" << std::endl;
cmd.printMessage();
return EXIT_SUCCESS;
}
Ptr<Feature2D> orb = ORB::create(cmd.get<int>("nfeatures"));
orb.dynamicCast<cv::ORB>()->setFastThreshold(cmd.get<int>("fastThreshold"));
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");
if (!cmd.get<String>("left").empty() && !cmd.get<String>("right").empty())
{
Mat imgL = imread(cmd.get<String>("left"));
Mat imgR = imread(cmd.get<String>("right"));
std::vector<KeyPoint> kpRef, kpCur;
Mat descRef, descCur;
orb->detectAndCompute(imgL, noArray(), kpRef, descRef);
orb->detectAndCompute(imgR, noArray(), kpCur, descCur);
std::vector<DMatch> matchesAll, matchesGMS;
matcher->match(descCur, descRef, matchesAll);
matchGMS(imgR.size(), imgL.size(), kpCur, kpRef, matchesAll, matchesGMS, cmd.get<bool>("withRotation"), cmd.get<bool>("withScale"));
std::cout << "matchesGMS: " << matchesGMS.size() << std::endl;
Mat frameMatches;
if (cmd.get<bool>("drawSimple"))
drawMatches(imgR, kpCur, imgL, kpRef, matchesGMS, frameMatches, Scalar::all(-1), Scalar::all(-1),
std::vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
else
drawMatches(imgR, kpCur, imgL, kpRef, matchesGMS, frameMatches);
imshow("Matches GMS", frameMatches);
waitKey();
}
else
{
std::vector<KeyPoint> kpRef;
Mat descRef;
VideoCapture capture(cmd.get<int>("camera"));
//Camera warm-up
for (int i = 0; i < 10; i++)
{
Mat frame;
capture >> frame;
}
Mat frameRef;
for (;;)
{
Mat frame;
capture >> frame;
if (frameRef.empty())
{
frame.copyTo(frameRef);
orb->detectAndCompute(frameRef, noArray(), kpRef, descRef);
}
TickMeter tm;
tm.start();
std::vector<KeyPoint> kp;
Mat desc;
orb->detectAndCompute(frame, noArray(), kp, desc);
tm.stop();
double t_orb = tm.getTimeMilli();
tm.reset();
tm.start();
std::vector<DMatch> matchesAll, matchesGMS;
matcher->match(desc, descRef, matchesAll);
tm.stop();
double t_match = tm.getTimeMilli();
matchGMS(frame.size(), frameRef.size(), kp, kpRef, matchesAll, matchesGMS, cmd.get<bool>("withRotation"), cmd.get<bool>("withScale"));
tm.stop();
Mat frameMatches;
if (cmd.get<bool>("drawSimple"))
drawMatches(frame, kp, frameRef, kpRef, matchesGMS, frameMatches, Scalar::all(-1), Scalar::all(-1),
std::vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
else
drawMatches(frame, kp, frameRef, kpRef, matchesGMS, frameMatches);
String label = format("ORB: %.2f ms", t_orb);
putText(frameMatches, label, Point(20, 20), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0,0,255));
label = format("Matching: %.2f ms", t_match);
putText(frameMatches, label, Point(20, 40), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0,0,255));
label = format("GMS matching: %.2f ms", tm.getTimeMilli());
putText(frameMatches, label, Point(20, 60), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0,0,255));
putText(frameMatches, "Press r to reinitialize the reference image.", Point(frameMatches.cols-380, 20), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0,0,255));
putText(frameMatches, "Press esc to quit.", Point(frameMatches.cols-180, 40), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0,0,255));
imshow("Matches GMS", frameMatches);
int c = waitKey(30);
if (c == 27)
break;
else if (c == 'r')
{
frame.copyTo(frameRef);
orb->detectAndCompute(frameRef, noArray(), kpRef, descRef);
}
}
}
return EXIT_SUCCESS;
}
@@ -0,0 +1,172 @@
/*
By downloading, copying, installing or using the software you agree to this license.
If you do not agree to this license, do not download, install,
copy or use the software.
License Agreement
For Open Source Computer Vision Library
(3-clause BSD License)
Copyright (C) 2000-2016, Intel Corporation, all rights reserved.
Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
Copyright (C) 2009-2016, NVIDIA Corporation, all rights reserved.
Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved.
Copyright (C) 2015-2016, OpenCV Foundation, all rights reserved.
Copyright (C) 2015-2016, Itseez Inc., all rights reserved.
Third party copyrights are property of their respective owners.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the names of the copyright holders nor the names of the contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are disclaimed.
In no event shall copyright holders or contributors be liable for any direct,
indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused
and on any theory of liability, whether in contract, strict liability,
or tort (including negligence or otherwise) arising in any way out of
the use of this software, even if advised of the possibility of such damage.
*/
/*
Contributed by Gregor Kovalcik <gregor dot kovalcik at gmail dot com>
based on code provided by Martin Krulis, Jakub Lokoc and Tomas Skopal.
References:
Martin Krulis, Jakub Lokoc, Tomas Skopal.
Efficient Extraction of Clustering-Based Feature Signatures Using GPU Architectures.
Multimedia tools and applications, 75(13), pp.: 80718103, Springer, ISSN: 1380-7501, 2016
Christian Beecks, Merih Seran Uysal, Thomas Seidl.
Signature quadratic form distance.
In Proceedings of the ACM International Conference on Image and Video Retrieval, pages 438-445.
ACM, 2010.
*/
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <iostream>
#include <string>
using namespace std;
using namespace cv;
using namespace xfeatures2d;
void printHelpMessage(void);
void printHelpMessage(void)
{
cout << "Example of the PCTSignatures algorithm computing and visualizing\n"
"image signature for one image, or comparing multiple images with the first\n"
"image using the signature quadratic form distance.\n\n"
"Usage: pct_signatures ImageToProcessAndDisplay\n"
"or: pct_signatures ReferenceImage [ImagesToCompareWithTheReferenceImage]\n\n"
"The program has 2 modes:\n"
"- single argument: program computes and visualizes the image signature\n"
"- multiple arguments: program compares the first image to the others\n"
" using pct signatures and signature quadratic form distance (SQFD)";
}
/** @brief
Example of the PCTSignatures algorithm.
The program has 2 modes:
- single argument mode, where the program computes and visualizes the image signature
- multiple argument mode, where the program compares the first image to the others
using signatures and signature quadratic form distance (SQFD)
*/
int main(int argc, char** argv)
{
if (argc < 2) // Check arguments
{
printHelpMessage();
return 1;
}
Mat source;
source = imread(argv[1]); // Read the file
if (!source.data) // Check for invalid input
{
cerr << "Could not open or find the image: " << argv[1];
return -1;
}
Mat signature, result; // define variables
int initSampleCount = 2000;
int initSeedCount = 400;
int grayscaleBitsPerPixel = 4;
vector<Point2f> initPoints;
namedWindow("Source", WINDOW_AUTOSIZE); // Create windows for display.
namedWindow("Result", WINDOW_AUTOSIZE);
// create the algorithm
PCTSignatures::generateInitPoints(initPoints, initSampleCount, PCTSignatures::UNIFORM);
Ptr<PCTSignatures> pctSignatures = PCTSignatures::create(initPoints, initSeedCount);
pctSignatures->setGrayscaleBits(grayscaleBitsPerPixel);
// compute and visualize the first image
double start = (double)getTickCount();
pctSignatures->computeSignature(source, signature);
double end = (double)getTickCount();
cout << "Signature of the reference image computed in " << (end - start) / (getTickFrequency() * 1.0f) << " seconds." << endl;
PCTSignatures::drawSignature(source, signature, result);
imshow("Source", source); // show the result
imshow("Result", result);
if (argc == 2) // single image -> finish right after the visualization
{
waitKey(0); // Wait for user input
return 0;
}
// multiple images -> compare to the first one
else
{
vector<Mat> images;
vector<Mat> signatures;
vector<float> distances;
for (int i = 2; i < argc; i++)
{
Mat image = imread(argv[i]);
if (!source.data) // Check for invalid input
{
cerr << "Could not open or find the image: " << argv[i] << std::endl;
return 1;
}
images.push_back(image);
}
pctSignatures->computeSignatures(images, signatures);
Ptr<PCTSignaturesSQFD> pctSQFD = PCTSignaturesSQFD::create();
pctSQFD->computeQuadraticFormDistances(signature, signatures, distances);
for (int i = 0; i < (int)(distances.size()); i++)
{
cout << "Image: " << argv[i + 2] << ", similarity: " << distances[i] << endl;
}
waitKey(0); // Wait for user input
}
return 0;
}
+170
View File
@@ -0,0 +1,170 @@
/*
By downloading, copying, installing or using the software you agree to this license.
If you do not agree to this license, do not download, install,
copy or use the software.
License Agreement
For Open Source Computer Vision Library
(3-clause BSD License)
Copyright (C) 2000-2016, Intel Corporation, all rights reserved.
Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
Copyright (C) 2009-2016, NVIDIA Corporation, all rights reserved.
Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved.
Copyright (C) 2015-2016, OpenCV Foundation, all rights reserved.
Copyright (C) 2015-2016, Itseez Inc., all rights reserved.
Third party copyrights are property of their respective owners.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the names of the copyright holders nor the names of the contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are disclaimed.
In no event shall copyright holders or contributors be liable for any direct,
indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused
and on any theory of liability, whether in contract, strict liability,
or tort (including negligence or otherwise) arising in any way out of
the use of this software, even if advised of the possibility of such damage.
*/
/*
Contributed by Gregor Kovalcik <gregor dot kovalcik at gmail dot com>
based on code provided by Martin Krulis, Jakub Lokoc and Tomas Skopal.
References:
Martin Krulis, Jakub Lokoc, Tomas Skopal.
Efficient Extraction of Clustering-Based Feature Signatures Using GPU Architectures.
Multimedia tools and applications, 75(13), pp.: 80718103, Springer, ISSN: 1380-7501, 2016
Christian Beecks, Merih Seran Uysal, Thomas Seidl.
Signature quadratic form distance.
In Proceedings of the ACM International Conference on Image and Video Retrieval, pages 438-445.
ACM, 2010.
*/
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <iostream>
#include <string>
using namespace std;
using namespace cv;
using namespace xfeatures2d;
void printHelpMessage(void);
void printHelpMessage(void)
{
cout << "Example of the PCTSignatures algorithm.\n\n"
"This program computes and visualizes position-color-texture signatures\n"
"using images from webcam if available.\n\n"
"Usage:\n"
"pct_webcam [sample_count] [seed_count]\n"
"Note: sample_count must be greater or equal to seed_count.";
}
/** @brief
Example of the PCTSignatures algorithm.
This program computes and visualizes position-color-texture signatures
of images taken from webcam if available.
*/
int main(int argc, char** argv)
{
// define variables
Mat frame, signature, result;
int initSampleCount = 2000;
int initSeedCount = 400;
int grayscaleBitsPerPixel = 4;
// parse for help argument
{
for (int i = 1; i < argc; i++)
{
if ((string)argv[i] == "-h" || (string)argv[i] == "--help")
{
printHelpMessage();
return 0;
}
}
}
// parse optional arguments
if (argc > 1) // sample count
{
initSampleCount = atoi(argv[1]);
if (initSampleCount <= 0)
{
cerr << "Sample count have to be a positive integer: " << argv[1] << endl;
return 1;
}
initSeedCount = (int)floor(static_cast<float>(initSampleCount / 4));
initSeedCount = std::max(1, initSeedCount); // fallback if sample count == 1
}
if (argc > 2) // seed count
{
initSeedCount = atoi(argv[2]);
if (initSeedCount <= 0)
{
cerr << "Seed count have to be a positive integer: " << argv[2] << endl;
return 1;
}
if (initSeedCount > initSampleCount)
{
cerr << "Seed count have to be lower or equal to sample count!" << endl;
return 1;
}
}
// create algorithm
Ptr<PCTSignatures> pctSignatures = PCTSignatures::create(initSampleCount, initSeedCount, PCTSignatures::UNIFORM);
pctSignatures->setGrayscaleBits(grayscaleBitsPerPixel);
// open video capture device
VideoCapture videoCapture;
if (!videoCapture.open(0))
{
cerr << "Unable to open the first video capture device with ID = 0!" << endl;
return 1;
}
// Create windows for display.
namedWindow("Source", WINDOW_AUTOSIZE);
namedWindow("Result", WINDOW_AUTOSIZE);
// run drawing loop
for (;;)
{
videoCapture >> frame;
if (frame.empty()) break; // end of video stream
pctSignatures->computeSignature(frame, signature);
PCTSignatures::drawSignature(Mat::zeros(frame.size(), frame.type()), signature, result);
imshow("Source", frame); // Show our images inside the windows.
imshow("Result", result);
if (waitKey(1) == 27) break; // stop videocapturing by pressing ESC
}
return 0;
}
@@ -0,0 +1,89 @@
/*
* shape_context.cpp -- Shape context demo for shape matching
*/
#include <iostream>
#include "opencv2/opencv_modules.hpp"
#ifdef HAVE_OPENCV_SHAPE
#include "opencv2/shape.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/features.hpp"
#include "opencv2/xfeatures2d.hpp"
#include "opencv2/core/utility.hpp"
#include <string>
using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;
static void help()
{
printf("\nThis program demonstrates how to use common interface for shape transformers\n"
"Call\n"
"shape_transformation [image1] [image2]\n");
}
int main(int argc, char** argv)
{
help();
if (argc < 3)
{
printf("Not enough parameters\n");
return -1;
}
Mat img1 = imread(argv[1], IMREAD_GRAYSCALE);
Mat img2 = imread(argv[2], IMREAD_GRAYSCALE);
if(img1.empty() || img2.empty())
{
printf("Can't read one of the images\n");
return -1;
}
// detecting keypoints & computing descriptors
Ptr<SURF> surf = SURF::create(5000);
vector<KeyPoint> keypoints1, keypoints2;
Mat descriptors1, descriptors2;
surf->detectAndCompute(img1, Mat(), keypoints1, descriptors1);
surf->detectAndCompute(img2, Mat(), keypoints2, descriptors2);
// matching descriptors
BFMatcher matcher(surf->defaultNorm());
vector<DMatch> matches;
matcher.match(descriptors1, descriptors2, matches);
// drawing the results
namedWindow("matches", 1);
Mat img_matches;
drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches);
imshow("matches", img_matches);
// extract points
vector<Point2f> pts1, pts2;
for (size_t ii=0; ii<keypoints1.size(); ii++)
pts1.push_back( keypoints1[ii].pt );
for (size_t ii=0; ii<keypoints2.size(); ii++)
pts2.push_back( keypoints2[ii].pt );
// Apply TPS
Ptr<ThinPlateSplineShapeTransformer> mytps = createThinPlateSplineShapeTransformer(25000); //TPS with a relaxed constraint
mytps->estimateTransformation(pts1, pts2, matches);
mytps->warpImage(img2, img2);
imshow("Tranformed", img2);
waitKey(0);
return 0;
}
#else
int main()
{
std::cerr << "OpenCV was built without shape module" << std::endl;
return 0;
}
#endif // HAVE_OPENCV_SHAPE
@@ -0,0 +1,225 @@
#include <iostream>
#include <stdio.h>
#include "opencv2/core.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/features.hpp"
#include "opencv2/geometry.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/xfeatures2d.hpp"
using namespace cv;
using namespace cv::xfeatures2d;
const int LOOP_NUM = 10;
const int GOOD_PTS_MAX = 50;
const float GOOD_PORTION = 0.15f;
int64 work_begin = 0;
int64 work_end = 0;
static void workBegin()
{
work_begin = getTickCount();
}
static void workEnd()
{
work_end = getTickCount() - work_begin;
}
static double getTime()
{
return work_end /((double)getTickFrequency() )* 1000.;
}
struct SURFDetector
{
Ptr<Feature2D> surf;
SURFDetector(double hessian = 800.0)
{
surf = SURF::create(hessian);
}
template<class T>
void operator()(const T& in, const T& mask, std::vector<cv::KeyPoint>& pts, T& descriptors, bool useProvided = false)
{
surf->detectAndCompute(in, mask, pts, descriptors, useProvided);
}
};
template<class KPMatcher>
struct SURFMatcher
{
KPMatcher matcher;
template<class T>
void match(const T& in1, const T& in2, std::vector<cv::DMatch>& matches)
{
matcher.match(in1, in2, matches);
}
};
static Mat drawGoodMatches(
const Mat& img1,
const Mat& img2,
const std::vector<KeyPoint>& keypoints1,
const std::vector<KeyPoint>& keypoints2,
std::vector<DMatch>& matches,
std::vector<Point2f>& scene_corners_
)
{
//-- Sort matches and preserve top 10% matches
std::sort(matches.begin(), matches.end());
std::vector< DMatch > good_matches;
double minDist = matches.front().distance;
double maxDist = matches.back().distance;
const int ptsPairs = std::min(GOOD_PTS_MAX, (int)(matches.size() * GOOD_PORTION));
for( int i = 0; i < ptsPairs; i++ )
{
good_matches.push_back( matches[i] );
}
std::cout << "\nMax distance: " << maxDist << std::endl;
std::cout << "Min distance: " << minDist << std::endl;
std::cout << "Calculating homography using " << ptsPairs << " point pairs." << std::endl;
// drawing the results
Mat img_matches;
drawMatches( img1, keypoints1, img2, keypoints2,
good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
std::vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
//-- Localize the object
std::vector<Point2f> obj;
std::vector<Point2f> scene;
for( size_t i = 0; i < good_matches.size(); i++ )
{
//-- Get the keypoints from the good matches
obj.push_back( keypoints1[ good_matches[i].queryIdx ].pt );
scene.push_back( keypoints2[ good_matches[i].trainIdx ].pt );
}
//-- Get the corners from the image_1 ( the object to be "detected" )
std::vector<Point2f> obj_corners(4);
obj_corners[0] = Point(0,0);
obj_corners[1] = Point( img1.cols, 0 );
obj_corners[2] = Point( img1.cols, img1.rows );
obj_corners[3] = Point( 0, img1.rows );
std::vector<Point2f> scene_corners(4);
Mat H = findHomography( obj, scene, RANSAC );
perspectiveTransform( obj_corners, scene_corners, H);
scene_corners_ = scene_corners;
//-- Draw lines between the corners (the mapped object in the scene - image_2 )
line( img_matches,
scene_corners[0] + Point2f( (float)img1.cols, 0), scene_corners[1] + Point2f( (float)img1.cols, 0),
Scalar( 0, 255, 0), 2, LINE_AA );
line( img_matches,
scene_corners[1] + Point2f( (float)img1.cols, 0), scene_corners[2] + Point2f( (float)img1.cols, 0),
Scalar( 0, 255, 0), 2, LINE_AA );
line( img_matches,
scene_corners[2] + Point2f( (float)img1.cols, 0), scene_corners[3] + Point2f( (float)img1.cols, 0),
Scalar( 0, 255, 0), 2, LINE_AA );
line( img_matches,
scene_corners[3] + Point2f( (float)img1.cols, 0), scene_corners[0] + Point2f( (float)img1.cols, 0),
Scalar( 0, 255, 0), 2, LINE_AA );
return img_matches;
}
////////////////////////////////////////////////////
// This program demonstrates the usage of SURF_OCL.
// use cpu findHomography interface to calculate the transformation matrix
int main(int argc, char* argv[])
{
const char* keys =
"{ h help | | print help message }"
"{ l left | box.png | specify left image }"
"{ r right | box_in_scene.png | specify right image }"
"{ o output | SURF_output.jpg | specify output save path }"
"{ m cpu_mode | | run without OpenCL }";
CommandLineParser cmd(argc, argv, keys);
if (cmd.has("help"))
{
std::cout << "Usage: surf_matcher [options]" << std::endl;
std::cout << "Available options:" << std::endl;
cmd.printMessage();
return EXIT_SUCCESS;
}
if (cmd.has("cpu_mode"))
{
ocl::setUseOpenCL(false);
std::cout << "OpenCL was disabled" << std::endl;
}
UMat img1, img2;
std::string outpath = cmd.get<std::string>("o");
std::string leftName = cmd.get<std::string>("l");
imread(leftName, IMREAD_GRAYSCALE).copyTo(img1);
if(img1.empty())
{
std::cout << "Couldn't load " << leftName << std::endl;
cmd.printMessage();
return EXIT_FAILURE;
}
std::string rightName = cmd.get<std::string>("r");
imread(rightName, IMREAD_GRAYSCALE).copyTo(img2);
if(img2.empty())
{
std::cout << "Couldn't load " << rightName << std::endl;
cmd.printMessage();
return EXIT_FAILURE;
}
double surf_time = 0.;
//declare input/output
std::vector<KeyPoint> keypoints1, keypoints2;
std::vector<DMatch> matches;
UMat _descriptors1, _descriptors2;
Mat descriptors1 = _descriptors1.getMat(ACCESS_RW),
descriptors2 = _descriptors2.getMat(ACCESS_RW);
//instantiate detectors/matchers
SURFDetector surf;
SURFMatcher<BFMatcher> matcher;
//-- start of timing section
for (int i = 0; i <= LOOP_NUM; i++)
{
if(i == 1) workBegin();
surf(img1.getMat(ACCESS_READ), Mat(), keypoints1, descriptors1);
surf(img2.getMat(ACCESS_READ), Mat(), keypoints2, descriptors2);
matcher.match(descriptors1, descriptors2, matches);
}
workEnd();
std::cout << "FOUND " << keypoints1.size() << " keypoints on first image" << std::endl;
std::cout << "FOUND " << keypoints2.size() << " keypoints on second image" << std::endl;
surf_time = getTime();
std::cout << "SURF run time: " << surf_time / LOOP_NUM << " ms" << std::endl<<"\n";
std::vector<Point2f> corner;
Mat img_matches = drawGoodMatches(img1.getMat(ACCESS_READ), img2.getMat(ACCESS_READ), keypoints1, keypoints2, matches, corner);
//-- Show detected matches
namedWindow("surf matches", 0);
imshow("surf matches", img_matches);
imwrite(outpath, img_matches);
waitKey(0);
return EXIT_SUCCESS;
}
@@ -0,0 +1,248 @@
/*
* video_homography.cpp
*
* Created on: Oct 18, 2010
* Author: erublee
*/
#include <iostream>
#include "opencv2/opencv_modules.hpp"
#ifdef HAVE_OPENCV_3D
#include "opencv2/geometry.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/features.hpp"
#include "opencv2/xfeatures2d.hpp"
#include <list>
#include <vector>
using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;
static void help(char **av)
{
cout << "\nThis program demonstrated the use of features with the Fast corner detector and brief descriptors\n"
<< "to track planar objects by computing their homography from the key (training) image to the query (test) image\n\n" << endl;
cout << "usage: " << av[0] << " <video device number>\n" << endl;
cout << "The following keys do stuff:" << endl;
cout << " t : grabs a reference frame to match against" << endl;
cout << " l : makes the reference frame new every frame" << endl;
cout << " q or escape: quit" << endl;
}
namespace
{
void drawMatchesRelative(const vector<KeyPoint>& train, const vector<KeyPoint>& query,
std::vector<cv::DMatch>& matches, Mat& img, const vector<unsigned char>& mask = vector<
unsigned char> ())
{
for (int i = 0; i < (int)matches.size(); i++)
{
if (mask.empty() || mask[i])
{
Point2f pt_new = query[matches[i].queryIdx].pt;
Point2f pt_old = train[matches[i].trainIdx].pt;
cv::line(img, pt_new, pt_old, Scalar(125, 255, 125), 1);
cv::circle(img, pt_new, 2, Scalar(255, 0, 125), 1);
}
}
}
//Takes a descriptor and turns it into an xy point
void keypoints2points(const vector<KeyPoint>& in, vector<Point2f>& out)
{
out.clear();
out.reserve(in.size());
for (size_t i = 0; i < in.size(); ++i)
{
out.push_back(in[i].pt);
}
}
//Takes an xy point and appends that to a keypoint structure
void points2keypoints(const vector<Point2f>& in, vector<KeyPoint>& out)
{
out.clear();
out.reserve(in.size());
for (size_t i = 0; i < in.size(); ++i)
{
out.push_back(KeyPoint(in[i], 1));
}
}
//Uses computed homography H to warp original input points to new planar position
void warpKeypoints(const Mat& H, const vector<KeyPoint>& in, vector<KeyPoint>& out)
{
vector<Point2f> pts;
keypoints2points(in, pts);
vector<Point2f> pts_w(pts.size());
Mat m_pts_w(pts_w);
perspectiveTransform(Mat(pts), m_pts_w, H);
points2keypoints(pts_w, out);
}
//Converts matching indices to xy points
void matches2points(const vector<KeyPoint>& train, const vector<KeyPoint>& query,
const std::vector<cv::DMatch>& matches, std::vector<cv::Point2f>& pts_train,
std::vector<Point2f>& pts_query)
{
pts_train.clear();
pts_query.clear();
pts_train.reserve(matches.size());
pts_query.reserve(matches.size());
size_t i = 0;
for (; i < matches.size(); i++)
{
const DMatch & dmatch = matches[i];
pts_query.push_back(query[dmatch.queryIdx].pt);
pts_train.push_back(train[dmatch.trainIdx].pt);
}
}
void resetH(Mat&H)
{
H = Mat::eye(3, 3, CV_32FC1);
}
}
int main(int ac, char ** av)
{
if (ac != 2)
{
help(av);
return 1;
}
Ptr<BriefDescriptorExtractor> brief = BriefDescriptorExtractor::create(32);
VideoCapture capture;
capture.open(atoi(av[1]));
if (!capture.isOpened())
{
help(av);
cout << "capture device " << atoi(av[1]) << " failed to open!" << endl;
return 1;
}
cout << "following keys do stuff:" << endl;
cout << "t : grabs a reference frame to match against" << endl;
cout << "l : makes the reference frame new every frame" << endl;
cout << "q or escape: quit" << endl;
Mat frame;
vector<DMatch> matches;
BFMatcher desc_matcher(brief->defaultNorm());
vector<Point2f> train_pts, query_pts;
vector<KeyPoint> train_kpts, query_kpts;
vector<unsigned char> match_mask;
Mat gray;
bool ref_live = true;
Mat train_desc, query_desc;
Ptr<FastFeatureDetector> detector = FastFeatureDetector::create(10, true);
Mat H_prev = Mat::eye(3, 3, CV_32FC1);
for (;;)
{
capture >> frame;
if (frame.empty())
break;
cvtColor(frame, gray, COLOR_RGB2GRAY);
detector->detect(gray, query_kpts); //Find interest points
brief->compute(gray, query_kpts, query_desc); //Compute brief descriptors at each keypoint location
if (!train_kpts.empty())
{
vector<KeyPoint> test_kpts;
warpKeypoints(H_prev.inv(), query_kpts, test_kpts);
//Mat mask = windowedMatchingMask(test_kpts, train_kpts, 25, 25);
desc_matcher.match(query_desc, train_desc, matches, Mat());
drawKeypoints(frame, test_kpts, frame, Scalar(255, 0, 0), DrawMatchesFlags::DRAW_OVER_OUTIMG);
matches2points(train_kpts, query_kpts, matches, train_pts, query_pts);
if (matches.size() > 5)
{
Mat H = findHomography(train_pts, query_pts, RANSAC, 4, match_mask);
if (countNonZero(Mat(match_mask)) > 15)
{
H_prev = H;
}
else
resetH(H_prev);
drawMatchesRelative(train_kpts, query_kpts, matches, frame, match_mask);
}
else
resetH(H_prev);
}
else
{
H_prev = Mat::eye(3, 3, CV_32FC1);
Mat out;
drawKeypoints(gray, query_kpts, out);
frame = out;
}
imshow("frame", frame);
if (ref_live)
{
train_kpts = query_kpts;
query_desc.copyTo(train_desc);
}
char key = (char)waitKey(2);
switch (key)
{
case 'l':
ref_live = true;
resetH(H_prev);
break;
case 't':
ref_live = false;
train_kpts = query_kpts;
query_desc.copyTo(train_desc);
resetH(H_prev);
break;
case 27:
case 'q':
return 0;
break;
}
}
return 0;
}
#else
int main()
{
std::cerr << "OpenCV was built without 3d module" << std::endl;
return 0;
}
#endif