Why doesn't SIFT work for 8 bit images (JPEG) in OpenCV with Python?

Question:

I used SIFT for all my other 24 bit JPEG images without any problems, however, the 8-bit one always give me the following error.

image is empty or has incorrect depth (!=CV_8U) in function cv::SIFT::operator ()

Does anyone know how to deal with it?

Here is my code:

import cv2 
import numpy as np 
import os 
import glob
import scipy.cluster
os.chdir('mydirectory')
images = []

for infile in glob.glob('./*.jpg'):
  pic = cv2.imread(infile,0)
  images.append(pic)

my_set = images
descriptors = np.array([])
feaL=np.array([])

for pic in my_set:
  kp, des = cv2.SIFT().detectAndCompute(pic, None)
  feaL=np.append(feaL,des.shape[0])
  descriptors = np.append(descriptors, des)

Then the error “image is empty or has incorrect depth (!=CV_8U) in function cv::SIFT::operator ()” pops up.

Asked By: Joseph Yu

||

Answers:

EDIT: After typing this I just saw the grayscale flag on imread. Try printing the images as they are read in, it sounds like imread may be silently failing and leaving you with empty Mats.

cv2.SIFT.detectAndCompute never takes anything other than 8-bit grayscale, so I’m not sure that you actually did use SIFT on a 24-bit image without problems.

cv2.SIFT.detectAndCompute

Python: cv2.SIFT.detectAndCompute(image, mask[, descriptors[, useProvidedKeypoints]]) → keypoints, descriptors

So to change to 8 bit grayscale immediately prior to detection and extraction:

for pic in my_set:
    pic = cv2.cvtColor(pic, cv2.COLOR_BGR2GRAY)
    kp, des = cv2.SIFT().detectAndCompute(pic, None)

Of course that is a dumb place to put it, but it’s up to you to figure out if you need to keep the BGR originals or not, etc.

I answered a different user that encountered the same error while using cv2.SIFT().detectAndCompute() in-depth in this stackoverflow post.

The sift functions (at least specifically .detectAndCompute() )
ONLY accepts images with 8 bit integer values.

Before using sift on an image, convert it into 8bit using something like
image8bit = cv2.normalize(image, None, 0, 255, cv2.NORM_MINMAX).astype('uint8')

Answered By: Alexander Mays

for people who uses os.listdir() function
this is my error
enter image description here

when you use

for folder in classes:
    for img in os.listdir(os.path.join('data', folder)):

every folder has file named Thumbs.db to avoid it or to run your code
enter image description here

you should write code like that

for folder in classes:
    for img in os.listdir(os.path.join('data', folder))[:-1]: 

enter image description here

in the end it work

enter image description here

Answered By: Nour Alden
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.