I have an opencv application in which I need to store a 2d point's coordinates, and the feature descriptor for that point.
For example, after i run the following code:
std::vector<KeyPoint> keypoints_1;
Mat descriptors_1;
Ptr<FeatureDetector> detector = ORB::create();
Ptr<DescriptorExtractor> descriptor = ORB::create();
detector->detect ( img_1,keypoints_1 );
descriptor->compute ( img_1, keypoints_1, descriptors_1 );
I get descriptors_1, which is every descriptor for every Keypoint'
How can I get the descriptor that corresponds with, for example, keypoints_1[12], and store it as a Mat?
Neither descriptors_1.rows, nor descriptors_1.cols has the same size as the number of keypoints.
descriptor->compute may remove key points from the array - if it can't compute the descriptor for a given key point. After calling compute the two matrices should have the same number of rows.
Related
I want to make an calcOpticalFlowPyrLK from feature points get from image, when I use goodFeaturesToTrack, everything is OK as following:
goodFeaturesToTrack(blackOutImagePrev, prevCorners, 200, 0.04, 30);
calcOpticalFlowPyrLK(blackOutImagePrev, blackOutImageNext, prevCorners, nextCorners, status, err);
Due to the processing speed issue, I want to change the function that I get feature points to surf or fast method. For the surf, the function is:
final KeyPointVector kp = new KeyPointVector();
final SURF surf = SURF.create(2500, 4, 2, true, false);
surf.detect(image, kp);
Since the surf get feature points are stored in KeyPointVector, but the type of prevCorners is Mat. How could I transfer it to Mat so I can call the calcOpticalFlowPyrLK? Or there is any workaround?
Looks like a KeyPointVector is just a vector of KeyPoints. The KeyPoints type has the pt() method which will return a Point2f which you can construct a Mat with. So create the new Mat, and loop through the keypoints vector, get the points with pt() and insert.
I saved ORB and SIFT descriptors in xml.
I tried use Mat descriptors = imread("descriptor.xml")
but it didn't work.
it's blank.
Let say that you have stored the SIFT descriptor in descriptor.xml. Use the following code to assign the saved descriptor back to a Mat variable.
Mat sift_descriptor;
FileStorage fs("descriptor.xml", FileStorage::READ);
fs["descriptor"] >> sift_descriptor;
fs.release();
You have to save and load Mats that are not images with cv::FileStorage.
Is there any way in which we can limit the number of keypoints to the 100 in OPENCV SURF?
Will the keypoints obtained be ordered according to their strength?
How to obtain the strength of the descriptor?
I am working on OPENCV in a LINUX system with a cpp program.
regards,
shiksha
My code is:
int main( int argc, char** argv )
{
Mat img_1 = imread( argv[1], CV_LOAD_IMAGE_GRAYSCALE );
Mat img_2 = imread( argv[2], CV_LOAD_IMAGE_GRAYSCALE );
//-- Step 1: Detect the keypoints using SURF Detector
int minHessian = 500;
SurfFeatureDetector detector( minHessian,1,2,false,true );
std::vector<KeyPoint> keypoints_1p;
std::vector<KeyPoint> keypoints_2p;
detector.detect( img_1, keypoints_1p );
detector.detect( img_2, keypoints_2p);
// computing descriptors
SurfDescriptorExtractor extractor(minHessian,1,1,1,0);
Mat descriptors1, descriptors2;
extractor.compute(img_1, keypoints_1p, descriptors1);
extractor.compute(img_2, keypoints_2p, descriptors2);
You can get at most 100. I could imagine images (say for example a constant image) that have no SIFT descriptor. There are many ways to limit the keypoints to 100. There are easy solutions and hard solutions to your problem. You can get at most 100, by randomly selecting 100 keypoints from as many keypoints you get.
There is no such thing as the strength of the keypoint. You're going to have to define your own concept of strength.
There are a wide variety of parameter in the original Lowe paper that filter the keypoints (one of them is that they don't match an image edge, section 4.1 of Lowe's paper). There are 2 or 3 other parameters. You would need to adjust the parameters systematically in such a way that you only get 100. If you get less than 100 you filter less, and if you get more than 100 you filter more.
see the question here. And see my answer there how to limit the number of keypoints.
I am trying to extract different point descriptors (SIFT, SURF, ORB, BRIEF,...) to build Bag of Visual words. The problem seems to be that I am using very small images : 12x60px.
Using a dense extractor I am able to get some keypoints, but then when extracting the descriptor no data is extracted.
Here is the code :
vector<KeyPoint> points;
Mat descriptor; // descriptor of the current image
Ptr<DescriptorExtractor> extractor = DescriptorExtractor::create("BRIEF");
Ptr<FeatureDetector> detector(new DenseFeatureDetector(1.f,1,0.1f,6,0,true,false));
image = imread(filename, 0);
roi = Mat(image,Rect(0,0,12,60));
detector->detect(roi,points);
extractor->compute(roi,points,descriptor);
cout << descriptor << endl;
The result is [] (with BRIEF and ORB) and SegFault (with SURF and SIFT).
Does anyone have a clue on how to densely extract point descriptors from small images on OpenCV ?
Thanks for your help.
Indeed, I finally managed to work my way to a solution. Thanks for the help.
I am now using an Orb detector with initalised parameters instead of a random one, e.g:
Ptr<DescriptorExtractor> extractor(new ORB(500, 1.2f, 8, orbSize, 0, 2, ORB::HARRIS_SCORE, orbSize));
I had to explore the documentation of OpenCV thoroughly before finding the answer to my problem : Orb documentation.
Also if people are using the dense point extractor they should be aware that after the descriptor computing process they may have less keypoints than produced by the keypoint extractor. The descriptor computing removes any keypoints for which it cannot get the data.
BRIEF and ORB use a 32x32 patch to get the descriptor. Since it doesn't fit your image, they remove those keypoints (to avoid returning keypoints without descriptor).
In the case of SURF and SIFT, they can use smaller patches, but it depends on the scale provided by the keypoint. In this case, I guess they have to use a bigger patch and the same as before happens. I don't know why you get a segfault, though; maybe the SIFT/SURF descriptor extractors don't check that keypoints are inside the image boundaries, as BRIEF/ORB ones do.
I have an image and i want to locate key points by using SIFT detector and group them, then i want to generate local features for each key point by using SIFT, would you please help me how I can do it ? Please give me any suggestions
I really appreciate your help
I'm not sure that I understand what you mean, but if you extract SIFT features from an image, you automatically get the feature descriptor which is used to compare features to each other. Of course you also get the feature location, size, direction and hessian value with it.
While you can group those features by there position in the image, but there is currently no way that I'm aware of to compare those groups, since they may be locally related, but can have wildly different feature descriptors.
Also I would suggest SURF. It is faster and not patent encumbered.
Have a look at the examples from OpenCV if you want specific instructions on how to retrieve and compare descriptors.
If you are using opencv here are the commands to do it, else if you are using the matlab see the link MATCHING_using surf
USING OPENCV::
// you can change the parameters for your requirement
double hessianThreshold=200;
int octaves=3;
int octaveLayers=4;
bool upright=false;
vector<KeyPoint>keypoints;
//The detector detects the keypoints in an image here image is RGBIMAGE of Mat type
SurfFeatureDetector detector( hessianThreshold, octaves, octaveLayers, upright );
detector.detect(RGB_IMAGE, keypoints);
//The extractor computesthe local features around the keypoints
SurfDescriptorExtractor extractor;
Mat descriptors;
extractor.compute( last_ref, keypoints, descriptors);
// all the key points local features are stored in rows one after another in descriptors matrix...
Hope it is useful:)