【问题标题】:OpenCV CascadeClassifier detectMultiScale resulting Rect outside input Mat boundsOpenCV CascadeClassifier detectMultiScale 结果 Rect 超出输入 Mat 边界
【发布时间】:2016-09-01 19:39:46
【问题描述】:

detectMultiScale 返回输入 Mat 边界之外的矩形时遇到问题。

所以我正在做的是一种优化技术,其中视频源的第一帧被传递给完整的detectMultiScale。

如果检测到对象,我会创建一个临时垫,我会从当前完整帧克隆之前检测到对象的矩形。

然后我将这个临时垫传递给detectMultiScale,因此只有前一帧检测到对象的矩形周围的区域。

我遇到的问题是,在传递 temp Mat 时,detectMultiScale 的结果会给出输入 temp Mat 边界之外的矩形。

主要是我想知道这里到底发生了什么。我对可能发生的事情有两个想法,但我无法确定。

  1. 将矩形从完整帧克隆到临时 Mat 时的克隆操作位于 Mat 对象内部的某个位置,将克隆区域设置为完整帧的行和列。例如,我有一个 100x100 的全帧,我试图在 80x80 的位置从它克隆一个 10x10 的矩形。生成的 Mat 大小将是 10x10,但可能在 Mat 内部某处说 Mat 从 80x80 开始?

  2. CascadeClassifier 是否将状态保持在我之前传递给它的全帧的某个位置?

我不确定这里发生了什么,但希望有人能解释一下。

这是我正在尝试做的一个小代码示例,cmets 解释了我看到的结果:

std::vector<cv::Rect> DetectObjects(cv::Mat fullFrame, bool useFullFrame, cv::Rect detectionRect)
{
    // fullFrame is 100x100
    // detectionRect is 10x10 at position 80x80 eg. cv::Rect(80,80,10,10)
    // useFullFrame is False

    std::vector<cv::Rect> results;
    if(useFullFrame)
    {
        object_cascade.detectMultiScale(fullFrame,
                results,
                m_ScaleFactor,
                m_Neighbors,
                0 | cv::CASCADE_SCALE_IMAGE | cv::CASCADE_DO_ROUGH_SEARCH  | cv::CASCADE_DO_CANNY_PRUNING,
                m_MinSize,
                m_MaxSize);
    }
    else
    {
        // useFullFrame is false, so we run this block

        cv::Mat tmpMat = fullFrame(detectionRect).clone();
        // tmpMat is size 10,10

        object_cascade.detectMultiScale(tmpMat,
                results,
                m_ScaleFactor,
                m_Neighbors,
                0 | cv::CASCADE_SCALE_IMAGE | cv::CASCADE_DO_ROUGH_SEARCH  | cv::CASCADE_DO_CANNY_PRUNING,
                m_MinSize,
                m_MaxSize);
    }

    if(results.size() > 0)
    {
        // this is the weird part. When looking at the first element of
        // results, (result[0]), it is at position 80,80, size 10,10
        // so it is cv::Rect(80,80,10,10)
        // even though the second detectMultiScale was ran with a Mat of 10x10

        // do stuff
    }
}

这与我在代码中的内容非常接近,除了我在上面提到的 cmets 中的实际示例值之外,我使用的值很简单,而不是像 1920x1080 和实际结果这样的全帧值,例如 367x711 .

那么为什么我从 detectMultiScale 得到的结果超出了输入 Mat 的范围?

编辑:

我最初为嵌入式 linux 发行版编写了这个程序,没有出现这个问题(我总是得到预期的结果)。这个问题发生在 Windows 版本和 opencv 的构建上,所以我目前正在查看 opencv 代码,看看是否有任何与此相关的突出内容。

【问题讨论】:

    标签: c++ windows opencv


    【解决方案1】:

    我相信这是一个简单的逻辑错误。这个:

    if(fullFrame)
    

    应该是这样的:

    if(useFullFrame)
    

    【讨论】:

    • 对不起,这是上面代码中的错字。我没有复制粘贴,只是手动输入的。 if 语句的第二块实际上正在运行。感谢您的建议,有时您只需要第二双眼睛,但在这种情况下,我已经通过调试并逐行执行代码排除了这种可能性
    • 在这种情况下,我猜关键在于Mat::operator () 的详细信息。根据文档,它只是创建一个新的标头,而克隆操作只是创建整个矩阵、标头和所有内容的新深层副本。因此,虽然像 detectMultiScale 这样的函数可能尊重定义的 ROI,但它们仍然可能返回绝对坐标。 (根据您的问题,听起来这正是它的行为方式。)我将消除克隆操作并通过偏移量调整返回的结果。
    • 我现在要调查一下,这听起来就像正在发生的事情。我会报告我的发现。奇怪的是,虽然这在我的 opencv linux 版本中没有发生,但您会认为代码在逻辑上基本相同
    猜你喜欢
    • 1970-01-01
    • 2021-04-15
    • 2016-03-07
    • 2020-11-27
    • 2021-11-02
    • 2021-02-26
    • 1970-01-01
    • 1970-01-01
    • 2018-10-23
    相关资源
    最近更新 更多