我的任务是使用 OpenCV 检测给定图像中的对象(我不在乎它是 Python 还是 C++ 实现)。下面的三个示例中显示的对象是一个黑色矩形,其中包含五个白色矩形。所有维度都是已知的。
但是,图像的旋转、比例、距离、透视、照明条件、相机焦距/镜头和背景是未知的。黑色矩形的边缘不能保证完全可见,但是在五个白色矩形之前不会有任何东西 - 它们将始终完全可见。最终目标是能够检测图像中该对象的存在,并旋转、缩放和裁剪以显示移除透视的对象。鉴于它的四个角,我相当有信心我可以调整图像以仅裁剪对象。但是,我不太有信心能够可靠地找到这四个角。在模棱两可的情况下,与将图像的某些其他特征误识别为对象相比,没有找到对象更可取。
使用 OpenCV 我想出了以下方法,但是我觉得我可能会遗漏一些明显的东西。是否有更多方法可用,或者其中一种是最佳解决方案?
第一个想法是寻找物体的外边缘。
使用 Canny 边缘检测(在缩放到已知大小、灰度和高斯模糊之后),找到与对象外部形状最匹配的轮廓。这可以解决透视、颜色、大小问题,但如果背景复杂,或者图像中其他地方有与对象形状相似的东西,则会失败。也许这可以通过一组更好的规则来改进以找到正确的轮廓 - 可能涉及五个白色矩形以及外边缘。
下一个想法是使用特征检测匹配已知模板。
使用 ORB 特征检测、描述符匹配和单应性(来自本教程)失败,我相信是因为它检测的特征与对象内的其他特征非常相似(许多核心是四分之一白和四分之三黑) . 但是,我确实喜欢匹配已知模板的想法 - 这个想法对我来说很有意义。我想虽然因为对象在几何上非常基本,所以在特征匹配步骤中可能会发现很多误报。
使用 Houghlines 或 HoughLinesP,寻找间隔均匀的平行线。刚刚开始走这条路,所以需要研究阈值等的最佳方法。虽然对于具有复杂背景的图像来说看起来很混乱,但我认为它可能工作得很好,因为我可以依靠黑色对象中的白色矩形应该始终对比度高,可以很好地指示线条的位置。
我的最终想法是逐行扫描图像,寻找白色到黑色的图案。
我还没有开始使用这种方法,但我的想法是取一条图像(在某个角度),转换为 HSV 颜色空间,并在 Value 列中查找按顺序出现五次的常规黑白图案。这个想法对我来说听起来很有希望,因为我认为它应该忽略许多未知变量。
我已经看过了许多OpenCV的教程,以及SO问题,如这一个,但是因为我的目标是相当简单的几何我有实施给出的思路问题。
我觉得这是一个可以实现的任务,但我的挣扎是不知道进一步追求哪种方法。我对前两个想法进行了相当多的试验,虽然我没有取得任何非常可靠的成果,但也许我遗漏了一些东西。是否有一种我没有想到的标准方法来完成这项任务,或者我建议的方法之一是最明智的?
编辑:一旦使用上述方法之一(或其他方法)找到角落,我正在考虑使用 Hu Moments 或 OpenCV 的 matchShapes() 函数来消除任何误报。
EDIT2:根据@Timo 的要求添加了更多输入图像示例
我一直在学习 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 …
我有一个包含一些 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)