小编Min*_*mal的帖子

图像处理:"可口可乐罐"识别的算法改进

在过去的几年里,我参与过的最有趣的项目之一是关于图像处理的项目.我们的目标是建立一个能够识别可口可乐"罐头"的系统(请注意,我正在强调'罐头'这个词,你会在一分钟内看到原因).您可以在下面看到一个示例,其中可以使用缩放和旋转在绿色矩形中识别.

模板匹配

对项目的一些限制:

  • 背景可能非常嘈杂.
  • 可以具有任何规模旋转,甚至方向(在合理的限度内).
  • 图像可能有一定程度的模糊性(轮廓可能不完全笔直).
  • 图像中可能有可口可乐瓶,算法应该只检测罐头!
  • 图像的亮度可能会有很大差异(因此您不能过多依赖颜色检测).
  • 可以部分地隐藏在两侧或中间,可能部分地隐藏了一瓶后面.
  • 有可能是没有像在所有的,在这种情况下,你必须找到什么,写一条消息这样说.

所以你最终可能会遇到这样棘手的事情(在这种情况下,我的算法完全失败):

总失败

我不久前做了这个项目,并且做了很多乐趣,我有一个不错的实现.以下是有关我的实施的一些细节:

语言:使用OpenCV库在C++中完成.

预处理:对于图像预处理,即将图像转换为更原始的形式以给出算法,我使用了两种方法:

  1. 将颜色域从RGB更改为HSV并基于"红色"色调进行过滤,饱和度高于某个阈值以避免橙色样色,并过滤低值以避免暗色调.最终结果是二进制黑白图像,其中所有白色像素将表示与该阈值匹配的像素.显然,图像中仍有很多废话,但这会减少您必须使用的维度数量. 二值化图像
  2. 使用中值滤波进行噪声滤波(取所有邻居的中值像素值并用该值替换像素)以减少噪声.
  3. 使用Canny边缘检测过滤器在2个先前步骤之后获取所有项目的轮廓. 轮廓检测

算法:我为这个任务选择的算法本身取自本关于特征提取的神奇书籍,称为广义霍夫变换(与常规Hough变换有很大不同).它基本上说了几件事:

  • 您可以在不知道其解析方程的情况下描述空间中的对象(这是这种情况).
  • 它可以抵抗图像变形,例如缩放和旋转,因为它基本上会针对比例因子和旋转因子的每个组合测试图像.
  • 它使用算法将"学习"的基本模型(模板).
  • 轮廓图像中剩余的每个像素将根据从模型中学到的内容投票给另一个像素,该像素应该是对象的中心(就重力而言).

最后,你得到了一张投票的热图,例如,这里所有罐子轮廓的像素都会投票给它的引力中心,所以你会在同一个像素对应的投票中得到很多票.中心,并将在热图中看到如下峰值:

GHT

一旦你有了这个,一个简单的基于阈值的启发式可以给你中心像素的位置,你可以从中获得比例和旋转,然后围绕它绘制你的小矩形(最终的比例和旋转因子显然将相对于你原始模板).理论上至少......

结果:现在,虽然这种方法在基本情况下起作用,但在某些方面却严重缺乏:

  • 非常慢!我并没有强调这一点.处理30个测试图像需要将近一整天,显然是因为我有一个非常高的旋转和平移比例因子,因为一些罐子非常小.
  • 当瓶子出现在图像中时,它完全丢失了,并且由于某种原因,几乎总是发现瓶子而不是罐头(可能因为瓶子更大,因此有更多的像素,因此更多的选票)
  • 模糊图像也不好,因为投票在中心周围的随机位置以像素结束,因此以非常嘈杂的热图结束.
  • 实现了平移和旋转的方差,但没有取向,这意味着没有直接面对相机物镜的罐子被识别出来.

你能帮助我改进我的特定算法,只使用OpenCV功能来解决上面提到的四个具体问题吗?

我希望有些人也会从中学到一些东西,毕竟我认为不仅要问问题的人应该学习.:)

c++ algorithm opencv image-processing

1585
推荐指数
20
解决办法
18万
查看次数

将BigDecimal舍入为*always*有两个小数位

我正在尝试将BigDecimal值向上舍入到小数点后两位.

我正在使用

BigDecimal rounded = value.round(new MathContext(2, RoundingMode.CEILING));
logger.trace("rounded {} to {}", value, rounded);
Run Code Online (Sandbox Code Playgroud)

但它不能始终如一地做我想做的事:

rounded 0.819 to 0.82
rounded 1.092 to 1.1
rounded 1.365 to 1.4 // should be 1.37
rounded 2.730 to 2.8 // should be 2.73
rounded 0.819 to 0.82
Run Code Online (Sandbox Code Playgroud)

我不关心有效数字,我只想要两位小数.我如何使用BigDecimal执行此操作?或者是否有另一个类/库更适合这个?

java math rounding bigdecimal

198
推荐指数
1
解决办法
18万
查看次数

什么是位屏蔽?

我对C编程很新,我遇到了掩码.有人可以向我解释位屏蔽的一般概念和功能吗?非常感谢例子.

c terminology bit-manipulation bitmask bitwise-operators

162
推荐指数
2
解决办法
24万
查看次数

如何优雅地忽略MATLAB函数的某些返回值?

是否有可能从函数中获取'nth'返回值而不必为n-1之前的所有返回值创建虚拟变量?

