error: (-5) image is empty or has incorrect depth (!=CV_8U) in function cv::SIFT::operator ()
Asked Answered
C

2

6

I am trying to run basic script found on a tutorial for object detection. I have tried everything I could find on web but failed to solve it. Already tried different suggested methods to convert image to CV_U8. Also used 8 bit images as input, still without progress. Here is the code:

import cv2
import numpy as np
MIN_MATCH_COUNT=30

detector=cv2.SIFT()

FLANN_INDEX_KDITREE=0
flannParam=dict(algorithm=FLANN_INDEX_KDITREE,tree=5)
flann=cv2.FlannBasedMatcher(flannParam,{})

trainImg=cv2.imread("TrainingData/TrainImg.jpeg",0)
trainKP,trainDesc=detector.detectAndCompute(trainImg,None)

cam=cv2.VideoCapture(0)
while True:
    ret, QueryImgBGR=cam.read()
    QueryImg=cv2.cvtColor(QueryImgBGR,cv2.COLOR_BGR2GRAY)
    queryKP,queryDesc=detector.detectAndCompute(QueryImg,None)
    matches=flann.knnMatch(queryDesc,trainDesc,k=2)

    goodMatch=[]
    for m,n in matches:
        if(m.distance<0.75*n.distance):
            goodMatch.append(m)
    if(len(goodMatch)>MIN_MATCH_COUNT):
        tp=[]
        qp=[]
        for m in goodMatch:
            tp.append(trainKP[m.trainIdx].pt)
            qp.append(queryKP[m.queryIdx].pt)
        tp,qp=np.float32((tp,qp))
        H,status=cv2.findHomography(tp,qp,cv2.RANSAC,3.0)
        h,w=trainImg.shape
        trainBorder=np.float32([[[0,0],[0,h-1],[w-1,h-1],[w-1,0]]])
        queryBorder=cv2.perspectiveTransform(trainBorder,H)
        cv2.polylines(QueryImgBGR,[np.int32(queryBorder)],True,(0,255,0),5)
    else:
        print "Not Enough match found- %d/%d"%(len(goodMatch),MIN_MATCH_COUNT)
    cv2.imshow('result',QueryImgBGR)
    if cv2.waitKey(10)==ord('q'):
        break
cam.release()
cv2.destroyAllWindows()

Here is the error:

enter image description here

I am currently using conda environment with opencv2.4.11.

Clipclop answered 11/5, 2018 at 18:36 Comment(3)
Please don't paste images of consoles - paste the text insteadCoquito
Check whether 'QueryImageBGR' is empty or not before proceeding..Meanly
Thank you for your response. Image files were assigned wrong extensions, which were being translated in unexpected dimension. Further I think I hastily made some mistake in path to images when I tried different alternatives. It work perfectly after redefining full path and reassigning extention.Clipclop
R
11

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')

DETAILS
The source code of void SIFT_Impl::detectAndCompute(InputArray _image, ... ) contains exception checks that verifies the data is 8bit int.

if( image.empty() || image.depth() != CV_8U )
    CV_Error( Error::StsBadArg, "image is empty or has incorrect depth (!=CV_8U)" );

if( !mask.empty() && mask.type() != CV_8UC1 )
    CV_Error( Error::StsBadArg, "mask has incorrect type (!=CV_8UC1)" );

The second check only applies to the optional "InputArray _mask" arguement, and this mask can only be CV_8UC1 which means it must be CV_8U depth and only 1 channel (so much be greyscale).

On the opencv page defining basic structure , the depth level CV_8U is defined as

CV_8U - 8-bit unsigned integers ( 0..255 )

This means the input image must be defined by 8-bit integers with values 0-255.

The sift function only works in greyscale, so the input should be 1 channel as well. If the input has 3 or 4 channels instead of 1 (such as RGB, or RGB with alpha) , sift will convert the input image into greyscale before running its algorithm. You can convert to greyscale yourself before using sift with

More info on how opencv defines image depths (CV_8U) or types (CV_8UC1) can be found here.

P.S. I am new on stackoverflow, please let me know any problems/suggestions with my formatting. Thank you!

Retiarius answered 31/10, 2019 at 23:54 Comment(0)
H
0

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

Hangbird answered 8/2, 2023 at 11:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.