小编Rob*_*ert的帖子

使用 OpenCV 检测图像中已知形状/对象的方法

我的任务是使用 OpenCV 检测给定图像中的对象(我不在乎它是 Python 还是 C++ 实现)。下面的三个示例中显示的对象是一个黑色矩形,其中包含五个白色矩形。所有维度都是已知的。

在此处输入图片说明

但是,图像的旋转、比例、距离、透视、照明条件、相机焦距/镜头和背景是未知的。黑色矩形的边缘不能保证完全可见,但是在五个白色矩形之前不会有任何东西 - 它们将始终完全可见。最终目标是能够检测图像中该对象的存在,并旋转、缩放和裁剪以显示移除透视的对象。鉴于它的四个角,我相当有信心我可以调整图像以仅裁剪对象。但是,我不太有信心能够可靠地找到这四个角。在模棱两可的情况下,与将图像的某些其他特征误识别为对象相比,没有找到对象更可取。

使用 OpenCV 我想出了以下方法,但是我觉得我可能会遗漏一些明显的东西。是否有更多方法可用,或者其中一种是最佳解决方案?

基于边缘的轮廓

第一个想法是寻找物体的外边缘。

使用 Canny 边缘检测(在缩放到已知大小、灰度和高斯模糊之后),找到与对象外部形状最匹配的轮廓。这可以解决透视、颜色、大小问题,但如果背景复杂,或者图像中其他地方有与对象形状相似的东西,则会失败。也许这可以通过一组更好的规则来改进以找到正确的轮廓 - 可能涉及五个白色矩形以及外边缘。

在此处输入图片说明 在此处输入图片说明

特征检测

下一个想法是使用特征检测匹配已知模板。

使用 ORB 特征检测、描述符匹配和单应性(来自本教程)失败,我相信是因为它检测的特征与对象内的其他特征非常相似(许多核心是四分之一白和四分之三黑) . 但是,我确实喜欢匹配已知模板的想法 - 这个想法对我来说很有意义。我想虽然因为对象在几何上非常基本,所以在特征匹配步骤中可能会发现很多误报。

在此处输入图片说明

平行线

使用 Houghlines 或 HoughLinesP,寻找间隔均匀的平行线。刚刚开始走这条路,所以需要研究阈值等的最佳方法。虽然对于具有复杂背景的图像来说看起来很混乱,但我认为它可能工作得很好,因为我可以依靠黑色对象中的白色矩形应该始终对比度高,可以很好地指示线条的位置。

在此处输入图片说明

'条码扫描'

我的最终想法是逐行扫描图像,寻找白色到黑色的图案。

我还没有开始使用这种方法,但我的想法是取一条图像(在某个角度),转换为 HSV 颜色空间,并在 Value 列中查找按顺序出现五次的常规黑白图案。这个想法对我来说听起来很有希望,因为我认为它应该忽略许多未知变量。

想法

我已经看过了许多OpenCV的教程,以及SO问题,如这一个,但是因为我的目标是相当简单的几何我有实施给出的思路问题。

我觉得这是一个可以实现的任务,但我的挣扎是不知道进一步追求哪种方法。我对前两个想法进行了相当多的试验,虽然我没有取得任何非常可靠的成果,但也许我遗漏了一些东西。是否有一种我没有想到的标准方法来完成这项任务,或者我建议的方法之一是最明智的?

编辑:一旦使用上述方法之一(或其他方法)找到角落,我正在考虑使用 Hu Moments 或 OpenCV 的 matchShapes() 函数来消除任何误报。

EDIT2:根据@Timo 的要求添加了更多输入图像示例


c++ python opencv image-processing

11
推荐指数
1
解决办法
6893
查看次数

协程和带有静态变量的函数有什么区别?

我一直在学习 C++20 中的新功能,并试图了解共同讨论的共同例程的“生成器”用例。我试图在这里创建一个小例子,但如果有错误,我深表歉意:

generator<int> Generate() {
    int i = 0;
    while(1) {
        co_yield i++;
    }
}

int main()
{
    auto gen { Generate() };
    for (int x = 0; x < 10; ++x) {
        gen.next();
        std::cout << gen.getValue() << std::endl;
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是我看不出这与具有静态变量的函数有何不同,例如:

auto gen() {
    static int i = 0;
    return i++;
}

int main()
{
    for (int x = 0; x < 10; ++x)
        std::cout << gen() << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我想我可能会看到异步 I/O 是一个用例,尤其是使用co_await …

c++ coroutine c++20

8
推荐指数
1
解决办法
376
查看次数

如何将默认的太空飞船运算符与 std::string 成员一起使用

我有一个包含一些 POD 类型和一个字符串成员的结构。我想使用默认的太空飞船运算符来允许对我的结构进行相等操作,但我在字符串成员方面遇到了一些问题。据我所知,应该支持<=>std::string但实际上情况似乎并非如此。

我有一个最小的复制示例,以及我从下面的 clang (版本 14)得到的警告。奇怪的是,在 godbolt 中,这个示例没有产生警告/错误,甚至可以追溯到 clang 12 ( https://godbolt.org/z/b65s9oMGf )。

我真的很感激有人指出我的误解在哪里,因为我对此感到非常困惑。

#include <compare>
#include <string>

enum class MyEnum
{
    ZERO = 0,
    ONE = 1
};

struct MyStruct
{
    float a{};
    int b{};
    std::string c{};
    MyEnum d{};

    auto operator<=>(const MyStruct&) const = default;
};

int main()
{
    MyStruct my_struct;
    MyStruct my_other_struct;

    if(my_struct == my_other_struct)
    {
        return 0;
    }

    return 1;
}
Run Code Online (Sandbox Code Playgroud)
$ clang --std=c++20 -Werror test.cpp                                                                                                                                                                                      
test.cpp:16:10: error: explicitly defaulted three-way comparison …
Run Code Online (Sandbox Code Playgroud)

c++ clang c++20

3
推荐指数
1
解决办法
767
查看次数

标签 统计

c++ ×3

c++20 ×2

clang ×1

coroutine ×1

image-processing ×1

opencv ×1

python ×1