c++ 和 python 层之间的 opencv.groupRectangles() 差异

Posted

技术标签:

【中文标题】c++ 和 python 层之间的 opencv.groupRectangles() 差异【英文标题】:opencv.groupRectangles() discrepancy between c++ and python layers 【发布时间】:2019-01-31 14:42:03 【问题描述】:

我正在尝试将对 opencv 的 groupRectangles() 的调用从 python 转换为 c++,并注意到 python 绑定的输出与 c++ 调用的输出不匹配。

我已经编辑了下面的输出,以反映在 ubuntu 18.04 上使用 opencv 3.2 复制它

库版本

我在 Ubuntu 18.04 上运行 opencv。

c++ 程序链接到 opencv 3.2.0(由 ldd 报告)。

python 模块报告版本 3.2.0

C++ 代码

我编写了以下程序来获取一组 (x1, y1, x2, y2) 输入并将它们传递给groupRectangles(),组阈值为 3,epsilon 为 0.02。为了便于比较,输出以python的列表格式打印。

#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>

// display in python format
std::ostream& operator<<(std::ostream& out, std::vector<cv::Rect>& rectangles)

    out << '[';
    for (auto i = 0u; i<rectangles.size(); ++i)
    
        if (i)
            out << ',';
        out << '[' << rectangles[i].tl().x << ',' << rectangles[i].tl().y << ',' << rectangles[i].br().x << ',' << rectangles[i].br().y << ']';
    
    return out << ']';


// inputs are x1,y1,x2,y2
constexpr const float inputs[][4] = 547,432,701,639,557,435,700,640,560,438,695,641,560,438,694,640,88,443,336,663,83,444,357,671,83,444,373,676,87,449,377,676,87,454,380,677,76,453,388,680,72,447,394,683,80,437,393,683,101,430,392,678,547,433,702,641,555,433,701,645,558,437,696,647,556,440,696,644,84,443,357,664,73,448,369,665,74,449,375,664,81,451,373,664,85,454,375,666,81,454,385,672,74,452,392,676,77,445,396,679,91,433,392,680,547,430,705,644,553,429,704,649,555,434,697,649,552,438,695,649,85,445,365,661,69,451,376,662,69,452,379,663,76,453,374,663,80,452,377,666,79,451,382,671,74,449,388,673,77,445,393,673,90,434,389,674,546,429,706,643,553,428,703,647,554,432,695,649,553,435,693,654,81,445,370,663,68,454,383,664,67,455,388,664,72,454,384,667,77,452,382,669,71,448,386,671,66,443,388,672,73,438,389,671,92,429,388,673,545,429,706,642,553,429,703,643,553,432,695,647,553,432,696,658,79,450,367,664,72,459,379,663,71,459,387,665,75,458,388,667,75,455,390,666,65,448,389,668,63,441,387,669,73,433,384,672,100,425,388,675,549,429,707,648,550,429,701,652,554,434,703,662,79,462,356,665,73,462,374,665,74,461,383,666,73,460,387,667,69,457,391,664,60,447,390,668,63,435,385,673,81,430,384,676,116,433,390,677;

int main()

    std::vector<cv::Rect> candidates;
    std::transform(std::begin(inputs), std::end(inputs), std::back_inserter(candidates),
        [](const float coord[4]) 
            return cv::Rect(cv::Point((int)coord[0], (int)coord[1]), cv::Point((int)coord[2], (int)coord[3]));
         );

    std::cout << "input:\n" << candidates << '\n';
    std::vector<int> weights(candidates.size());
    cv::groupRectangles(candidates, weights, 3, 0.02); 
    std::cout << "output:\n" << candidates << '\n';

    return EXIT_SUCCESS;

测试执行

在执行 c++ 程序时,我得到以下输出:

