Ошибка: (-5) изображение пустое или имеет неправильную глубину (!=CV_8U) в функции cv::SIFT::operator ()

Я пытаюсь запустить базовый скрипт из учебника по обнаружению объектов. Я перепробовал все, что мог найти в Интернете, но не смог решить. Уже пробовал разные предложенные методы для конвертации изображения в CV_U8. Также использовались 8-битные изображения в качестве входных данных, но без прогресса. Вот код:

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

Вот ошибка:

В настоящее время я использую среду conda с opencv2.4.11.

2 ответа

Функции просеивания (по крайней мере, конкретно .detectAndCompute())
Принимает ТОЛЬКО изображения с 8-битными целыми числами.

Перед использованием просеивания изображения преобразуйте его в 8-битное, используя что-то вроде
image8bit = cv2.normalize(image, None, 0, 255, cv2.NORM_MINMAX).astype('uint8')

ДЕТАЛИ
Исходный кодvoid SIFT_Impl::detectAndCompute(InputArray _image, ... ) содержит проверки исключений, которые проверяют, что данные являются 8-битными 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)" );

Вторая проверка применяется только к необязательному аргументу InputArray _mask, и эта маска может быть только CV_8UC1 это означает, что это должна быть глубина CV_8U и только 1 канал (так много оттенков серого).

На странице opencv, определяющей базовую структуру, уровень глубиныCV_8U определяется как

CV_8U - 8-битные целые числа без знака ( 0..255)

Это означает, что входное изображение должно быть определено 8-битными целыми числами со значениями 0-255.

Функция просеивания работает только в оттенках серого, поэтому вход также должен быть 1-канальным. Если вход имеет 3 или 4 канала вместо 1 (например, RGB или RGB с альфа-каналом), sift преобразует входное изображение в оттенки серого перед запуском своего алгоритма. Вы можете самостоятельно преобразовать в оттенки серого, прежде чем использовать sift с

Более подробную информацию о том, как opencv определяет глубину изображения (CV_8U) или типы (CV_8UC1), можно найти здесь.

PS Я новичок в stackru, пожалуйста, дайте мне знать о любых проблемах / предложениях с моим форматированием. Спасибо!

для людей, которые используютos.listdir()функция это моя ошибка

когда вы используете

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

в каждой папке есть файл с именем Thumbs.db, чтобы избежать его или запустить ваш код

вы должны написать такой код

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

в итоге работает

Другие вопросы по тегам