Лев Белый
Лев Белый

Reputation: 11

Python cv2 ORB detectandcompute returning "invalid number of channels in input image"

I'm trying to extract and match features from two different images but for some reason the "detectAndCompute" method doesn¡t work on my orb object: orb = cv2.ORB_create() kp, corners = orb.detectAndCompute(image,None I am passing a single grayscale image (the return of the function np.float32(cv2.cvtColor(image, cv2.COLOR_BGR2GRAY))). For some reason, the program returns the following error: Traceback (most recent call last): File "C:\Users\levxr\Desktop\Visual-positioning-bot-main\alloverlay.py", line 37, in cv2.imshow("camera "+str(i), corn1.updateanddisplay()) File "C:\Users\levxr\Desktop\Visual-positioning-bot-main\features.py", line 33, in updateanddisplay dst = self.update(image=self.image) File "C:\Users\levxr\Desktop\Visual-positioning-bot-main\features.py", line 23, in update kp, corners = orb.detectAndCompute(image,None) cv2.error: OpenCV(4.4.0) c:\users\appveyor\appdata\local\temp\1\pip-req-build-95hbg2jt\opencv\modules\imgproc\src\color.simd_helpers.hpp:92: error: (-2:Unspecified error) in function '__cdecl cv::impl::anonymous-namespace'::CvtHelper<struct cv::impl::anonymous namespace'::Set<3,4,-1>,struct cv::impl::A0x2980c61a::Set<1,-1,-1>,struct cv::impl::A0x2980c61a::Set<0,2,5>,2>::CvtHelper(const class cv::_InputArray &,const class cv::_OutputArray &,int)'

Invalid number of channels in input image: 'VScn::contains(scn)' where 'scn' is 1

The program is split in 3 files, alloverlay.py(the main file):

import sys
import cv2
import numpy as np
import features as corn
import camera as cali
cv2.ocl.setUseOpenCL(False)
#videoname = input("enter input")
videoname = "camera10001-0200.mkv"
try:
    videoname = int(videoname)
    cap = cv2.VideoCapture(videoname)
except:
    cap = cv2.VideoCapture(videoname)
videoname2 = "camera 20000-0200.mkv"
try:
    videoname = int(videoname)
    cap2 = cv2.VideoCapture(videoname)
except:
    cap2 = cv2.VideoCapture(videoname)
if cap.isOpened()and cap2.isOpened():
    ret1, image1 = cap.read()
    ret2, image2 = cap2.read()
    ret = [ret1, ret2]
    image = [np.float32(cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)), np.float32(cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY))]
    cali1 = cali.Calibrator()
    corn1 = corn.Corner_detector(image)
while cap.isOpened() and cap2.isOpened():
    ret[0], image[0] = cap.read()
    ret[1], image[1] = cap2.read()
    if ret:
        backupimg = image
        for i, img in enumerate(image):
            if cali1.calibrated:
                backupimg[i] = corn1.image = cali1.undistort(np.float32(cv2.cvtColor(image[i], cv2.COLOR_BGR2GRAY)), cali1.mtx, cali1.dist)
            else:
                backupimg[i] = corn1.image = np.float32(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY))
            cv2.imshow("camera "+str(i), corn1.updateanddisplay())
        image = backupimg
        print(ret, image)
        #cv2.imshow("test", image)
        key = cv2.waitKey(1)
        if key == ord("c"):
            cali1.calibrate(cali1.image)
        if cv2.waitKey(25) & 0xFF == ord("q"):
            break
    else:
        print("capture not reading")
        break
cap.release()

, camera.py(module to calibrate and undistort the camera and triangulate the relative position of the point (a different part of this project, irrelevant to this issue)):

import sys
import cv2
#import glob
import numpy as np
cv2.ocl.setUseOpenCL(False)
class Missing_calibration_data_error(Exception):
    def __init__():
        pass
