【问题标题】:What does the gradient from Sobel mean?Sobel 的梯度是什么意思?
【发布时间】:2014-04-08 18:21:26
【问题描述】:

我有每个像素的 Sobel 算子的梯度。在我的情况下是 320x480。但是我怎样才能将它们与方向联系起来呢?例如,我打算为指纹绘制一个方向图。那么,我该如何开始呢?

是通过将梯度分成块(例如 16x24)然后将梯度相加并用 384 来获得平均梯度吗?然后从那里使用平均梯度从块的中心画一条线?

如果我错了,请纠正我。谢谢。

这是我用来寻找渐变的代码

cv::Mat original_Mat=cv::imread("original.bmp", 1);

cv::Mat grad = cv::Mat::zeros(original_Mat.size(), CV_64F);

cv::Mat grad_x = cv::Mat::zeros(original_Mat.size(), CV_64F); 
cv::Mat grad_y = cv::Mat::zeros(original_Mat.size(), CV_64F);

/// Gradient X
cv::Sobel(original_Mat, grad_x, CV_16S, 1, 0, 3);

/// Gradient Y
cv::Sobel(original_Mat, grad_y, CV_16S, 0, 1, 3);

short* pixelX = grad_x.ptr<short>(0);
short* pixelY = grad_y.ptr<short>(0);

int count = 0;
int min = 999999;
int max = -1;
int a=0,b=0;

for(int i = 0; i < grad_x.rows * grad_x.cols; i++) 
{
    double directionRAD = atan2(pixelY[i], pixelX[i]);
    int directionDEG = (int)(180 + directionRAD / CV_PI * 180);

    //printf("%d ",directionDEG);
    if(directionDEG < min){min = directionDEG;}
    if(directionDEG > max){max = directionDEG;}


    if(directionDEG < 0 || directionDEG > 360)
    {
        cout<<"Weird gradient direction given in method: getGradients.";
    }

}

【问题讨论】:

    标签: c++ opencv orientation gradient fingerprint


    【解决方案1】:

    有几种方法可以可视化方向图:

    正如您所建议的,您可以按块绘制它,但是您必须小心“平均”方向。例如,如果对 0° 和 180° 方向进行平均会发生什么?

    更常见的是,方向只是简单地映射到一个灰度值。这将可视化每个像素的梯度。例如:

    int v = (int)(128+directionRAD / CV_PI * 128);
    

    (免责声明:不是 100% 确定 128,其中一个实际上可能必须是 127...

    或者您可以将 x 和 y 梯度幅度分别映射到 rg 分量,理想情况是在将梯度向量标准化为长度 1 之后。假设 normX 是 x 方向上的标准化梯度-1 和 1 之间的值:

    int red = (int)((normX + 1)*127.5);
    int green= (int)((normY + 1)*127.5);
    

    【讨论】:

    • 谢谢,但我还是很困惑。 v是干什么用的?我得到的值范围是 0-256。灰度?我如何使用这些信息来画线?
    • v 是一个灰度值。如果您通过像这样计算每个像素值来生成新图像,您将获得一个图像,其中每个像素代表该像素处的梯度方向。这只是画线的一种替代方法,而且(根据我的经验)更常用。
    • @andreas,我使用了 imwrite 并得到了图像,但它看起来像 i.imgur.com/Cssqmux.png 这与原始 i.imgur.com/5PRemmw.png 完全不同,我正在尝试以这种方式 i.imgur.com/SwQfkHR.png。有什么办法吗?
    • 这看起来像是您的代码有问题。你看过answers.opencv.org/question/9493/…吗?
    • 你知道我的代码有什么问题吗?是的,我以前见过。从您的链接中,我现在可以平均 5x5 块方向值,然后为每个块画线吗?那会得到方向图吗?
    【解决方案2】:

    平均取决于 Sobel 内核大小。

    使用 CV_32FC 或 CV_64FC 代替 CV_16S 会更好。

    您还可以使用 cv::phase 方法加速您的代码。

    在这里查看我的答案:Sobel operator for gradient angle

    【讨论】:

    • 谢谢。你的方法得到的角度和我的方法是一样的吧?你能告诉我如何从这里开始绘制地图吗?
    • 我觉得HOG visuzlizer应该是最合适的:(看这里)juergenwiki.de/work/wiki/…
    • 您还可以绘制除最大 bin 或平均(N 个最强) bin 之外的所有 bin,并绘制每个块的结果。
    猜你喜欢
    • 1970-01-01
    • 2019-07-17
    • 2018-08-27
    • 2023-04-09
    • 2014-04-18
    • 1970-01-01
    • 2020-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多