Search code examples
pythonscikit-imageorb

'The parameter `image` must be a 2-dimensional array'


I'm trying to extract orb features via scikit-image, but I got the error The parameter image must be a 2-dimensional array. I converted it to greyscale so the image is actually 2-dimensional.

    from skimage.feature import ORB
    from skimage.color import rgb2gray

    def find_orb(img, n_keypoints=2000, **kwargs):
        descriptor_extractor = ORB(n_keypoints, **kwargs)
        descriptor_extractor.detect_and_extract(rgb2gray(img))
        return descriptor_extractor.keypoints, descriptor_extractor.descriptors

    pano_image_collection = io.ImageCollection('jpeg/lowres/8_*.jpg',
                                    load_func=lambda f:io.imread(f).astype(np.float32) / 255)
    img = pano_image_collection[0]
    keypoints, descriptors = find_orb(img)

And this is the error

ValueError                                Traceback (most recent call last)
<ipython-input-5-5dce31f8d3f4> in <module>()
----> 7 keypoints, descriptors = find_orb(img)

<ipython-input-4-26e09ccf38ce> in find_orb(img, n_keypoints, **kwargs)
 14     descriptor_extractor = ORB(n_keypoints, **kwargs)
---> 15     descriptor_extractor.detect_and_extract(rgb2gray(img))
 16     return descriptor_extractor.keypoints, descriptor_extractor.descriptors

/usr/local/lib/python3.6/site-packages/skimage/feature/orb.py in detect_and_extract(self, image)
302 
303             keypoints, orientations, responses = \
--> 304                 self._detect_octave(octave_image)
305 
306             if len(keypoints) == 0:

/usr/local/lib/python3.6/site-packages/skimage/feature/orb.py in _detect_octave(self, octave_image)
139         # Extract keypoints for current octave
140         fast_response = corner_fast(octave_image, self.fast_n,
--> 141                                     self.fast_threshold)
142         keypoints = corner_peaks(fast_response, min_distance=1)
143 

/usr/local/lib/python3.6/site-packages/skimage/feature/corner.py in corner_fast(image, n, threshold)
745 
746     """
--> 747     image = _prepare_grayscale_input_2D(image)
748 
749     image = np.ascontiguousarray(image)

/usr/local/lib/python3.6/site-packages/skimage/feature/util.py in _prepare_grayscale_input_2D(image)
140 def _prepare_grayscale_input_2D(image):
141     image = np.squeeze(image)
--> 142     assert_nD(image, 2)
143     return img_as_float(image)
144 

/usr/local/lib/python3.6/site-packages/skimage/_shared/utils.py in assert_nD(array, ndim, arg_name)
176         raise ValueError(msg_empty_array % (arg_name))
177     if not array.ndim in ndim:
--> 178         raise ValueError(msg_incorrect_dim % (arg_name, '-or-'.join([str(n) for n in ndim])))
179 
180 

ValueError: The parameter `image` must be a 2-dimensional array

Solution

  • I am afraid I cannot help you anymore than this: I ran it with a debugger and the image at the second level of the pyramid that is created internally in ORB has only one entry and shape (1, 1), which will be redcued to a one-dimensional image in a subsequent np.squeeze call.

    Update: Op (Daria Musatkina) has found solution to the problem, quoting: The problem here is that first parameter for orb is downsample and not n_keypoints. That's why octave with shape (1, 1) was created.

    For reference, the ORB API doc

    My initial answer was incorrect (see comments below):

    I assume that your image is RGB, which is probably imported as a 2D + channel (3D total) numpy.ndarray with uint8 entries. ndarray.astype does not change the dimensionality of the image, only the data type. Instead of a 3D array of uint8, you now have a 3D array of float32, with the same values (not considering any numerical errors here). Thus, you did not convert into gray scale space, you just changed the data type of your array. You could try to use np.mean along the channel axis, instead, for example.