【问题标题】:How to Compute the Structure Tensor of an Image using OpenCV如何使用 OpenCV 计算图像的结构张量
【发布时间】:2015-05-26 12:07:32
【问题描述】:

我正在尝试实现一个应用程序,该应用程序使用图像在大型图像数据库中搜索相似图像。我正在开发一个用于此搜索的图像描述符,并且我想将颜色信息与一些渐变信息结合起来。我已经看到在这个领域中使用结构张量来查找图像或子图像中的主要梯度方向。

我想拍摄一张图像,将其划分为子图像的网格,例如 4x4 网格(共 16 个子图像),然后找到每个单元格的前导梯度方向。为了找到领先的梯度方向,我想看看计算每个单元的结构张量是否可以很好地表示图像梯度并改善图像匹配。这是个好主意还是坏主意?想法是得到一个类似于本文3.2节的想法的特征向量http://cybertron.cg.tu-berlin.de/eitz/pdf/2009_sbim.pdf

将图像划分为子图像(细胞)是微不足道的,使用 opencv 我可以使用 Sobel 函数计算偏导数。

Mat dx, dy; 
Sobel(im, dx, CV_32F, 1, 0, 3, 1, 0, BORDER_DEFAULT);
Sobel(im, dy, CV_32F, 0, 1, 3, 1, 0, BORDER_DEFAULT); 

计算 dx^2、dy^2 和 dxy 应该不是问题,但我不确定如何计算结构张量矩阵并使用张量矩阵找到图像或子图像的主梯度方向.如何使用 OpenCV 实现这一点?

编辑 好的,这就是我所做的。

    Mat _im; // Image to compute main gradient direction for. 
    cvtColor(im, _im, CV_BGR2GRAY);
    GaussianBlur(_im, _im, Size(3, 3), 0, 0, BORDER_DEFAULT); //Blur the image to remove unnecessary details. 
    GaussianBlur(_im, _im, Size(5, 5), 0, 0, BORDER_DEFAULT);
    GaussianBlur(_im, _im, Size(7, 7), 0, 0, BORDER_DEFAULT);

    // Calculate image derivatives 
    Mat dx2, dy2, dxy; 
    Sobel(_im, dx2, CV_32F, 2, 0, 3, 1, 0, BORDER_DEFAULT); 
    Sobel(_im, dy2, CV_32F, 0, 2, 3, 1, 0, BORDER_DEFAULT);
    Sobel(_im, dxy, CV_32F, 1, 1, 3, 1, 0, BORDER_DEFAULT);

    Mat t(2, 2, CV_32F); // tensor matrix

    // Insert values to the tensor matrix.
    t.at<float>(0, 0) = sum(dx2)[0];
    t.at<float>(0, 1) = sum(dxy)[0];
    t.at<float>(1, 0) = sum(dxy)[0];
    t.at<float>(1, 1) = sum(dy2)[0];

    // eigen decomposition to get the main gradient direction. 
    Mat eigVal, eigVec;
    eigen(t, eigVal, eigVec);

    // This should compute the angle of the gradient direction based on the first eigenvector. 
    float* eVec1 = eigVec.ptr<float>(0);
    float* eVec2 = eigVec.ptr<float>(1);
    cout << fastAtan2(eVec1[0], eVec1[1]) << endl;
    cout << fastAtan2(eVec2[0], eVec2[1]) << endl;

这种方法正确吗?


使用此图像,应用程序输出 44.9905, 135.01。 这给出了 0、90。


当我使用真实图像的一部分时,我得到 342.743、72.7425,我觉得这很奇怪。我希望沿着颜色变化获得一个角度(90ish)。

经过测试,我不确定我的实现是否正确,因此欢迎对此提供任何反馈或 cmets。

【问题讨论】:

  • 你见过this吗?
  • 我见过这个,但这不适合我的应用。我想避免存储整个梯度方向矩阵。如果我使用 32x32 图像,我需要存储 1024 个值。我希望使用结构张量只会给我一个主方向的向量,然后我可以用它来比较图像以找到具有相似梯度方向的图像。
  • 但是如果你只存储值的平均值,是不是错了?像这样,您将有一个主要方向。

标签: c++ opencv image-processing descriptor


【解决方案1】:

我相信您的问题是您正在计算二阶导数,而不是对一阶导数进行平方。它应该是这样的:

// Calculate image derivatives 
Mat dx, dy; 
Mat dx2, dy2, dxy;
Sobel(_im, dx, CV_32F, 1, 0); 
Sobel(_im, dy, CV_32F, 0, 1);
multiply(dx, dx, dx2);
multiply(dy, dy, dy2);
multiply(dx, dy, dxy);

附: 哦,顺便说一句,没有必要一遍又一遍地做高斯模糊。只需使用更大的内核并模糊一次。 D.S.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-20
    • 2016-05-31
    • 1970-01-01
    • 2022-07-01
    • 2021-08-12
    • 2014-06-01
    • 1970-01-01
    相关资源
    最近更新 更多