opencv version 3.* HogDescriptor takes at most 1 argument (5 given)

匿名 (未验证) 提交于 2019-12-03 01:05:01

问题:

I am trying to use HogDescriptor and I am getting this error. I saw in the document that the constructor can take more then one argument. I am working in python 3.6 and opencv 3.2

This is my code:

def _extract_feature(X):     """Performs feature extraction          :param X:       data (rows=images, cols=pixels)         :param feature: which feature to extract                         - "hog":  HOG features         :returns:       X (rows=samples, cols=features)     """      X = [cv2.cvtColor(x, cv2.COLOR_BGR2GRAY) for x in X]      # operate on smaller image     small_size = (32, 32)     X = [cv2.resize(x, small_size) for x in X]      # histogram of gradients     block_size = (small_size[0] / 2, small_size[1] / 2)     block_stride = (small_size[0] / 4, small_size[1] / 4)     cell_size = block_stride     num_bins = 9     hog = cv2.HOGDescriptor(small_size, block_size, block_stride,                             cell_size, num_bins)     X = [hog.compute(x) for x in X]      X = [x.flatten() for x in X]     return X 

So why am I getting the error:

TypeError: HogDescriptor takes at most 1 argument (5 given) 

Update: I installed python 2.7 and tried it and it works.

回答1:

The issue you're observing is due to combination of several factors:

  • PEP-238
  • Mapping to Python and dispatching of overloaded C++ functions (as done in OpenCV)

Division in Python

The meaning of operator / has changed between Python 2.x and Python 3.x.

From PEP-238:

  • Classic division will remain the default in the Python 2.x series; true division will be standard in Python 3.0

For example, in Python 2.x you have

>>> small_size = (32, 32) >>> block_size = (small_size[0] / 2, small_size[1] / 2) >>> print(block_size) (16, 16) 

And in Python 3.x you have

>>> small_size = (32, 32) >>> block_size = (small_size[0] / 2, small_size[1] / 2) >>> print(block_size) (16.0, 16.0) 

In order to get the same result, your Python 3.x code would need to use operator //

>>> small_size = (32, 32) >>> block_size = (small_size[0] // 2, small_size[1] // 2) >>> print(block_size) (16, 16) 

Mapping and Handling of Overloads

Without going into detail (that would warrant a separate question), the overload resolution depends on the types of arguments. The matching of types is quite strict, e.g. you may not pass a floating point number to an integer argument.

The C++ signature of the constructor in question (truncated to only the relevant arguments) is

HOGDescriptor (Size _winSize     , Size _blockSize     , Size _blockStride     , Size _cellSize     , int _nbins, ...) 

cv::Size is a class that contains two integers. In the Python API, it is represented as a tuple containing two integers.

Therefore, to call this overload in Python, we need to provide:

  • 4x a tuple containing two integers (for _winSize, _blockSize, _blockStride, and _cellSize)
  • 1x an integer (for _nbins)

We can test this out in the Python interpreter.

>>> import cv2 >>> cv2.HOGDescriptor((1,1),(1,1),(1,1),(1,1),1) <HOGDescriptor 0393D0F0> 

This matches our expectations. Let's try some other options.

>>> cv2.HOGDescriptor((1,1,1),(1,1),(1,1),(1,1),1) TypeError: HOGDescriptor() takes at most 1 argument (5 given) >>> cv2.HOGDescriptor((1,),(1,1),(1,1),(1,1),1) TypeError: HOGDescriptor() takes at most 1 argument (5 given) 

We see the tuples need to have 2 values, no more, no less.

>>> cv2.HOGDescriptor([1,1],(1,1),(1,1),(1,1),1) TypeError: HOGDescriptor() takes at most 1 argument (5 given) 

Lists won't do, it has to be a tuple.

>>> cv2.HOGDescriptor((1.0,1.0),(1,1),(1,1),(1,1),1) TypeError: HOGDescriptor() takes at most 1 argument (5 given) 

Tuples of floats won't work either.

>>> cv2.HOGDescriptor((1,1),(1,1),(1,1),(1,1),1.0) TypeError: HOGDescriptor() takes at most 1 argument (5 given) 

Nor can we substitute an float for an integer.

Pulling it All Together

Considering the above, in terms of the values you pass the constructor, the two variants are:

  • Python 2.x: cv2.HOGDescriptor((32,32),(16,16),(8,8),(8,8),9)
  • Python 3.x: cv2.HOGDescriptor((32,32),(16.0,16.0),(8.0,8.0),(8.0,8.0),9)

We can clearly see that the parameters in Python 3.x don't satisfy the requirements of the overload.

As to why we get the misleading error message, that seems like another topic warranting a separate question, and I haven't done all the research necessary to answer this authoritatively.



回答2:

HOGDescriptor is an overloaded function.

If you look at the c++ documentation, it shows 4 versions - one with no parameters, one with 12, one with string and one with an option I'm not immediately familiar with.

You've tried to use one with 5 arguments. There isn't a function for that. You need to use either none, all 12 or one. If you look at this StackOverflow question, this person has supplied an xml file for the control specification - this fits the string filename option and hence is a valid function.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!