input:
[[547,432,701,639],[557,435,700,640],[560,438,695,641],[560,438,694,640],[88,443,336,663],[83,444,357,671],[83,444,373,676],[87,449,377,676],[87,454,380,677],[76,453,388,680],[72,447,394,683],[80,437,393,683],[101,430,392,678],[547,433,702,641],[555,433,701,645],[558,437,696,647],[556,440,696,644],[84,443,357,664],[73,448,369,665],[74,449,375,664],[81,451,373,664],[85,454,375,666],[81,454,385,672],[74,452,392,676],[77,445,396,679],[91,433,392,680],[547,430,705,644],[553,429,704,649],[555,434,697,649],[552,438,695,649],[85,445,365,661],[69,451,376,662],[69,452,379,663],[76,453,374,663],[80,452,377,666],[79,451,382,671],[74,449,388,673],[77,445,393,673],[90,434,389,674],[546,429,706,643],[553,428,703,647],[554,432,695,649],[553,435,693,654],[81,445,370,663],[68,454,383,664],[67,455,388,664],[72,454,384,667],[77,452,382,669],[71,448,386,671],[66,443,388,672],[73,438,389,671],[92,429,388,673],[545,429,706,642],[553,429,703,643],[553,432,695,647],[553,432,696,658],[79,450,367,664],[72,459,379,663],[71,459,387,665],[75,458,388,667],[75,455,390,666],[65,448,389,668],[63,441,387,669],[73,433,384,672],[100,425,388,675],[549,429,707,648],[550,429,701,652],[554,434,703,662],[79,462,356,665],[73,462,374,665],[74,461,383,666],[73,460,387,667],[69,457,391,664],[60,447,390,668],[63,435,385,673],[81,430,384,676],[116,433,390,677]]
output:
[[546,431,704,642],[70,447,389,672],[555,435,696,647],[74,455,381,666]]

在 python 中,我将 c++ 输入剪切并粘贴为groupRectangles() 的输入,但得到完全不同的结果:

cv2.groupRectangles([[547,432,701,639],[557,435,700,640],[560,438,695,641],[560,438,694,640],[88,443,336,663],[83,444,357,671],[83,444,373,676],[87,449,377,676],[87,454,380,677],[76,453,388,680],[72,447,394,683],[80,437,393,683],[101,430,392,678],[547,433,702,641],[555,433,701,645],[558,437,696,647],[556,440,696,644],[84,443,357,664],[73,448,369,665],[74,449,375,664],[81,451,373,664],[85,454,375,666],[81,454,385,672],[74,452,392,676],[77,445,396,679],[91,433,392,680],[547,430,705,644],[553,429,704,649],[555,434,697,649],[552,438,695,649],[85,445,365,661],[69,451,376,662],[69,452,379,663],[76,453,374,663],[80,452,377,666],[79,451,382,671],[74,449,388,673],[77,445,393,673],[90,434,389,674],[546,429,706,643],[553,428,703,647],[554,432,695,649],[553,435,693,654],[81,445,370,663],[68,454,383,664],[67,455,388,664],[72,454,384,667],[77,452,382,669],[71,448,386,671],[66,443,388,672],[73,438,389,671],[92,429,388,673],[545,429,706,642],[553,429,703,643],[553,432,695,647],[553,432,696,658],[79,450,367,664],[72,459,379,663],[71,459,387,665],[75,458,388,667],[75,455,390,666],[65,448,389,668],[63,441,387,669],[73,433,384,672],[100,425,388,675],[549,429,707,648],[550,429,701,652],[554,434,703,662],[79,462,356,665],[73,462,374,665],[74,461,383,666],[73,460,387,667],[69,457,391,664],[60,447,390,668],[63,435,385,673],[81,430,384,676],[116,433,390,677]], 3, 0.02)
(array([[553, 433, 700, 647],
       [ 75, 449, 382, 669],
       [ 95, 430, 390, 676]], dtype=int32), array([[23],
       [46],
       [ 5]], dtype=int32))

这是我转换为 cv::RectgroupRectangles() 中的不确定性或其他问题的问题吗?

【问题讨论】:

【参考方案1】:

上面的问题完全在python c++ cv::Rect 的转换中。在 python 中,列表 [4] 是 x, y, height, width, not x1, y1, x2, y2(因为我被移植的代码中的错误导致我相信)。

如果我更改以下行,上面的代码可以正常工作。

打印时:

out << '[' << rectangles[i].tl().x << ',' << rectangles[i].tl().y << ',' << rectangles[i].width << ',' << rectangles[i].height << ']';

在构造cv::Rect时:

return cv::Rect((int)coord[0], (int)coord[1], (int)coord[2], (int)coord[3]);

【讨论】:

以上是关于c++ 和 python 层之间的 opencv.groupRectangles() 差异的主要内容,如果未能解决你的问题,请参考以下文章

使用 Redis 在 C++ 和 python 之间共享 Opencv 图像

OpenCV 的 Python 或 C++ 编码之间的性能是不是不同?

为使用 OpenCV 的 C++ 代码编写 Python 绑定

在 python 和 c++ 之间传递二进制数据

使用Opencv和C++在垂直方向的两点之间绘制直线

什么类型的数据可以在预编译的 C++ 和 Java for Android 之间传递?