cv2.dnn.NMSBoxes
opencv-python 中cv2.dnn.NMSBoxes接口说明很简单,如下
def NMSBoxes(bboxes, scores, score_threshold, nms_threshold, eta=None, top_k=None): # real signature unknown; restored from __doc__
"""
NMSBoxes(bboxes, scores, score_threshold, nms_threshold[, eta[, top_k]]) -> indices
. @brief Performs non maximum suppression given boxes and corresponding scores.
.
. * @param bboxes a set of bounding boxes to apply NMS.
. * @param scores a set of corresponding confidences.
. * @param score_threshold a threshold used to filter boxes by score.
. * @param nms_threshold a threshold used in non maximum suppression.
. * @param indices the kept indices of bboxes after NMS.
. * @param eta a coefficient in adaptive threshold formula: \f$nms\_threshold_{i+1}=eta\cdot nms\_threshold_i\f$.
. * @param top_k if `>0`, keep at most @p top_k picked indices.
"""
pass
其中,参数bboxes
,没有太多有用的说明,我们目标检测算法不同,产生的bboxes的表示形式也有差异。所以需要弄清楚NMSBoxes函数的bboxes具体形式。既然Python接口中没有太多信息,我们查看C++的api说明。
翻阅Opencv-4.5.4的API文档,我们找到3个不同的API声明,如下的说明:
第三个与Python一致,我们查看其说明,与Python一致,说明是一样的,但遗憾的是其参说明没有提供比Python更多信息,
接下来,我们查看了其参数MatOfRect2d
类型说明,一样无所获,没办法,去其C++源码,碰碰运气。
/** @brief Performs non maximum suppression given boxes and corresponding scores.
* @param bboxes a set of bounding boxes to apply NMS.
* @param scores a set of corresponding confidences.
* @param score_threshold a threshold used to filter boxes by score.
* @param nms_threshold a threshold used in non maximum suppression.
* @param indices the kept indices of bboxes after NMS.
* @param eta a coefficient in adaptive threshold formula: \f$nms\_threshold_{i+1}=eta\cdot nms\_threshold_i\f$.
* @param top_k if `>0`, keep at most @p top_k picked indices.
*/
CV_EXPORTS void NMSBoxes(const std::vector<Rect>& bboxes, const std::vector<float>& scores,
const float score_threshold, const float nms_threshold,
CV_OUT std::vector<int>& indices,
const float eta = 1.f, const int top_k = 0);
CV_EXPORTS_W void NMSBoxes(const std::vector<Rect2d>& bboxes, const std::vector<float>& scores,
const float score_threshold, const float nms_threshold,
CV_OUT std::vector<int>& indices,
const float eta = 1.f, const int top_k = 0);
NMSBoxes
的C++源码声明如上,我们可以看到相似声明有3个,但我们显然不看其实现,看到其参数bboxes
的有Rect
和Rect2d
两种,查看其声明如下,其实就是Rect_
在int、float、double的三种形态。
typedef Rect_<int> Rect2i;
typedef Rect_<float> Rect2f;
typedef Rect_<double> Rect2d;
typedef Rect2i Rect;
查看Rect_的定义,代码挺简单。
/** @brief Template class for 2D rectangles
described by the following parameters:
- Coordinates of the top-left corner. This is a default interpretation of Rect_::x and Rect_::y
in OpenCV. Though, in your algorithms you may count x and y from the bottom-left corner.
- Rectangle width and height.
OpenCV typically assumes that the top and left boundary of the rectangle are inclusive, while the
right and bottom boundaries are not. For example, the method Rect_::contains returns true if
\f[x \leq pt.x < x+width,
y \leq pt.y < y+height\f]
Virtually every loop over an image ROI in OpenCV (where ROI is specified by Rect_\<int\> ) is
implemented as:
@code
for(int y = roi.y; y < roi.y + roi.height; y++)
for(int x = roi.x; x < roi.x + roi.width; x++)
{
// ...
}
@endcode
In addition to the class members, the following operations on rectangles are implemented:
- \f$\texttt{rect} = \texttt{rect} \pm \texttt{point}\f$ (shifting a rectangle by a certain offset)
- \f$\texttt{rect} = \texttt{rect} \pm \texttt{size}\f$ (expanding or shrinking a rectangle by a
certain amount)
- rect += point, rect -= point, rect += size, rect -= size (augmenting operations)
- rect = rect1 & rect2 (rectangle intersection)
- rect = rect1 | rect2 (minimum area rectangle containing rect1 and rect2 )
- rect &= rect1, rect |= rect1 (and the corresponding augmenting operations)
- rect == rect1, rect != rect1 (rectangle comparison)
This is an example how the partial ordering on rectangles can be established (rect1 \f$\subseteq\f$
rect2):
@code
template<typename _Tp> inline bool
operator <= (const Rect_<_Tp>& r1, const Rect_<_Tp>& r2)
{
return (r1 & r2) == r1;
}
@endcode
For your convenience, the Rect_\<\> alias is available: cv::Rect
*/
template<typename _Tp> class Rect_
{
public:
typedef _Tp value_type;
//! default constructor
Rect_();
Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height);
#if OPENCV_ABI_COMPATIBILITY < 500
Rect_(const Rect_& r) = default;
Rect_(Rect_&& r) CV_NOEXCEPT = default;
#endif
Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz);
Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2);
#if OPENCV_ABI_COMPATIBILITY < 500
Rect_& operator = (const Rect_& r) = default;
Rect_& operator = (Rect_&& r) CV_NOEXCEPT = default;
#endif
//! the top-left corner
Point_<_Tp> tl() const;
//! the bottom-right corner
Point_<_Tp> br() const;
//! size (width, height) of the rectangle
Size_<_Tp> size() const;
//! area (width*height) of the rectangle
_Tp area() const;
//! true if empty
bool empty() const;
//! conversion to another data type
template<typename _Tp2> operator Rect_<_Tp2>() const;
//! checks whether the rectangle contains the point
bool contains(const Point_<_Tp>& pt) const;
_Tp x; //!< x coordinate of the top-left corner
_Tp y; //!< y coordinate of the top-left corner
_Tp width; //!< width of the rectangle
_Tp height; //!< height of the rectangle
};
能用到的构造函数就是
Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height);
其参数说明,可以参考类变量注释:
_Tp x; //!< x coordinate of the top-left corner
_Tp y; //!< y coordinate of the top-left corner
_Tp width; //!< width of the rectangle
_Tp height; //!< height of the rectangle
所以cv2.dnn.NMSBoxes的bboxes框应该是左上角坐标(x,y)和 w,h, 那么针对不同模型的,要具体情况转化一下,才能应用该函数。