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.
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.
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')
for people who uses os.listdir()
function
this is my error
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
you should write code like that
for folder in classes:
for img in os.listdir(os.path.join('data', folder))[:-1]:
in the end it work
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.
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.
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')
for people who uses os.listdir()
function
this is my error
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
you should write code like that
for folder in classes:
for img in os.listdir(os.path.join('data', folder))[:-1]:
in the end it work