2013-04-27 2 views
1

전체 배열에서 배열 (MatND 객체)을 검색하여 MAX 값의 5 %가되는 곳을 알아야합니다. minMaxLoc 함수는 나에게 MAX 값을 반환하지만, 내 스스로 찾아서 뜨겁지는 모른다.OpenCv - 히스토그램 배열에서 값 얻기

아이디어가 있으십니까?

답변

3

그것이 UCHAR 매트이면

/** 
* @param : input image 
* @hist : histogram 
* @nmin : total minimum pixels number 
* @nmax : total maximum pixels number 
* @channel : channel number 
* 
* ex : images with 1000 pixels, 50 equal to 5% of it 
*/ 
std::pair<size_t, size_t> get_quantile_uchar(cv::Mat &input, cv::MatND &hist, size_t nmin, size_t nmax, int channel) 
{ 
    int const hist_size = std::numeric_limits<uchar>::max() + 1; 
    float const hranges[2] = {0, 255}; 
    float const *ranges[] = {hranges}; 

    //compute and cumulate the histogram 
    cv::calcHist(&input, 1, &channel, cv::Mat(), hist, 1, &hist_size, ranges); 
    auto *hist_ptr = hist.ptr<float>(0); 
    for(size_t i = 1; i != hist_size; ++i){ 
     hist_ptr[i] += hist_ptr[i - 1]; 
    } 

    // get the new min/max 
    std::pair<size_t, size_t> min_max(0, hist_size - 1); 
    while(min_max.first != (hist_size - 1) && hist_ptr[min_max.first] <= nmin){ 
     ++min_max.first; // the corresponding histogram value is the current cell position 
    } 

    while(min_max.second > 0 && hist_ptr[min_max.second] > nmax){ 
     --min_max.second; // the corresponding histogram value is the current cell position 
    } 

    if (min_max.second < hist_size - 2) 
     ++min_max.second; 

    return min_max; 
} 
0 ~ 255 내의 값을 갖는 매트 (* 100, 100)가있는 경우

예에서는, 사용자는 상단 5 % 백분위 최저 3 % 백분위 수를 측정 할 수 그것이 UCHAR 매트가 아닌 경우이

auto const result = get_quantile(input, hist, input.total * 0.03, input.total * 0.95, 0); 

처럼, 당신은 당신이 먼저 측정하고자하는 채널을 정렬 할 수 있습니다

/** 
* @brief generic algorithm for other channel types except of uchar 
* @param input the input image 
* @param output the output image 
* @param smin total number of minimum pixels 
* @param smax total number maximum pixels 
* @param channel the channel used to compute the histogram 
* 
* This algorithm only support uchar channel and float channel by now 
*/ 
template<typename T> 
std::pair<T, T> get_quantile(cv::Mat &input, size_t smin, size_t smax, int channel) 
{ 
    std::vector<float> temp_input = copy_to_one_dim_array_ch<float>(input, channel); 
    std::sort(std::begin(temp_input), std::end(temp_input)); 

    return std::pair<T, T>(temp_input[smin], temp_input[temp_input.size() - 1 - smax]); 
} 

다음 문제는 당신이 쉽게되기 확인하려면 nonbyte 이미지를

를 지원하지 않는 기능 copy_to_one_dim_array_ch 일부 기능은 C++ 11 지원이 필요

/* 
* experimental version for cv::Mat, try to alleviate the problem 
* of code bloat.User should make sure the space of begin point to 
* have enough of spaces. 
*/ 
template<typename T, typename InputIter> 
void copy_to_one_dim_array_ch(cv::Mat const &src, InputIter begin, int channel) 
{ 
    int const channel_number = src.channels(); 
    if(channel_number <= channel || channel < 0){ 
     throw std::out_of_range("channel value is invalid\n" + std::string(__FUNCTION__) + 
           "\n" + std::string(__FILE__)); 
    } 

    for(int row = 0; row != src.rows; ++row){ 
     auto ptr = src.ptr<T>(row) + channel; 
     for(int col = 0; col != src.cols; ++col){ 
      *begin = *ptr; 
      ++begin; 
      ptr += channel_number; 
     } 
    } 
} 

template<typename T> 
std::vector<T> const copy_to_one_dim_array_ch(cv::Mat const &src, int channel) 
{ 
    std::vector<T> result(src.total()); 
    copy_to_one_dim_array_ch<T>(src, std::begin(result), channel); 

    return result; 
} 

및 기능 copy_to_one_dim_array_ch 을 구현하는 방법입니다 사용하려면 수 있습니다. 1 : 클래스의 함수를 래핑하십시오.
2 : uchar에 완전 전문화 적용 3 : 함수에서 클래스 래핑