parent
3b207a77f8
commit
d191729b46
15 changed files with 1081 additions and 108 deletions
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 792 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 56 KiB |
@ -0,0 +1,169 @@ |
||||
#include <opencv2/line_descriptor.hpp> |
||||
|
||||
#include "opencv2/core/utility.hpp" |
||||
#include "opencv2/core/private.hpp" |
||||
#include <opencv2/imgproc.hpp> |
||||
#include <opencv2/features2d.hpp> |
||||
#include <opencv2/highgui.hpp> |
||||
|
||||
#include <iostream> |
||||
#include <vector> |
||||
|
||||
using namespace cv; |
||||
|
||||
static const char* keys = |
||||
{ |
||||
"{@image_path1 | | Image path 1 }" |
||||
"{@image_path2 | | Image path 2 }" |
||||
}; |
||||
|
||||
static void help() |
||||
{ |
||||
std::cout << "\nThis example shows the functionalities of descriptors matching\n" << |
||||
"Please, run this sample using a command in the form\n" << |
||||
"./example_line_descriptor_matching <path_to_input_image 1>" |
||||
<< "<path_to_input_image 2>" << std::endl; |
||||
|
||||
} |
||||
|
||||
/* invert numBits bits in input char */ |
||||
uchar invertSingleBits (uchar dividend_char, int numBits) |
||||
{ |
||||
std::vector<int> bin_vector; |
||||
long dividend; |
||||
long bin_num; |
||||
|
||||
/* convert input char to a long */ |
||||
dividend = (long)dividend_char; |
||||
|
||||
/*if a 0 has been obtained, just generate a 8-bit long vector of zeros */ |
||||
if(dividend == 0) |
||||
bin_vector = std::vector<int>(8, 0); |
||||
|
||||
/* else, apply classic decimal to binary conversion */ |
||||
else |
||||
{ |
||||
while ( dividend >= 1 ) |
||||
{ |
||||
bin_num = dividend % 2; |
||||
dividend /= 2; |
||||
bin_vector.push_back(bin_num); |
||||
} |
||||
} |
||||
|
||||
/* ensure that binary vector always has length 8 */ |
||||
if(bin_vector.size()<8){ |
||||
std::vector<int> zeros (8-bin_vector.size(), 0); |
||||
bin_vector.insert(bin_vector.end(), zeros.begin(), zeros.end()); |
||||
} |
||||
|
||||
/* invert numBits bits */ |
||||
for(int index = 0; index<numBits; index++) |
||||
{ |
||||
if(bin_vector[index] == 0) |
||||
bin_vector[index] = 1; |
||||
|
||||
else |
||||
bin_vector[index] = 0; |
||||
} |
||||
|
||||
/* reconvert to decimal */ |
||||
uchar result; |
||||
for(int i = (int)bin_vector.size()-1; i>=0; i--) |
||||
result += bin_vector[i]*pow(2, i); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
int main( int argc, char** argv ) |
||||
{ |
||||
/* get parameters from comand line */ |
||||
CommandLineParser parser( argc, argv, keys ); |
||||
String image_path1 = parser.get<String>( 0 ); |
||||
String image_path2 = parser.get<String>( 1 ); |
||||
|
||||
if(image_path1.empty() || image_path2.empty()) |
||||
{ |
||||
help(); |
||||
return -1; |
||||
} |
||||
|
||||
|
||||
/* load image */ |
||||
cv::Mat imageMat1 = imread(image_path1, 1); |
||||
cv::Mat imageMat2 = imread(image_path2, 1); |
||||
|
||||
if(imageMat1.data == NULL || imageMat2.data == NULL) |
||||
{ |
||||
std::cout << "Error, images could not be loaded. Please, check their paths" |
||||
<< std::endl; |
||||
} |
||||
|
||||
/* create binary masks */ |
||||
cv::Mat mask1 = Mat::ones(imageMat1.size(), CV_8UC1); |
||||
cv::Mat mask2 = Mat::ones(imageMat2.size(), CV_8UC1); |
||||
|
||||
/* create a pointer to a BinaryDescriptor object with default parameters */ |
||||
Ptr<BinaryDescriptor> bd = BinaryDescriptor::createBinaryDescriptor(); |
||||
|
||||
/* compute lines */ |
||||
std::vector<KeyLine> keylines1, keylines2; |
||||
bd->detect(imageMat1, keylines1, mask1); |
||||
bd->detect(imageMat2, keylines2, mask2); |
||||
|
||||
/* compute descriptors */ |
||||
cv::Mat descr1, descr2; |
||||
bd->compute(imageMat1, keylines1, descr1); |
||||
bd->compute(imageMat2, keylines2, descr2); |
||||
|
||||
/* create a BinaryDescriptorMatcher object */ |
||||
Ptr<BinaryDescriptorMatcher> bdm = BinaryDescriptorMatcher::createBinaryDescriptorMatcher(); |
||||
|
||||
/* make a copy of descr2 mat */ |
||||
Mat descr2Copy = descr1.clone(); |
||||
|
||||
/* randomly change some bits in original descriptors */ |
||||
srand (time(NULL)); |
||||
|
||||
for(int j = 0; j<descr1.rows; j++) |
||||
{ |
||||
/* select a random column */ |
||||
int randCol = rand() % 32; |
||||
|
||||
/* get correspondent data */ |
||||
uchar u = descr1.at<uchar>(j, randCol); |
||||
|
||||
/* change bits */ |
||||
for(int k = 1; k<=5; k++) |
||||
{ |
||||
/* copy current row to train matrix */ |
||||
descr2Copy.push_back(descr1.row(j)); |
||||
|
||||
/* invert k bits */ |
||||
uchar uc = invertSingleBits(u, k); |
||||
|
||||
/* update current row in train matrix */ |
||||
descr2Copy.at<uchar>(descr2Copy.rows-1, randCol) = uc; |
||||
} |
||||
} |
||||
|
||||
/* prepare a structure to host matches */ |
||||
std::vector<std::vector<DMatch> > matches; |
||||
|
||||
/* require knn match */ |
||||
bdm->knnMatch(descr1, descr2, matches, 6); |
||||
|
||||
/* visualize matches and Hamming distances */ |
||||
for(size_t v = 0; v<matches.size(); v++) |
||||
{ |
||||
for(size_t m = 0; m<matches[v].size(); m++) |
||||
{ |
||||
DMatch dm = matches[v][m]; |
||||
std::cout << dm.queryIdx << " " << dm.trainIdx << " " |
||||
<< dm.distance << std::endl; |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
|
@ -0,0 +1,111 @@ |
||||
#include <opencv2/line_descriptor.hpp> |
||||
|
||||
#include "opencv2/core/utility.hpp" |
||||
#include "opencv2/core/private.hpp" |
||||
#include <opencv2/imgproc.hpp> |
||||
#include <opencv2/features2d.hpp> |
||||
#include <opencv2/highgui.hpp> |
||||
|
||||
#include <iostream> |
||||
#include <vector> |
||||
|
||||
using namespace cv; |
||||
|
||||
static const std::string images[] = |
||||
{ |
||||
"cameraman.jpg", |
||||
"church.jpg", |
||||
"church2.png", |
||||
"einstein.jpg", |
||||
"stuff.jpg" |
||||
}; |
||||
|
||||
static const char* keys = |
||||
{ |
||||
"{@image_path | | Image path }" |
||||
}; |
||||
|
||||
static void help() |
||||
{ |
||||
std::cout << "\nThis example shows the functionalities of radius matching " << |
||||
"Please, run this sample using a command in the form\n" << |
||||
"./example_line_descriptor_radius_matching <path_to_input_images>/" |
||||
<< std::endl; |
||||
} |
||||
|
||||
int main( int argc, char** argv ) |
||||
{ |
||||
/* get parameters from comand line */ |
||||
CommandLineParser parser( argc, argv, keys ); |
||||
String pathToImages = parser.get<String>( 0 ); |
||||
|
||||
/* create structures for hosting KeyLines and descriptors */ |
||||
int num_elements = sizeof( images ) / sizeof( images[0] ); |
||||
std::vector<Mat> descriptorsMat; |
||||
std::vector<std::vector<KeyLine> > linesMat; |
||||
|
||||
/*create a pointer to a BinaryDescriptor object */ |
||||
Ptr<BinaryDescriptor> bd = BinaryDescriptor::createBinaryDescriptor(); |
||||
|
||||
/* compute lines and descriptors */ |
||||
for(int i = 0; i<num_elements; i++) |
||||
{ |
||||
/* get path to image */ |
||||
std::stringstream image_path; |
||||
image_path << pathToImages << images[i]; |
||||
|
||||
/* load image */ |
||||
Mat loadedImage = imread(image_path.str().c_str(), 1); |
||||
if(loadedImage.data == NULL) |
||||
{ |
||||
std::cout << "Could not load images." << std::endl; |
||||
help(); |
||||
exit(-1); |
||||
} |
||||
|
||||
/* compute lines and descriptors */ |
||||
std::vector<KeyLine> lines; |
||||
Mat computedDescr; |
||||
bd->detect(loadedImage, lines); |
||||
bd->compute(loadedImage, lines, computedDescr); |
||||
|
||||
descriptorsMat.push_back(computedDescr); |
||||
linesMat.push_back(lines); |
||||
|
||||
} |
||||
|
||||
/* compose a queries matrix */ |
||||
Mat queries; |
||||
for(size_t j = 0; j<descriptorsMat.size(); j++) |
||||
{ |
||||
if(descriptorsMat[j].rows >= 5) |
||||
queries.push_back(descriptorsMat[j].rowRange(0, 5)); |
||||
|
||||
else if(descriptorsMat[j].rows >0 && descriptorsMat[j].rows<5) |
||||
queries.push_back(descriptorsMat[j]); |
||||
} |
||||
|
||||
std::cout << "It has been generated a matrix of " << queries.rows |
||||
<< " descriptors" << std::endl; |
||||
|
||||
/* create a BinaryDescriptorMatcher object */ |
||||
Ptr<BinaryDescriptorMatcher> bdm = BinaryDescriptorMatcher::createBinaryDescriptorMatcher(); |
||||
|
||||
/* populate matcher */ |
||||
bdm->add(descriptorsMat); |
||||
|
||||
/* compute matches */ |
||||
std::vector<std::vector<DMatch> > matches; |
||||
bdm->radiusMatch(queries, matches, 30); |
||||
|
||||
/* print matches */ |
||||
for(size_t q = 0; q<matches.size(); q++) |
||||
{ |
||||
for(size_t m = 0; m<matches[q].size(); m++) |
||||
{ |
||||
DMatch dm = matches[q][m]; |
||||
std::cout << "Descriptor: " << q << " Image: " << dm.imgIdx |
||||
<< " Distance: " << dm.distance << std::endl; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,142 @@ |
||||
#include "precomp.hpp" |
||||
|
||||
namespace cv |
||||
{ |
||||
/* draw matches between two images */ |
||||
void drawLineMatches( const Mat& img1, const std::vector<KeyLine>& keylines1, |
||||
const Mat& img2, const std::vector<KeyLine>& keylines2, |
||||
const std::vector<DMatch>& matches1to2, |
||||
Mat& outImg, const Scalar& matchColor, |
||||
const Scalar& singleLineColor, |
||||
const std::vector<char>& matchesMask, int flags ) |
||||
{ |
||||
|
||||
/* initialize output matrix (if necessary) */ |
||||
if(flags == DrawLinesMatchesFlags::DEFAULT) |
||||
{ |
||||
/* check how many rows are necessary for output matrix */ |
||||
int totalRows = img1.rows >= img2.rows?img1.rows:img2.rows; |
||||
|
||||
/* initialize output matrix */ |
||||
outImg = Mat::zeros(totalRows, img1.cols+img2.cols, img1.type()); |
||||
|
||||
} |
||||
|
||||
/* initialize random seed: */ |
||||
srand (time(NULL)); |
||||
|
||||
Scalar singleLineColorRGB; |
||||
if(singleLineColor == Scalar::all(-1)) |
||||
{ |
||||
int R = (rand() % (int)(255 + 1)); |
||||
int G = (rand() % (int)(255 + 1)); |
||||
int B = (rand() % (int)(255 + 1)); |
||||
|
||||
singleLineColorRGB = Scalar(R, G, B); |
||||
} |
||||
|
||||
else |
||||
singleLineColorRGB = singleLineColor; |
||||
|
||||
/* copy input images to output images */ |
||||
Mat roi_left(outImg, Rect(0,0,img1.cols,img1.rows)); |
||||
Mat roi_right(outImg, Rect(img1.cols,0,img2.cols,img2.rows)); |
||||
img1.copyTo(roi_left); |
||||
img2.copyTo(roi_right); |
||||
|
||||
/* get columns offset */ |
||||
int offset = img1.cols; |
||||
|
||||
/* if requested, draw lines from both images */ |
||||
if(flags != DrawLinesMatchesFlags::NOT_DRAW_SINGLE_LINES) |
||||
{ |
||||
for(size_t i = 0; i<keylines1.size(); i++) |
||||
{ |
||||
KeyLine k1 = keylines1[i]; |
||||
line(outImg,Point(k1.startPointX, k1.startPointY), |
||||
Point(k1.endPointX, k1.endPointY), singleLineColorRGB, 2); |
||||
} |
||||
|
||||
for(size_t j = 0; j<keylines2.size(); j++) |
||||
{ |
||||
KeyLine k2 = keylines2[j]; |
||||
line(outImg,Point(k2.startPointX+offset, k2.startPointY), |
||||
Point(k2.endPointX+offset, k2.endPointY), singleLineColorRGB, 2); |
||||
} |
||||
} |
||||
|
||||
/* draw matches */ |
||||
for(size_t counter = 0; counter<matches1to2.size(); counter++) |
||||
{ |
||||
if(matchesMask[counter] != 0) |
||||
{ |
||||
DMatch dm = matches1to2[counter]; |
||||
KeyLine left = keylines1[dm.queryIdx]; |
||||
KeyLine right = keylines2[dm.trainIdx]; |
||||
|
||||
Scalar matchColorRGB; |
||||
if(matchColor == Scalar::all(-1)) |
||||
{ |
||||
int R = (rand() % (int)(255 + 1)); |
||||
int G = (rand() % (int)(255 + 1)); |
||||
int B = (rand() % (int)(255 + 1)); |
||||
|
||||
matchColorRGB = Scalar(R, G, B); |
||||
|
||||
if(singleLineColor == Scalar::all(-1)) |
||||
singleLineColorRGB = matchColorRGB; |
||||
} |
||||
|
||||
else |
||||
matchColorRGB = matchColor; |
||||
|
||||
/* draw lines if necessary */ |
||||
line(outImg, Point(left.startPointX, left.startPointY), |
||||
Point(left.endPointX, left.endPointY), singleLineColorRGB, 2); |
||||
|
||||
line(outImg, Point(right.startPointX+offset, right.startPointY), |
||||
Point(right.endPointX+offset, right.endPointY), singleLineColorRGB, 2); |
||||
|
||||
/* link correspondent lines */ |
||||
line(outImg, Point(left.startPointX, left.startPointY), |
||||
Point(right.startPointX+offset, right.startPointY), matchColorRGB, 1); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/* draw extracted lines on original image */ |
||||
void drawKeylines( const Mat& image, |
||||
const std::vector<KeyLine>& keylines, |
||||
Mat& outImage, |
||||
const Scalar& color, |
||||
int flags ) |
||||
{ |
||||
if(flags == DrawLinesMatchesFlags::DEFAULT) |
||||
outImage = image.clone(); |
||||
|
||||
for(size_t i = 0; i<keylines.size(); i++) |
||||
{ |
||||
/* decide lines' color */ |
||||
Scalar lineColor; |
||||
if(color != Scalar::all(-1)) |
||||
{ |
||||
int R = (rand() % (int)(255 + 1)); |
||||
int G = (rand() % (int)(255 + 1)); |
||||
int B = (rand() % (int)(255 + 1)); |
||||
|
||||
lineColor = Scalar(R, G, B); |
||||
} |
||||
|
||||
else |
||||
lineColor = color; |
||||
|
||||
/* get line */ |
||||
KeyLine k = keylines[i]; |
||||
|
||||
/* draw line */ |
||||
line(outImage, Point(k.startPointX, k.startPointY), |
||||
Point(k.endPointX, k.endPointY), lineColor, 1); |
||||
} |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue