梯度矢量的直方图分级
我正在研究一个项目,该项目有一个小组件,要求比较图像渐变上的分布。 假设我已经使用Sobel滤波器在x和y方向上计算了图像梯度,并且为每个像素提供了一个2维向量。 显然,规模和方向是相当无足轻重的,如下所示:
然而,我不清楚的是如何将这两个组件分成二维直方图以获得任意数量的垃圾箱。
我曾考虑过这些方面的内容(用浏览器写的):
//Assuming normalised magnitudes.
//Histogram dimensions are bins * bins.
int getHistIdx(float mag, float dir, int bins) {
const int magInt = reinterpret_cast<int>(mag);
const int dirInt = reinterpret_cast<int>(dir);
const int magMod = reinterpret_cast<int>(static_cast<float>(1.0));
const int dirMod = reinterpret_cast<int>(static_cast<float>(TWO_PI));
const int idxMag = (magInt % magMod) & bins
const int idxDir = (dirInt % dirMod) & bins;
return idxMag * bins + idxDir;
}
但是,我怀疑mod操作会引入很多不正确的重叠,即将完全不同的渐变放入同一个bin。
任何有关这个问题的见解将非常感激。
我想避免使用任何现成的库,因为我希望尽可能将此项目保持为依赖关系。 另外我打算在CUDA中实现这一点。
这更像是一个什么是直方图问题? 而不是您的一个标签。 两件事情:
接下来,你说你想要一个“二维直方图”,但返回一个单一的数字。 二维直方图,以及在您的上下文中有意义的是三维图 - 平面是theta / R,2索引,而三维轴是“计数”。
所以第一个建议,返回
return Pair<int,int>(idxMag,idxDir);
然后您可以制作2D直方图或2个2D直方图。
关于“箱数”
这与用例有关。 你需要定义你想要的箱数(对于θ和R可能是不同的)。 也许只是一些不变的10箱? 也许它应该取决于向量的数量? 在任何情况下,您都需要一个函数来接收矢量的数量或矢量的总数,并返回每个轴的箱数。 这可能是一个常量(10箱)最初,你可以玩它。 一旦你决定垃圾桶的数量:
确定垃圾箱
0<theta<2 pi
的有界情况,这很容易。 假设平均分配,将间隔均等地分为箱的数量。 你的调制实际上处理得很好 - 如果你实际上已经调制了2 * pi,那你就没有。 尽管如此,你仍然需要确定边界。 R
来说,这是棘手的,因为这是无限的。 这里有两种选择,但都依赖于相同的策略 - 选择一个最大的垃圾箱。 可以任意(说R=10
),所以比这更长的任何向量都放在“长于最大”的bin中。 其余部分是平分的(例如,虽然你可以选择其他发行版)。 另一种选择是用最长的矢量来确定最大箱的边缘。 获取索引
一旦你有箱子,你需要搜索箱子中当前矢量的大小/方向。 如果bin是代表bin的最小/最大值(也可能是索引)的对,比如在一个链表中,那么它就是类似的东西(例如mag):
bin = histogram.first;
while ( mag > bin.min ) bin = bin.next;
magIdx = bin.index;
如果垃圾箱不包含索引,则可以使用计数器并在此期间增加它。 此外,对于最终的箱子的幅度应该保持“无限”或一些大数目作为限制。 请注意,这与调制无关,尽管这对您的方向会起作用 - 正如您编码的那样。 我不明白这是对规范有意义的。
尽管如此,你必须考虑一下你想要的东西。 无论如何,这里的所有“对象”都足够小,可以自己编写,甚至可以使用小数组。
我认为你应该把你的垃圾箱放在一个方形阵列中,然后独立地通过vx和vy装箱。
如果您的渐变是合理的,即使您只需要先扫描数据以累积x和y中的最小值和最大值,然后均匀分割渐变。
如果梯度分布非常不均匀,则可能需要先排序(例如)vx,然后安排每个分箱之间的边界完全平均分配值。
一个中间解决方案可能是获得最小和最大值,忽略(例如)10%的最极端值。
链接地址: http://www.djcxy.com/p/64037.html