FLANN Index in Python - Training Fails with Segfault
Dear Internet,
I'm trying to add a number of images to a FLANN index (thousands in reality, once I have this working) and then find the closest match in the index to a query image. But it segfaults. :(
Bare essentials code:
import numpy as np
import cv2
import sys
FLANN_INDEX_LSH = 6
img1 = cv2.imread(sys.argv[1],0)
brisk = cv2.BRISK()
kp1, des1 = brisk.detectAndCompute(img1,None)
index_params= dict(algorithm = FLANN_INDEX_LSH,
table_number = 6, # 12
key_size = 12, # 20
multi_probe_level = 1) #2
search_params = dict(checks=50) # or pass empty dictionary
flann = cv2.FlannBasedMatcher(index_params,search_params)
for filename in sys.argv[2:]:
img2 = cv2.imread(filename, 0)
print "Detecting and computing {0}".format(filename)
kp2, des2 = brisk.detectAndCompute(img2,None)
print "Adding..."
flann.add(des2)
print len(flann.getTrainDescriptors()) #verify that it actually took the descriptors in
print "Training..."
flann.train()
print "Matching..."
matches = flann.knnMatch(des1,k=2)
(I've tried this both with 2.4.9 and a pull of 3.0 alpha as from the day I'm posting this, both had same result.)
Problem: Here's the output where it fails:
Training...
Segmentation fault (core dumped)
So it dies at training, or at match() if I skip training.
What has me stuck:
I can't find this functionality in the docs as regards Python. Am I in the wrong places?
http://docs.opencv.org/trunk/modules/flann/doc/flann_fast_approximate_nearest_neighbor_search.html
http://docs.opencv.org/trunk/modules/features2d/doc/common_interfaces_of_descriptor_matchers.htmlFor lack of docs, I'm trying to emulate in Python what I see in matching_to_many_images.cpp from the samples since that's the closest thing to what I'm trying to do. I think. So that's where I'm getting what I have so far.
Now what? Kind of lost. Sorry if this is actually clearly documented and I just couldn't find it.
Thanks!
It could be a problem with LSH. Try with KDTREE algo param in your FLANN params, and you'll go farther. Also, you should see this: http://stackoverflow.com/a/13654489
EDIT: I think it's a bug in opencv. Training a flann based matcher results in segmentation fault (some pointer trying to access a memory location something that doesn't exist, probably). Try with simply matching two images one on one, and it works.
So, I guess the fault is somewhere in OpenCV. I used the features2d interfaces for creating detectors and descriptors extractors.
Also, I think you should try out BRISK from here, see if that works, with your 3.0 build: https://github.com/Itseez/opencv/blob/master/samples/python2/find_obj.py
To answer your questions:
Matching one to one worked just fine. In fact, I tested that with find_obj.py!
But then I came upon something else. http://stackoverflow.com/questions/25781782/making-flann-matcher-editable-and-savable-to-disk ...which passed descriptors inside a list to add().
So I made a switch that no longer causes the segfault:
This:<br>
flann.add([des2])
<br> instead of: <Br>flann.add(des2)
<br>It seems it needed a list of ndarrays, rather than an ndarray. Of course. The perils of using undocumented things, I guess.
@Christopher, Ah shit yes!! I guess I missed that too. I have working code for my app and I just couldn't see what I was missing. Indeed, the descriptors need to be passed as list