setting up Sift parameters, opencv - opencv

I 'm implementing sift using opencv 2.3.
Sift implementation with OpenCV 2.2
#include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <vector>
using namespace std;
using namespace cv;
int main(int argc, char *argv[])
{
Mat image = imread("TestImage.jpg");
// Create smart pointer for SIFT feature detector.
Ptr<FeatureDetector> featureDetector = FeatureDetector::create("SIFT");
vector<KeyPoint> keypoints;
// Detect the keypoints
featureDetector->detect(image, keypoints); // NOTE: featureDetector is a pointer hence the '->'.
//Similarly, we create a smart pointer to the SIFT extractor.
Ptr<DescriptorExtractor> featureExtractor = DescriptorExtractor::create("SIFT");
// Compute the 128 dimension SIFT descriptor at each keypoint.
// Each row in "descriptors" correspond to the SIFT descriptor for each keypoint
Mat descriptors;
featureExtractor->compute(image, keypoints, descriptors);
// If you would like to draw the detected keypoint just to check
Mat outputImage;
Scalar keypointColor = Scalar(255, 0, 0); // Blue keypoints.
drawKeypoints(image, keypoints, outputImage, keypointColor, DrawMatchesFlags::DEFAULT);
namedWindow("Output");
imshow("Output", outputImage);
char c = ' ';
while ((c = waitKey(0)) != 'q'); // Keep window there until user presses 'q' to quit.
return 0;
}
How can I change default CommonParams, DetectorParams, DescriptorParams parametrs.

The answer is at OpenCV change keypoint or descriptor parameters after creation. Relevant snippet:
featureDetector->set("someParam", someValue);

Related

OpenCV and DAISY descriptors

I am trying to do feature matching between 2 perspectives of the same image using DAISY and the FlannBasedMatcher.
I don't think there is even a single match that is correct.
Note: I also get different results each time I run the program but I think this is expected behaviour as explained here: FlannBasedMatcher returning different results
So what am I doing wrong? Why are these matches so bad?
Input Images
Wrong & non-deterministic results
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <iostream>
#include <vector>
#include <stdio.h>
using namespace cv;
using std::vector;
const float nn_match_ratio = 0.7f; // Nearest neighbor matching ratio
const float keypoint_diameter = 15.0f;
int main(int argc, char ** argv){
// Load images
Mat img1 = imread(argv[1]);
Mat img2 = imread(argv[2]);
vector<KeyPoint> keypoints1, keypoints2;
// Add every pixel to the list of keypoints for each image
for (float xx = keypoint_diameter; xx < img1.size().width - keypoint_diameter; xx++) {
for (float yy = keypoint_diameter; yy < img1.size().height - keypoint_diameter; yy++) {
keypoints1.push_back(KeyPoint(xx, yy, keypoint_diameter));
keypoints2.push_back(KeyPoint(xx, yy, keypoint_diameter));
}
}
Mat desc1, desc2;
Ptr<cv::xfeatures2d::DAISY> descriptor_extractor = cv::xfeatures2d::DAISY::create();
// Compute DAISY descriptors for both images
descriptor_extractor->compute(img1, keypoints1, desc1);
descriptor_extractor->compute(img2, keypoints2, desc2);
vector <vector<DMatch>> matches;
// For each descriptor in image1, find 2 closest matched in image2 (note: couldn't get BF matcher to work here at all)
FlannBasedMatcher flannmatcher;
flannmatcher.add(desc1);
flannmatcher.train();
flannmatcher.knnMatch(desc2, matches, 2);
// ignore matches with high ambiguity -- i.e. second closest match not much worse than first
// push all remaining matches back into DMatch Vector "good_matches" so we can draw them using DrawMatches
int num_good = 0;
vector<KeyPoint> matched1, matched2;
vector<DMatch> good_matches;
for (int i = 0; i < matches.size(); i++) {
DMatch first = matches[i][0];
DMatch second = matches[i][1];
if (first.distance < nn_match_ratio * second.distance) {
matched1.push_back(keypoints1[first.queryIdx]);
matched2.push_back(keypoints2[first.trainIdx]);
good_matches.push_back(DMatch(num_good, num_good, 0));
num_good++;
}
}
Mat res;
drawMatches(img1, matched1, img2, matched2, good_matches, res);
imwrite("_res.png", res);
return 0;
}
Sorry. I found my bug. I have the Indexes reversed in the lines that read:
matched1.push_back(keypoints1[first.queryIdx]);
matched2.push_back(keypoints2[first.trainIdx]);
how can i get the coordinates of the matches find in the two images,that is the coordinates of the matches in the first image and the coordinates of the matches in the second?

split a BGR matrix without use split() function

