问题
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:
I am currently using conda environment with opencv2.4.11.
回答1:
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 likeimage8bit = 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!
来源:https://stackoverflow.com/questions/50298329/error-5-image-is-empty-or-has-incorrect-depth-cv-8u-in-function-cvsift