比方说,我在MATLAB中有以下功能:

function [a,b,c,d] = func()
a = 1;
b = 2;
c = 3;
d = 4;
Run Code Online (Sandbox Code Playgroud)

现在假设,我只对第三个返回值感兴趣.这可以通过创建一个虚拟变量来完成:

[dummy, dummy, variableThatIWillUse, dummy] = func;
clear dummy;
Run Code Online (Sandbox Code Playgroud)

但我认为这有点难看.我认为你可能会做以下事情之一,但你不能:

[_, _, variableThatIWillUse, _] = func;

[, , variableThatIWillUse, ] = func;

variableThatIWillUse = func(3);

variableThatIWillUse = func()(3);

有没有优雅的方法可以做到这一点?


到目前为止,最好的解决方案是简单地使用variableThatIWillUse虚拟变量作为虚拟变量.这使我不必创建一个污染工作空间的真实虚拟变量(或者我需要清除它).简而言之:解决方案是使用variableThatIWillUsefor each返回值直到有趣的值.之后的返回值可以简单地忽略:

[variableThatIWillUse, variableThatIWillUse, variableThatIWillUse] = func;
Run Code Online (Sandbox Code Playgroud)

我仍然认为这是非常难看的代码,但如果没有更好的方法,那么我想我会接受答案.

matlab function return-value

117
推荐指数
5
解决办法
5万
查看次数

如何在C中定义一个函数指针数组

我有点问题.我正在尝试动态定义一个函数指针数组calloc.但我不知道如何编写语法.非常感谢.

c c++ arrays function-pointers

47
推荐指数
3
解决办法
9万
查看次数

将字符串转换为代码

我想知道是否有任何方法可以将StringJava 转换为Java可编译代码.

我有一个比较表达式保存在数据库字段中.我想从数据库中检索它,然后在条件结构中进行评估.

有没有办法做到这一点?

java

45
推荐指数
6
解决办法
6万
查看次数

使用'ObjectId'查询MongoDB

我已经将documents插入MongoDB而没有id.我想通过搜索默认分配的MongoDBObjectId来检索它们.

这是我的尝试 -

var query_id = Query.EQ("_id", "50ed4e7d5baffd13a44d0153");
var entity = dbCollection.FindOne(query_id);
return entity.ToString();
Run Code Online (Sandbox Code Playgroud)

我得到以下错误 -

发生了'System.NullReferenceException'类型的第一次机会异常

问题是什么?

.net c# mongodb mongodb-.net-driver

29
推荐指数
2
解决办法
4万
查看次数

C#:拆分字符串而不返回空字符串

我有一个字符串:

a = "1;2;3;"
Run Code Online (Sandbox Code Playgroud)

我想split这样:

foreach (string b in a.split(';'))
Run Code Online (Sandbox Code Playgroud)

我怎样才能确保我只返回1,2,3而不是一个"空字符串"?

如果我分裂1;2;3然后我会得到我想要的.但如果我分裂1;2;3;然后我得到一个额外的'空字符串'.我已经采取了建议并做到了这一点:

string[] batchstring = batch_idTextBox.Text.Split(';', StringSplitOptions.RemoveEmptyEntries);
Run Code Online (Sandbox Code Playgroud)

但是,我收到这些错误:

错误1'string.Split(params char [])'的最佳重载方法匹配包含一些无效参数C:\ Documents and Settings\agordon\My Documents\Visual Studio 2008\Projects\lomdb\EnterData\DataEntry\DAL.cs 18 36 EnterData

错误2参数'2':无法从'System.StringSplitOptions'转换为'char'C:\ Documents and Settings\agordon\My Documents\Visual Studio 2008\Projects\lomdb\EnterData\DataEntry\DAL.cs 18 68 EnterData

c# split

27
推荐指数
3
解决办法
2万
查看次数

如何使用MongoDB的官方C#驱动程序删除'ID'中的'文档'?

有人可以告诉我,如果有更好的方法document从使用官方C#驱动程序删除MongoDB 中的一个,而不是我以下 -

var query = Query.EQ("_id", a.Id);
database.GetCollection<Animal>("Animal").Remove(query);
Run Code Online (Sandbox Code Playgroud)

这段代码有效,但对我来说似乎太过分了.例如,"保存"命令需要一个实例并对其进行更新.我想要像 - Remove(item).

备注:我正在尝试使用C#的官方驱动程序,而不是看起来过时的NoRMSamus.

.net c# mongodb mongodb-.net-driver

25
推荐指数
3
解决办法
3万
查看次数

从MongoDB'集合'获取所有'文档'

我需要检索MongoDB中我的集合中的所有文档,但我无法弄清楚如何.我已经宣布我的'收藏'像这样 -

private static IMongoCollection<Project> SpeCollection = db.GetCollection<Project>("collection_Project");
Run Code Online (Sandbox Code Playgroud)

我遵循的是在解释这个 MongoDB的教程.我根据自己的需要调整了它,比如 -

 var documents = await SpeCollection.Find(new Project()).ToListAsync();
Run Code Online (Sandbox Code Playgroud)

但是,我一直有以下错误 -

MongoDB.Driver.IMongoCollection没有'Find'的定义和扩展方法[superlong stuff]的最佳覆盖.查找包含无效的参数.

.net c# mongodb mongodb-csharp-2.0 mongodb-.net-driver

25
推荐指数
3
解决办法
5万
查看次数