2015-11-06 2 views
2

Я хочу рассчитать среднее и стандартное отклонения для гистограммы изображения HSV, но я хочу только сделать эту гистограмму и вычисления для V-канала.Вычисление среднего и стандартного отклонения в C++ для одноканальной гистограммы

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

Вот что у меня есть на данный момент (переменная test - это изображение cv :: Mat, и это может быть любое изображение, которое вы хотите использовать для воссоздания проблемы). Я, вероятно, пропустил что-то очевидное, и цикл for может быть неправильным с точки зрения диапазона значений, но я еще не сделал этого на C++ раньше.

 cv::cvtColor(test, test, CV_BGR2HSV); 


     int v_bins = 50; 
     int histSize[] = { v_bins }; 
     cv::MatND hist; 

     float v_ranges[] = { 0, 255}; 
     cv::vector<cv::Mat> channel(3); 
     split(test, channel); 

     const float* ranges[] = { v_ranges }; 
     int channels[] = {0}; 

     cv::calcHist(&channel[2], 1, channels, cv::Mat(), hist, 1, histSize, ranges, true, false); //histogram calculation 

     float mean=0; 

     float rows= hist.size().height; 
     float cols = hist.size().width; 

     for (int v = 0; v < v_bins; v++) 
     { 
      std::cout << hist.at<float>(v, v) << std::endl;; 
      mean = mean + hist.at<float>(v); 
     } 

     mean = mean/(rows*cols); 
     std::cout << mean<< std::endl;; 
+0

cv :: вектор канал (3); ?? – sturkmen

+0

Я думал, что это необходимо, потому что HSV разделен на 3 канала, и мне нужен только V-канал для гистограммы – bardsleyta

+0

. Интересно, есть ли вектор cv :: vector? или std :: vector – sturkmen

ответ

2

Вы можете просто использовать cv::meanStdDev, который вычисляет среднее и стандартное отклонение элементов массива.

Обратите внимание, что оба mean и stddev аргументы cv::Scalar, так что вам нужно сделать mean[0] и stddev[0], чтобы получить двойные значения вашего одного массива hist канала.

Этот код будет разъяснено его использование:

#include <opencv2\opencv.hpp> 
#include <iostream> 

int main() 
{ 
    cv::Mat test = cv::imread("path_to_image"); 

    cv::cvtColor(test, test, CV_BGR2HSV); 

    int v_bins = 50; 
    int histSize[] = { v_bins }; 
    cv::MatND hist; 

    float v_ranges[] = { 0, 255 }; 
    cv::vector<cv::Mat> channel(3); 
    split(test, channel); 

    const float* ranges[] = { v_ranges }; 
    int channels[] = { 0 }; 

    cv::calcHist(&channel[2], 1, channels, cv::Mat(), hist, 1, histSize, ranges, true, false); //histogram calculation 

    cv::Scalar mean, stddev; 
    cv::meanStdDev(hist, mean, stddev); 

    std::cout << "Mean: " << mean[0] << " StdDev: " << stddev[0] << std::endl; 

    return 0; 
} 

UPDATE

Вы можете вычислить среднее значение и стандартное отклонение по их определению:

double dmean = 0.0; 
double dstddev = 0.0; 

// Mean standard algorithm 
for (int i = 0; i < v_bins; ++i) 
{ 
    dmean += hist.at<float>(i); 
} 
dmean /= v_bins; 

// Standard deviation standard algorithm 
std::vector<double> var(v_bins); 
for (int i = 0; i < v_bins; ++i) 
{ 
    var[i] = (dmean - hist.at<float>(i)) * (dmean - hist.at<float>(i)); 
} 
for (int i = 0; i < v_bins; ++i) 
{ 
    dstddev += var[i]; 
} 
dstddev = sqrt(dstddev/v_bins); 

std::cout << "Mean: " << dmean << " StdDev: " << dstddev << std::endl; 

и вы получите те же значения, что и OpenCV meanStdDev.

+0

ОК спасибо. попробуем это – bardsleyta

+0

Хорошо. Я получаю вывод, но для меня результаты, которые я получаю, выглядят довольно странно. я получаю среднее значение 69271.2 и стандартное отклонение 86937.1. Это реалистично для гистограммы или что-то пошло не так? – bardsleyta

+0

@bardsleyta Я обновил ответ и вычислением среднего и стандартного отклонения от их определения. Вы можете видеть, что результаты совпадают с результатами OpenCV. Если вы не ожидаете этих результатов, вероятно, вы не должны вычислять среднее и stddev на гистограмме, а на изображении. – Miki