3
votes

I'm trying to classify some images using SIFT for detect and compute keypoints and descriptors, and then use KNN for classify them:

This is my little code:

import os
import cv2

## Prepare images files
rootpath = '/Some/Directory'
files = []
for filedir, dirs, filess in os.walk(rootpath):
    for filename in filess:
        pathfile = os.path.join(filedir, filename)
        files.append(pathfile) 

## Detect keypoints and compute descriptors for train images
kp_train = []
dsc_train = []
for file in files:
    ima = cv2.imread(file)
    gray=cv2.cvtColor(ima,cv2.COLOR_BGR2GRAY)
    kpts, des = sift.detectAndCompute(gray, None) 
    kp_train.append(kpts)
    dsc_train.append(des)

## Train knn
dsc_train = np.array(dsc_train)
responses = np.arange(len(kp_train),dtype = np.float32)
knn = cv2.ml.KNearest_create()
knn.train(dsc_train, cv2.ml.ROW_SAMPLE, responses)

But I'm a little stuck with the next error

>>> knn.train(dsc_train,cv2.ml.ROW_SAMPLE,responses)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: dsc_train data type = 17 is not supported

files is a list with 10 images, so the loop detects and computes keypoints and descriptor for each image. I give you some images.Thanks

enter image description here

enter image description here

enter image description here

1
Can you include a reduced set of sample date to demonstrate, maby three images? - tfv
You may get quicker response if code is complete (including import statements, filenames etc) and data available so that we can reproduce it. - tfv
@tfv I edited the post. Check it. Thanks for the advices - Jose
Ooookaaay, my first idea would be to use features (e.g. textural features) instead of keypoints for such atype of images, but I'll try to have a look. - tfv
What version of cv2 are you using? - tfv

1 Answers

0
votes

In any case, my feeling is that you are missing a lines

import numpy as np

and

sift = cv2.SIFT()

somewhere in your code.

For me, the code which actually reproduces your problem (including some changes due to my version CV 2.4.12) is attached below.

However, I fear that the approach you have chosen is not appropriate for K-nearest neighbour (KNN) at all. KNN measures the distance between feature vectors belonging to different samples. However, for all feature vectors, each component of the vector needs to have the same meaning (e.g. one feature being the average brightness value of an image). So that feature always needs to show up at the same position of your vecort.

In SUFT, you are creating coordinates of key points of different images. Most importantly, the length of the features vectors will be different for each image, so you cannot apply kNN. Obviously those coordinates do not make sense as part of a feature vector used to compare between different images.

import os
import cv2 #Using CV 2.4.12
import numpy as np

## Prepare images files
rootpath = 'images/'
files = []
for filedir, dirs, filess in os.walk(rootpath):
    for filename in filess:
        pathfile = os.path.join(filedir, filename)
        files.append(pathfile) 

print files

## Detect keypoints and compute descriptors for train images
kp_train = []
dsc_train = []
sift = cv2.SIFT()
for file in files:
    ima = cv2.imread(file)
    print file
    gray=cv2.cvtColor(ima,cv2.COLOR_BGR2GRAY)
    kpts, des = sift.detectAndCompute(gray, None) #sift = cv2.xfeatures2d.SIFT_create()
    kp_train.append(kpts)
    dsc_train.append(des)

## Train knn
dsc_train = np.array(dsc_train)
responses = np.arange(len(kp_train),dtype = np.float32)
knn = cv2.KNearest()

#Next line does not work:
knn.train(dsc_train, responses)