梯度方向计算
我正在计算机视觉课程中完成我的任务。子任务之一是基于图像亮度的梯度方向计算。我制作了一个明亮[宽度][高度]矩阵,其中包含图像每个像素的亮度值。我有两个这样的功能:
double Image::grad_x(int x,int y){
if(x==width-1 || x==0) return bright[x][y];
return bright[x+1][y]-bright[x-1][y];
}
double Image::grad_y(int x,int y){
if(y==height-1 || y==0) return bright[x][y];
return bright[x][y+1]-bright[x][y-1];
}
编辑:边界检查已修复
我正在使用简单导数,而不使用索贝尔运算符,因为简单导数足以满足我的需求。
问题是,我是否正确地进行了这个梯度计算,以及我到底与边界像素有什么关系(现在函数返回像素本身的值,我不确定它是否准确)?顺便问一下,计算图像的梯度有什么用处吗?我想确保我的程序运行良好。
I'm working on my task in computer vision course. One of sub-tasks is gradient direction computation based on image brightness. I've made a matrix bright[width][height] containing brightness values for every pixel of the image. And i have two such functions:
double Image::grad_x(int x,int y){
if(x==width-1 || x==0) return bright[x][y];
return bright[x+1][y]-bright[x-1][y];
}
double Image::grad_y(int x,int y){
if(y==height-1 || y==0) return bright[x][y];
return bright[x][y+1]-bright[x][y-1];
}
EDIT: border check fixed
I'm working with simple derivative, without using Sobel operator 'cause simple derivative is sufficient for my needs.
The question is, am i doing this gradient computation right and what exactly do i have to do with border pixels(right now function returns value of the pixel itself, im not sure it's accurate)? And, by the way, is there any utility for computation of gradients of the image? I want to be sure my program is performing well.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
你的计算是正确的。这是您正在使用的一种简单的渐变方法,但如果这适合您的使用,那就没有问题。
极端情况是一个问题,因为您没有足够的数据来以与其他像素相同的方式计算梯度。处理这些问题的一种方法是简单地不计算极端情况并使用稍小的图像。
如果这不是一个选项,您也可以推断丢失的数据。如果您假设梯度变化平滑,则其工作原理如下:
在 x 梯度计算中,您可能计算了像素 1 的导数 A 和像素 2 的导数 B。如果您想推断像素 0 的值(极端情况)可以使用值a-(ba)。
数值示例:
Your computation is correct. It is a simple gradient method you're using, but if that's fine for your use there is nothing wrong with that.
The corner cases are a problem because you don't have enough data to calculate a gradient in the same way as the other pixels. One way to deal with them is to simply not calculate the corner cases and live with a slightly smaller image.
If this is not an option you can also extrapolate the missing data. If you assume that the gradient changes smoothly it works like this:
In your x-gradient calculations you may have calculated the derivate A for pixel 1 and B for pixel 2. If you want to extrapolate a value for pixel 0 (the corner case) the value a-(b-a) could be used.
A numerical example:
因此,一方面您希望保持简单,另一方面您希望程序性能良好。呵呵。
我实际上正在做类似的事情,不过,我不太关心边界。我喜欢将系数基于三次 B 样条曲线。如果将离散 2D 信号与 2D 三次 B 样条曲线进行卷积,您将得到一个非常平滑且两次连续可微的函数。可以计算该函数在任意点的精确强度和导数。由于三次 B 样条曲线不是插值器,因此与原始结果相比,结果会稍微平滑。但这对于许多应用程序来说不是问题。事实上,它在许多情况下往往会改善情况(在一定程度上抑制噪音)。如果您不想要这种平滑效果,您可以绕过它(请参阅下面的参考资料)。
在一维中,使用三次 B 样条作为重构滤波器进行重构,然后再次对信号进行采样,相当于将信号与该信号进行卷积。
其精确导数为:
并且精确 > 二阶导数为:
这些系数由三次 B 样条曲线及其导数得出。在 2D 中,您可以任意组合它。 1 个滤波器用于 x 方向,1 个滤波器用于 y 方向。示例:
这样做的好处是,尽管滤波结果并不完全对应于原始信号,而只是稍微平滑的版本,但它们仍然彼此一致。您可以通过使用描述的简单预处理技巧来解决平滑效果 此处。但根据您实际想要做什么,这种预处理可能不合适。
我用它来计算任意(子像素)点的二次泰勒近似,以找到鞍点和局部极值等内容。
如果您关心边界,您需要以某种方式选择适合您需要的外推法。我通常只是重复最后一个像素的像素值。它非常适合我的应用程序*。
So, on one hand you want to keep it simple on the other hand you want your program to perform well. Huh.
I'm actually doing something similar, though, I don't care much about the border. I like to base the coefficients off of cubic B-Splines. If you convolve your discrete 2D signal with a 2D cubic B-Spline, you'll get a very smooth and twice continuously differentiable function. It's possible to compute the exact intensities and derivatives of this function at arbitrary points. Since the cubic B-Spline is not an interpolator the result will be a bit smoothed compared to the original. But that's not a problem for many applications. In fact, it tends to improve things (suppresing noise to some extent) in many situations. If you don't want this smoothing effect, you can get around it (see my reference below).
In one dimension, reconstruction using the cubic B-Spline as reconstruction filter followed by sampling the signal again is equivalent to convolving the signal with
The exact derivative of this is:
And the exact second derivative is:
These coefficients follow from the cubic B-Spline curve and its derivatives. In 2D you can combine this arbitratily. One filter for the x direction and one filter for the y direction. Examples:
The nice thing about this is, even though the filtered results don't correspond exactly to the original signal but only a slightly smoothed version, they are nontheless consistent with each other. You can get around the smoothing effect by using a simple preprocessing trick that is described here. You'll also But depending on what you actually want to do, this preprocessing might be inappropriate.
I use this to compute quadratic Taylor approximations at arbitrary (sub-pixel) points to find things like saddle points and local extremums.
If you care about the border you need to somehow choose an extrapolation that fits your needs. I typically just repeat the pixel values of the last pixels. It works well for my applications*.
如何处理边界完全取决于应用程序。镜像、外推、添加零,这取决于您的需要。
现在你把亮度值作为边界,我不会这样做,它没有任何意义。就像您的图像在所有边界和镜像上有更多像素一样,为您的导数计算推断或归零它们的值。
为什么不只采用 Sobel 内核呢?它速度快而且不需要更多的编码工作?
编辑:您不检查 x 方向的边界。 grad_x(0, 0) 将导致运行时异常。
How you deal with borders totally depends on the application. Mirroring, extrapolation, adding zeroes, depending on your needs it will do.
Now you take as border the brightness value, I would not do that, it has no meaning. Just act like your image has more pixels on all borders and mirror, extrapolate or zero their value for your derivative calculation.
Why not taking just a Sobel kernel? It is fast and not more coding effort?
Edit: you do not check the borders in x-direction. grad_x(0, 0) will result in a runtime exception.
实用程序:
OpenCV 以及您使用的卷积核 (
[ 1 0 -1]
)。边框像素:
取决于应用程序。这里有一些填充图像的好方法。
Utility:
OpenCV with the convolution kernel you used (
[1 0 -1]
).Border pixels:
Depends on the application. Here are some nice ways to pad your image.