2015-05-26 5 views
1

Я пытаюсь реализовать приложение, которое использует изображения для поиска похожих изображений в большой базе данных изображений. Я разрабатываю дескриптор изображения для использования для этого поиска, и я хотел бы объединить информацию о цвете с некоторой информацией о градиенте. Я видел структурные тензоры, используемые в этой области, чтобы найти основное направление градиента в изображениях или суб-изображениях.Как вычислить тензор структуры изображения с помощью OpenCV

Я хотел бы сделать снимок, разделив его на сетку суб-изображений, например, сетку 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); 

Вычислительный дх^2, ау^2 и DXY не должно быть проблемой, но я не знаю, как я могу вычислить тензор структуры матрицы и использовать тензор матрицы найти основное направление градиента для изображения или суб-изображение. Как я могу реализовать это с помощью OpenCV?

EDIT Хорошо, это то, что я сделал.

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, который я нахожу странным. Я ожидал получить угол по изменению цвета (90-е годы).

После тестирования я не уверен, что моя реализация верна, поэтому любые отзывы или комментарии по этому поводу приветствуются.

+0

Вы видели [это] (http://answers.opencv.org/question/33206/calculates-the-angle-of-orientation-of-the-image-with-the-gradient-method/)? – sop

+0

Я это видел, но это не подходит для моего приложения. Я хотел бы избежать хранения всей матрицы градиентных направлений. Если я работаю с изображением 32x32, мне нужно будет сохранить 1024 значения. Я надеялся, что использование тензора структуры даст мне только один вектор основного направления, который я мог бы использовать для сравнения изображения, чтобы найти изображение с аналогичным направлением градиента. – krunarsson

+0

Но если вы храните только среднее значение, это неправильно? Таким образом, вы будете иметь основную ориентацию. – sop

ответ

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); 

P.S. О, кстати, нет необходимости гауссовской размытости снова и снова. Просто используйте большее ядро ​​и размывайте один раз. DS

 Смежные вопросы

  • Нет связанных вопросов^_^