计算 c++ 中直方图的梯度

发布于 2024-08-16 10:09:58 字数 486 浏览 4 评论 0 原文

我计算了 3D 灰度图像的直方图(一个简单的一维数组)。 现在我想计算这个直方图在每个点的梯度。所以这实际上意味着我必须计算一维函数在某些点的梯度。但是我没有功能。那么如何用具体的 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++ 解决它,所以我想你可以在这里帮助我。

谢谢你的建议 马克

I calculated the histogram(a simple 1d array) for an 3D grayscale Image.
Now I would like to calculate the gradient for the this histogram at each point. So this would actually mean I have to calculate the gradient for a 1D function at certain points. However I do not have a function. So how can I calculate it with concrete x and y values?

For the sake of simplicity could you probably explain this to me on an example histogram - for example with the following values (x is the intensity, and y the frequency of this intensity):

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

I know that this is also a math problem, but since I need to solve it in c++ I though you could help me here.

Thank you for your advice
Marc

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

明明#如月 2024-08-23 10:09:58

我认为您可以使用图像边界检测中使用的相同方法(即梯度演算)来计算梯度。如果您的直方图位于向量中,您可以计算梯度的近似值*:

for each point in the histogram compute 
     gradient[x] = (hist[x+1] - hist[x])

这是一种非常简单的方法,但我不确定是否是最准确的。

  • 近似,因为您正在使用离散数据而不是连续的

编辑

其他运算符可能会强调微小的差异(小梯度将变得更加强调)。罗伯茨算法源自导数演算:

lim delta -> 0 = f(x + delta) - f(x) / delta

delta 无限趋向于 0(以避免 0 除法),但永远不会为零。在计算机内存中这是不可能的,我们能得到的最小 delta 是 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]

I think you can calculate your gradient using the same approach used in image border detection (which is a gradient calculus). If your histogram is in a vector you can calculate an approximation of the gradient as*:

for each point in the histogram compute 
     gradient[x] = (hist[x+1] - hist[x])

This is a very simple way to do it, but I'm not sure if is the most accurate.

  • approximation because you are working with discrete data instead of continuous

Edited:

Other operators will may emphasize small differences (small gradients will became more emphasized). Roberts algorithm derives from the derivative calculus:

lim delta -> 0 = f(x + delta) - f(x) / delta

delta tends infinitely to 0 (in order to avoid 0 division) but is never zero. As in computer's memory this is impossible, the smallest we can get of delta is 1 (because 1 is the smallest distance from to points in an image (or histogram)).

Substituting

lim delta -> 0 to lim delta -> 1

we get

f(x + 1) - f(x) / 1 = f(x + 1) - f(x) => vet[x+1] - vet[x]
删除会话 2024-08-23 10:09:58

这里有两种通常的方法:

  1. 导数的离散近似
  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 点之间的间距。 (与同样正确的定义不同安德烈斯建议 ,这是否重要取决于您的用例。)

第二种情况中,拟合一个样条到您的数据[*],并向样条库询问您想要的点处的导数。

[*] 使用图书馆!除非这是一个学习项目,否则请勿自行实施。我会使用 ROOT 因为我的机器上已经有了它,但它是一个相当重的软件包,只是为了得到样条曲线...


最后,如果您的数据有噪声,您可能需要在进行斜率检测之前对其进行平滑处理。那就是你避免追逐噪音,只关注大范围的斜坡。

Two generally approaches here:

  1. a discrete approximation to the derivative
  2. take the real derivative of a fitted function

In the first case try:

g = (y_(i+1) - y_(i-1))/2*dx

at all the points except the ends, or one of

g_left-end  = (y_(i+1) - y_i)/dx
g_right-end = (y_i - y_(i-1))/dx

where dx is the spacing between x points. (Unlike the equally correct definition Andres suggested, this one is symmetric. Whether it matters or not depends on you use case.)

In the second case, fit a spline to your data[*], and ask the spline library the derivative at the point you want.

[*] Use a library! Do not implement this yourself unless this is a learning project. I'd use ROOT because I already have it on my machine, but it is a pretty heavy package just to get a spline...


Finally, if you data is noisy, you ma want to smooth it before doing slope detection. That was you avoid chasing the noise, and only look at large scale slopes.

望笑 2024-08-23 10:09:58
  1. 拿一些方格纸,在上面画出你的直方图。还通过直方图的 0,0 点绘制垂直轴和水平轴。

  2. 拿一条直尺,在您感兴趣的每个点处旋转直尺,直到它符合您对该点的梯度的想法。最重要的是你这样做,你对渐变的定义就是你想要的。

  3. 一旦直边处于您想要的角度,就以该角度画一条线。

    一旦

  4. 从刚刚绘制的线上的任意 2 点垂下垂线。如果您选择的 2 个点之间的水平距离约为直方图宽度的 25% 或更多,则执行以下步骤会更容易。从相同的 2 点绘制水平线以与直方图的垂直轴相交。

  5. 您的线现在定义了 x 距离和 y 距离,即水平/垂直(分别)轴的长度,由它们与垂直线/水平线的交点标记出来。您想要的渐变是 y 距离除以 x 距离。

现在,除了步骤 2 之外,将其转换为代码非常简单。您必须定义确定直方图上任意点的梯度的标准。简单的选择包括:

a) 在每个点,放下直尺以穿过该点及其右侧的下一个点;

b) 在每个点处,放下直尺以穿过该点及其左侧的下一个;

c) 在每个点处,放下直尺以穿过左侧的点和右侧的点。

您可能想要研究更复杂的选择,例如通过直方图上的多个点拟合曲线(例如二次或高阶多项式)并使用其导数来表示梯度。

在您理解纸上的问题之前,请避免使用 C++ 或其他任何语言进行编码。一旦你理解了它,编码就应该是微不足道的。

  1. Take some squared paper and draw on it your histogram. Draw also vertical and horizontal axes through the 0,0 point of your histogram.

  2. Take a straight edge and, at each point you are interested in, rotate the straight edge until it accords with your idea of what the gradient at that point is. It is most important that you do this, your definition of gradient is the one you want.

  3. Once the straight edge is at the angle you desire draw a line at that angle.

  4. Drop perpendiculars from any 2 points on the line you just drew. It will be easier to take the following step if the horizontal distance between the 2 points you choose is about 25% or more of the width of your histogram. From the same 2 points draw horizontal lines to intersect the vertical axis of your histogram.

  5. Your lines now define an x-distance and a y-distance, ie the length of the horizontal/ vertical (respectively) axes marked out by their intersections with the perpendiculars/horizontal lines. The gradient you want is the y-distance divided by the x-distance.

Now, to translate this into code is very straightforward, apart from step 2. You have to define what the criteria are for determining what the gradient at any point on the histogram is. Simple choices include:

a) at each point, set down your straight edge to pass through the point and the next one to its right;

b) at each point, set down your straight edge to pass through the point and the next one to its left;

c) at each point, set down your straight edge to pass through the point to the left and the point to the right.

You may want to investigate more complex choices such as fitting a curve (such as a quadratic or higher-order polynomial) through a number of points on your histogram and using the derivative of that to represent the gradient.

Until you understand the question on paper avoid coding in C++ or anything else. Once you do understand it, coding should be trivial.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文