I am programming with Visual Studio 2012 and the Opencv library, in the 2.4.6 version.
Someone can help me about splitting a BGR image into three images, one for every channel?
I know that there is the split function in OpenCV, but it causes me an unhandled exception, probably because I have a 64 bit processor with the 32 bit library, or probably it's the version of the library, so I want to know how to iterate on the pixel values of a BGR matrix without use split().
Thanks in advance.
If you don't want to use split() then you can read each r,g,b pixel value from your source image and write to destination image and which should be single channel.
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main( int argc, const char** argv ){
Mat src = imread("ball.jpg", 1);
Mat r(src.rows,src.cols,CV_8UC1);
Mat g(src.rows,src.cols,CV_8UC1);
Mat b(src.rows,src.cols,CV_8UC1);
for(int i=0;i<src.rows;i++){
for(int j=0;j<src.cols;j++){
Vec3b pixel = src.at<Vec3b>(i, j);
b.at<uchar>(i,j) = pixel[0];
g.at<uchar>(i,j) = pixel[1];
r.at<uchar>(i,j) = pixel[2];
}
}
imshow("src", src);
imshow("r", r);
imshow("g", g);
imshow("b", b);
waitKey(0);
}

OpenCV: How to use cvSobel?

I'm trying to find the gradient direction from the edges using OpenCv 2.4.5, but I'm having problem with cvSobel() and below is the error message and my code. I read somewhere that it might be due to the conversion between floating point(??) but I have no idea on how to fix it. Any Help??
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2\opencv.hpp>
#include <opencv2\calib3d\calib3d.hpp>
#include <iostream>
#include <stdlib.h>
#include "stdio.h"
using namespace cv;
using namespace std;
int main()
{
Mat im = imread("test1.jpg");
if (im.empty()) {
cout << "Cannot load image!" << endl;
}
Mat *dx, *dy;
dx = new Mat( Mat::zeros(im.rows, im.cols, 1));
dy = new Mat( Mat::zeros(im.rows, im.cols, 1));
imshow("Image", im);
// Convert Image to gray scale
Mat im_gray;
cvtColor(im, im_gray, CV_RGB2GRAY);
imshow("Gray", im_gray);
//trying to find the direction, but gives errors here
cvSobel(&im_gray, dx, 1,0,3);
waitKey(0);
return 0;
}
You are mixing the C++ and C api. cv::Mat is from the C++ api and CvArr* is from the C api.
here you are using The C api cvSobel on C++ classes.
//trying to find the direction, but gives errors here
cvSobel(&im_gray, dx, 1,0,3);
What happens if you do
cv::Sobel( im_gray, dx, im_gray.depth(), 1, 0, 3);
EDIT
and declare
Mat dx;
Mat dy;
I think this might solve your problem, I'm actually quite surprised your code compiles.

cvSobel problems - opencv

i've got the code below:
// Image Processing.cpp : Defines the entry point for the console application.
//
//Save an available image.
#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"
/*
The purpose of this program is to show an example of THRESHOLDING.
*/
int _tmain(int argc, _TCHAR* argv[])
{
IplImage* src = cvLoadImage("D:\\document\\Study\\university of technology\\semester_8\\Computer Vision\\Pics for test\\black-white 4.jpg");
IplImage* dst = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,3);
IplImage* temp1 = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* temp2 = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
cvCvtColor(src,temp1,CV_RGB2GRAY);
cvSobel(temp1,temp2,0,1,3);
cvMerge(temp2,temp2,temp2,NULL,dst);
cvNamedWindow("src",1);
cvNamedWindow("dst",1);
cvShowImage("src",src);
cvShowImage("dst",temp2);
cvWaitKey(0);
cvReleaseImage(&src);
//cvReleaseImage(&dst);
cvDestroyAllWindows();
return 0;
}
when i run it, there's an warning as the picture below:
but if i still click on "countinue" button, the result is displayed!
hope someone can give me an explaination !
The result is correct. The description of the program is not. Your xorder=0 and yorder=1 which means that you are detecting the first derivative in the y-direction. The white pixels in the image correspond to boundaries that can be detected by a vertical derivative, namely as close to horizontal boundaries as possible. This is why the vertical lines are barely ever detected.
CvSobel by itself has NOTHING to do with thresholding. CvSobel is a function used for finding boundaries and contours. Thresholding is most commonly an operation that creates a black-and-white image from a greyscale image. It is also called image binarization.
If you want to threshold an image, start with cvThreshold and cvAdaptiveThreshold.
i've fixed it, here is my code:
// Image Processing.cpp : Defines the entry point for the console application.
//
//Save an available image.
#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"
/*
The purpose of this program is to show an example of Sobel method.
*/
int _tmain(int argc, _TCHAR* argv[])
{
IplImage* src = cvLoadImage("D:\\document\\Study\\university of technology\\semester_8\\Computer Vision\\Pics for test\\black-white 4.jpg");
IplImage* dst = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* dst_x = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* dst_y = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* temp1 = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* temp2 = cvCreateImage(cvGetSize(src),IPL_DEPTH_16S,1);
cvCvtColor(src,temp1,CV_RGB2GRAY);
cvSobel(temp1,temp2,0,1,3);
cvConvertScale(temp2,dst_y,1.0,0);
cvSobel(temp1,temp2,1,0,3);
cvConvertScale(temp2,dst_x,1.0,0);
//k nen dao ham cung luc theo x va y ma nen dao ham rieng roi dung ham cvAdd.
//cvSobel(temp1,temp2,1,1,3);
//cvConvertScale(temp2,dst,1.0,0);
cvAdd(dst_x,dst_y,dst,NULL);
cvNamedWindow("src",1);
cvNamedWindow("dst",1);
cvNamedWindow("dst_x",1);
cvNamedWindow("dst_y",1);
cvShowImage("src",src);
cvShowImage("dst",dst);
cvShowImage("dst_x",dst_x);
cvShowImage("dst_y",dst_y);
cvWaitKey(0);
cvReleaseImage(&src);
cvReleaseImage(&dst);
cvReleaseImage(&temp1);
cvReleaseImage(&temp2);
cvDestroyAllWindows();
return 0;
}

