2015-01-19 2 views
0

Я новичок в OpenCV, и я собираюсь написать следующий код, чтобы вычислить квантованную и взвешенную гистограмму изображения rgb.Opencv: как вычислить трехмерную гистограмму?

M - это карта весов. Это объект Mat с теми же размерами входного изображения. Прежде всего, я поставлю все (двойные) значения в диапазоне [1,8]. Тогда для каждой тройки значений rgb (1,1,1), (1,1,2), .... (8,8,8) я хочу суммировать значение соответствующего веса. Так что, когда я нахожу тройку (1,2,1), я знаю, что она соответствует ящику 9 (т. Е. 9-й бит). Поэтому я пытаюсь суммировать значение M (x, y) с текущим аккумулятором H, но он не работает!

NB: В моем MatLab коде я сделать это с помощью accumarray Однако, есть что-то не так, когда я делать

H.at<uchar>(idx,1) = H.at<uchar>(idx,1) + M.at<double>(Point(x, y)); 

если я бегу M.type() возвращает значение 3

Mat H = Mat::zeros(1,512,CV_8UC1); 

    for (int y = 0; y < R.rows; ++y) { 
     for (int x = 0; x < R.cols; ++x) { 

      intensity = R.at<double>(Point(x, y)); 
      p = intensity[0]; 
      r = 1 + floor(p * 7.9999); 
      cout << "R index = " << r << endl << endl; 


      intensity = G.at<double>(Point(x, y)); 
      p = intensity[0]; 
      g = 1 + floor(p * 7.9999); 
      cout << "G index = " << g << endl << endl; 


      intensity = B.at<double>(Point(x, y)); 
      p = intensity[0]; 
      b = 1 + floor(p * 7.9999); 
      cout << "B index = " << b << endl << endl; 

      C.at<cv::Vec3b>(x, y)[0] = r; 
      C.at<cv::Vec3b>(x, y)[1] = g; 
      C.at<cv::Vec3b>(x, y)[2] = b; 

      //idx = 1 +((r-1)*64 + (g-1)*8 + (b-1)*1) 
      //Here i don't sum 1 because in C the indices starts from 0 
      idx = (r - 1) * 64 + (g - 1) * 8 + (b - 1) * 1; 

      H.at<uchar>(idx,1) = H.at<uchar>(idx,1) + M.at<double>(Point(x, y)); 
      cout << endl << idx; 

     } 
    } 

Редактировать Хорошо, позвольте мне сказать, некоторые изменения после ваших предложений, эта инициализация из С и Н

cv::Mat C(doubleRed.rows, doubleRed.cols, CV_8UC3); 
Mat H = Mat::zeros(1, 512, CV_16UC1); 

Я решил произошла ошибка в

C.at<cv::Vec3b>(x, y)[0] = r; 
C.at<cv::Vec3b>(x, y)[1] = g; 
C.at<cv::Vec3b>(x, y)[2] = b; 

переворачивая х и у него wokrs ... но я хочу понять, почему я должен это сделать .... Однако код по-прежнему падает, когда я пытаюсь использовать функцию в() Н:

H.at<uchar>(idx, 1) = H.at<uchar>(idx, 1) + M.at<double>(Point(x, y)); 

ответ

2

Некоторые вещи, которые я заметил, что может помочь:

Вы объявляете H следующим образом:

Mat H = Mat::zeros(1,512,CV_8UC1); 

Затем к нему доступ, как так:

H.at<uchar>(idx,1) = ... 

Так вы создаете матрицу с 1 row и 512 columns, а затем доступ к row idx и column 1. Вы должны поменять индексы в вашем at:

H.at<uchar>(1,idx) = ... 

Редактировать: Причина, по которой показатели кажутся назад что at() заказывает аргументы, как:

H.at<uchar>(row,column) ... or 
H.at<uchar>(y, x) ... 

Это противоположность Point, который заказывает такие аргументы, как:

Point2f P(column, row); or 
Point2f P(x, y); 

http://docs.opencv.org/modules/core/doc/basic_structures.html#mat-at

Кроме того, я не знаю, сколько предметов вы планируете иметь в каждом бункере, но если оно меньше 256, CV_8UC1 слишком мало.

Наконец, изображения в OpenCV, как правило, в BGR порядке, поэтому ваш

 C.at<cv::Vec3b>(x, y)[0] = r; 
     C.at<cv::Vec3b>(x, y)[1] = g; 
     C.at<cv::Vec3b>(x, y)[2] = b; 

, вероятно, в обратном направлении. Для скорости вы также можете вызвать at только один раз и сохранить значение в Vec3b перед доступом к отдельным элементам.

+0

Спасибо за ответ. Я просто хотел бы суммировать значения в M, которые имеют одинаковую комбинацию r, g, b. На самом деле, я планировал использовать C как карту индексов, а не как изображение, поэтому порядок r g и b в этом случае не имеет значения. Какой тип данных вы предлагаете для H? почему не простой int H [512]? – user2614596

+0

@ user2614596 Тип, который вы используете, зависит от того, насколько велика величина, которую вы будете хранить в 'H'. В настоящее время вы используете 'CV_8UC1', который представляет собой 8-разрядное целое без знака, которое будет хранить только значения из' [0..255] '. Если вы ожидаете значения за пределами этого диапазона, вы должны использовать 'CV_16UC1' или' CV_32SC1' (типов 'CV_32U' не существует). – beaker

+0

Это все еще не работает ... Я отредактировал вопрос, чтобы добавить подробности, но доступ к H не ясен. Значения M являются «большими» целыми без знака. – user2614596

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