Как сгладить гистограмму цвета в С++?

Привет, я написал следующие строки кода на python:

# convert the image to HSV color-space
image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

# compute the color histogram
hist  = cv2.calcHist([image], [0, 1, 2], None, [bins, bins, bins], [5, 240, 5, 240, 5, 240])

# normalize the histogram
cv2.normalize(hist, hist)

# return the histogram
return hist.flatten()

Сейчас пытаюсь переписать на С++. Я нашел отличный пример по адресу http://www.swarthmore.edu/NatSci/mzucker1/opencv-2.4.10-docs/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.html

Проблема, с которой я сталкиваюсь сейчас, заключается в том, чтобы сгладить историю в С++, например, в коде Python. Это форма вывода сглаживания истории в python (512). Любые идеи о том, как получить те же результаты в С++?

(Редактировать) код С++ до этого момента.

Размер Размер (500 500); image = imread("C:\johan.jpg",IMREAD_COLOR);

 resize(image,image,size);//resize image

 cvtColor(image, image, CV_BGR2HSV);
// Separate the image in 3 places ( H, S and V )
 vector<Mat> bgr_planes;
 split(image, bgr_planes );

 vector<Mat> hist_flat;

 // Establish the number of bins
 int histSize = 256;

 // Set the ranges ( for H,S,V) )
 float range[] = {5, 240} ;
 const float* histRange = { range };

 bool uniform = true; bool accumulate = false;

 Mat b_hist, g_hist, r_hist;

 cout << " Working fine Johan...";

 // Compute the histograms:
 calcHist( &bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate );
 calcHist( &bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate );
 calcHist( &bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate );
 //calcHist( &image,3, 0, Mat(), hist_flat, 1, &histSize, &histRange, uniform, accumulate );



 // Draw the histograms for B, G and R
 int hist_w = 512; int hist_h = 400;
 int bin_w = cvRound( (double) hist_w/histSize );



 Mat histImage(hist_h,hist_w, CV_8UC3, Scalar(0,0,0));

 // Normalize the result to [ 0, histImage.rows ]
 normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
 normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
 normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );



 // Draw for each channel
 for( int i = 1; i < histSize; i++ )
 {
     line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at<float>(i-1)) ) ,
                      Point( bin_w*(i), hist_h - cvRound(b_hist.at<float>(i)) ),
                      Scalar( 255, 0, 0), 2, 8, 0  );
     line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ) ,
                      Point( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ),
                      Scalar( 0, 255, 0), 2, 8, 0  );
     line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) ) ,
                      Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ),
                      Scalar( 0, 0, 255), 2, 8, 0  );
 }

 // Display

 imshow("calcHist Demo", histImage );
 imshow("The image resized",image);

person Johan Fick    schedule 28.08.2018    source источник
comment
Строго говоря, в С++ нет гистограмм, если вы не используете какую-либо библиотеку, обеспечивающую такую ​​​​функциональность. Однако std::map<T,unsigned> уже предоставляет все необходимое для гистограммы. При этом Stackoverflow не является службой кодирования, если вы хотите получить помощь, вам нужно показать, что вы пробовали, и задать конкретный вопрос.   -  person 463035818_is_not_a_number    schedule 28.08.2018
comment
Привет, спасибо за комментарий. В настоящее время я использую opencv для обеспечения возможности создания гистограммы данного изображения. Вот код С++, который я написал до этого момента (добавлен к вопросу). Чтобы быть более конкретным, как я могу сгладить гистограмму, сгенерированную для данного изображения, с помощью opencv 3.1.0 и С++. В коде, который я написал, я разбиваю изображение на части HSV, а затем определяю гистограммы и рисую их для целей визуализации.   -  person Johan Fick    schedule 28.08.2018


Ответы (2)


Просто чтобы добавить еще один ответ на этот вопрос. Поскольку вы используете OpenCV cv::Mat в качестве держателя гистограммы, одним из способов его выравнивания является использование изменения формы, например:

// create mat a with 512x512 size and float type
cv::Mat a(512,512,CV_32F);
// resize it to have only 1 row
a = a.reshape(0,1);

Эта функция O(1) не копирует элементы, а просто изменяет заголовок cv::Mat, чтобы он имел правильный размер.

После этого у вас будет 1 строка cv::mat с 262144 столбцами.

person api55    schedule 29.08.2018

В основном вы хотите сгладить 2D-массив ( hist = cv2.calcHist([image], [0, 1, 2], None, [bins, bins, bins], [5, 240, 5, 240, 5, 240]) - это 2D-массив 235x3 )

Самый простой код для этого находится в функции в C++, аналогичной numpy flatten

Основной алгоритм (cf http://www.ce.jhu.edu/dalrymple/classes/602/Class12.pdf )

for (q = 0; q < n; q++)
{
    for (t = 0; t < m; t++)
    {
        b[q * n + t] = a[q][t];  <-------
    }
}

источник: 2D-массив C++ в 1D-массив

(для трехмерного массива см. Как сгладить или индексировать массив в одномерном массиве? )

person ralf htp    schedule 28.08.2018
comment
Привет большое спасибо! Думаю, это решит мою проблему. - person Johan Fick; 28.08.2018