class Calibrator():
    def __init__(self, image=None, mtx=None, dist=None, camera_data={"pixelsize":None, "matrixsize":None, "baseline":None, "lens_distance":None}, criteria=(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001), calibrated = False):
        self.criteria = criteria
        self.objpoints = []
        self.imgpoints = []
        self.objp = np.zeros((6*7,3), np.float32)
        self.objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)
        self.image = image
        self.mtx = mtx
        self.dist = dist
        self.calibrated = calibrated
        self.pixelsize = camera_data["pixelsize"]
        self.matrixsize = camera_data["matrixsize"]
        self.baseline = camera_data["baseline"]
        self.lens_distance = camera_data["lens_distance"]
    def calibrate(self, image):
        gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
        ret, corners = cv2.findChessboardCorners(gray, (7,6),None)
        if ret == True:
            self.objpoints.append(self.objp)
            corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),self.criteria)
            self.imgpoints.append(corners2)
            h,  w = image.shape[:2]
            ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)
            self.mtx = mtx
            self.dist = dist
            self.calibrated = True
            return mtx, dist
    def undistort(self, image, mtx, dist):
        if dist == None or mtx == None or image == None:
            raise Missing_calibration_data_error
            h,  w = image.shape[:2]
        newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))
        dst = cv2.undistort(image, mtx, dist, None, newcameramtx)
        x,y,w,h = roi
        dst = dst[y:y+h, x:x+w]
        return image
    def calculate_point_relative_position(self, point_location2d):
        angle = self.baseline/(point_location2d[left][x]-point_location2d[right][x])
        x = angle * (point_location2d[left][x]-self.matrixsize[0]/2)
        y = angle * (point_location2d[left][y]-self.matrixsize[1]/2)
        z = self.lens_distance * (1-angle/self.pixelsize)
        return [x, y, z]
´´´
, and features.py(module to detect and match the features, aparently where the issue happens):
´´´
import sys
import cv2
import numpy as np
cv2.ocl.setUseOpenCL(False)
class Unknown_algorythm_error(Exception):
    def __init__(self):
        pass
class No_image_passed_error(Exception):
    def __int__ (self):
        pass
class Corner_detector():
    def __init__(self, image, detectortype="ORB", corners=[]):
        self.corners = corners
        self.image = image
        self.detectortype = detectortype
    def update(self, image=None):
        if self.detectortype == "Harris":
            self.corners = cv2.cornerHarris(image, 3, 3, 0, 1)
        elif self.detectortype == "Shi-Tomasi":
            self.corners = cv2.goodFeaturesToTrack(image, 3, 3, 0, 1)
        elif self.detectortype == "ORB":
            orb = cv2.ORB_create()
            kp, corners = orb.detectAndCompute(image,None)
        elif self.detectortype == "SURF":
            minHessian = 400
            detector = cv2.features2d_SURF(hessianThreshold=minHessian)
            keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
            keypoints2, descriptors2 = detector.detectAndCompute(img2, None)
        else:
            raise Unknown_algoryth_error
        return self.corners
    def updateanddisplay(self):
        dst = self.update(image=self.image)
        self.image[dst>0.01*dst.max()] = 0
        return self.image
class Feature_matcher():
    def __init__(self, matcher = cv2.DescriptorMatcher_create(cv2.DescriptorMatcher_FLANNBASED)):
        self.matcher = matcher

´´´
Does anyone know how to fix this? I've been looking for the answer for quite a while but i only find the answer for when you're converting the image to grayscale and it doesnt work for me.



Upvotes: 1

Views: 1774

Answers (1)

Rotem
Rotem

Reputation: 32084

It's hard to follow, but I think I identified the issue:
You are passing orb.detectAndCompute an image of type np.float32.

  • orb.detectAndCompute does not support image of type np.float32.

Reproducing the problem:

The following "simple test" reproduces the problem:
The code sample passes a black (zeros) image to orb.detectAndCompute:

The following code passes without an exception (image type is np.uint8):

# image type is uint8:
image = np.zeros((100, 100), np.uint8)
orb = cv2.ORB_create()
kp, corners = orb.detectAndCompute(image, None)

The following code raises an exception because image type is np.float32:

# image type is float32:
image = np.float32(np.zeros((100, 100), np.uint8))
orb = cv2.ORB_create()
kp, corners = orb.detectAndCompute(image, None)

Rises an exception:

Invalid number of channels in input image:


Solution:

Try to avoid the np.float32 conversion.
You may also convert image to uint8 as follows:

kp, corners = orb.detectAndCompute(image.astype(np.uint8), None)

Upvotes: 1

Related Questions