Error in implementing realtime camera based GPU_SURF in opencv

As the CPU based SURF in opencv was very slow for realtime application, we decided to use GPU_SURF, after setting up the opencv_gpu we made the following code:
#include <iostream>
#include <iomanip>
#include <windows.h>
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/gpu/gpu.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/core/types_c.h"
using namespace std;
using namespace cv;
using namespace cv::gpu;
void help()
{
cout << "\nThis program demonstrates using SURF_GPU features detector, descriptor extractor and BruteForceMatcher_GPU" << endl;
cout << "\nUsage:\n\tmatcher_simple_gpu <image1> <image2>" << endl;
}
int main(int argc, char* argv[])
{
GpuMat img1(imread("C:\\OpenCV2.3\\opencv2.3\\bin\\Debug\\tsucuba_left.png", CV_LOAD_IMAGE_GRAYSCALE));
SURF_GPU surf;
// detecting keypoints & computing descriptors
GpuMat keypoints1GPU, keypoints2GPU;
GpuMat descriptors1GPU, descriptors2GPU;
surf(img1, GpuMat(), keypoints1GPU, descriptors1GPU);
cout << "FOUND " << keypoints1GPU.cols << " keypoints on first image" << endl;
//cout << "FOUND " << keypoints2GPU.cols << " keypoints on second image" << endl;
CvCapture* capture = cvCreateCameraCapture(0);
int frame_width = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
int frame_height = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
cout<<"frames done\n";
cv::gpu::GpuMat frame_gpu = cv::gpu::GpuMat(frame_width, frame_height, CV_8UC3);
cv::gpu::GpuMat frame_gpu_cvt = cv::gpu::GpuMat(frame_width, frame_height, CV_8UC1);
cout<<"gpu frmes loaded\n";
//Sleep(200);
while(cvGrabFrame(capture))
{
IplImage* frame;
frame =cvQueryFrame(capture);
CvMat* image=0;
image = cvCreateMat(frame->height, frame->width, CV_8UC1);
frame_gpu.upload(image);
cout<<"frame uploaded\n";
cvtColor(frame_gpu,frame_gpu_cvt,CV_RGB2GRAY);
cout<<"color done\n";
surf(frame_gpu_cvt, GpuMat(), keypoints2GPU, descriptors2GPU);
// matching descriptors
BruteForceMatcher_GPU< L2<float> > matcher;
GpuMat trainIdx, distance;
matcher.matchSingle(descriptors1GPU, descriptors2GPU, trainIdx, distance);
// downloading results
vector<KeyPoint> keypoints1, keypoints2;
vector<float> descriptors1, descriptors2;
vector<DMatch> matches;
surf.downloadKeypoints(keypoints1GPU, keypoints1);
surf.downloadKeypoints(keypoints2GPU, keypoints2);
surf.downloadDescriptors(descriptors1GPU, descriptors1);
surf.downloadDescriptors(descriptors2GPU, descriptors2);
BruteForceMatcher_GPU< L2<float> >::matchDownload(trainIdx, distance, matches);
// drawing the results
Mat img_matches;
drawMatches(img1, keypoints1, frame_gpu, keypoints2, matches, img_matches);
namedWindow("matches", 0);
imshow("matches", img_matches);
//waitKey(0);
}
return 0;
}
The error that comes on executing it is:
OpenCV Error: Assertion failed (scn == 3 || scn == 4) in unknown function, file
..\..\..\opencv_2.3\opencv\modules\gpu\src\color.cpp, line 186
It is due to the line:
cvtColor(frame_gpu,frame_gpu_cvt,CV_RGB2GRAY);
There maybe other errors, can someone please help us out on this one.
scn is the number of channels in the first argument to cvtColor. Converting from RGB to GRAY requires that the first argument has three or four channels. The line frame_gpu.upload(image); is converting frame_gpu to one channel since image has one channel. It looks like you can skip the call to cvtColor and just call SURF directly on frame_gpu.

Resources