我计算了3D灰度图像的直方图(一个简单的1d数组)。 现在我想计算每个点的直方图的梯度。所以这实际上意味着我必须在某些点计算一维函数的梯度。但是我没有功能。那么如何用具体的x和y值来计算呢?
为了简单起见,您可以在示例直方图上向我解释 - 例如,使用以下值(x是强度,y是此强度的频率):
x1 = 1; y1 = 3
x2 = 2; y2 = 6
x3 = 3; y3 = 8
x4 = 4; y4 = 5
x5 = 5; y5 = 9
x6 = 6; y6 = 12
x7 = 7; y7 = 5
x8 = 8; y8 = 3
x9 = 9; y9 = 5
x10 = 10; y10 = 2
我知道这也是一个数学问题,但由于我需要用c ++解决它,我可以帮助我。
感谢您的建议 马克
答案 0 :(得分:3)
我认为您可以使用图像边界检测中使用的相同方法(这是一个渐变微积分)来计算渐变。如果直方图在矢量中,则可以将梯度的近似值计算为*:
for each point in the histogram compute
gradient[x] = (hist[x+1] - hist[x])
这是一种非常简单的方法,但我不确定它是否最准确。
<强>被修改强>:
其他运营商可能会强调小差异(小梯度将更加强调)。 Roberts算法源自导数演算:
lim delta -> 0 = f(x + delta) - f(x) / delta
delta无限地趋于0(为了避免0除法),但绝不为零。在计算机的存储器中,这是不可能的,我们可以得到的最小值为1(因为1是从图像(或直方图)中的点到最小距离)。
代替
lim delta -> 0 to lim delta -> 1
我们得到了
f(x + 1) - f(x) / 1 = f(x + 1) - f(x) => vet[x+1] - vet[x]
答案 1 :(得分:2)
取一些方形纸并画上你的直方图。通过直方图的0,0点绘制垂直和水平轴。
采取直边,并在您感兴趣的每个点旋转直边,直到它符合您对该点的渐变的想法。最重要的是,你这样做,你的梯度定义是你想要的。
一旦直边处于该角度,您希望在该角度画一条线。
从您刚绘制的线上的任意2个点掉落垂线。如果您选择的2个点之间的水平距离约为直方图宽度的25%或更多,则可以更轻松地执行以下步骤。从相同的2个点绘制水平线以与直方图的垂直轴相交。
您的线条现在定义了x距离和y距离,即水平/垂直(分别)轴的长度,它们与垂线/水平线的交点标出。你想要的渐变是y距离除以x距离。
现在,将此转换为代码非常简单,除了步骤2.您必须定义用于确定直方图上任何点的渐变的标准。简单的选择包括:
a)在每个点,设置你的直边穿过该点,然后是右边的下一个;
b)在每个点,设置你的直边通过点和左边的下一个点;
c)在每个点,设置你的直边以通过左边的点和右边的点。
您可能想要研究更复杂的选择,例如通过直方图上的多个点拟合曲线(例如二次或更高阶多项式),并使用它的导数来表示渐变。
在您理解纸上的问题之前,请避免使用C ++或其他任何内容进行编码。一旦你理解了它,编码应该是微不足道的。
答案 2 :(得分:2)
这里有两种方法:
在第一种情况中尝试:
g = (y_(i+1) - y_(i-1))/2*dx
除了两端以外的所有点,或
之一g_left-end = (y_(i+1) - y_i)/dx
g_right-end = (y_i - y_(i-1))/dx
其中dx
是x点之间的间距。 (与同样正确的定义Andres suggested不同,这个定义是对称的。它是否重要取决于你的用例。)
在第二种情况中,为数据[*]拟合spline,并在样条库中询问您想要的点的衍生物。
[*]使用图书馆!除非这是一个学习项目,否则不要自己实现。我使用ROOT因为我已经在我的机器上使用它了,但它只是为了得到一个样条线而非常重的包...
最后,如果您的数据有噪音,您可以在进行斜率检测之前将其平滑。那就是你避免追逐噪音,只看大规模的斜坡。