0

I have a matrix that consists of integers from 0 to N, and I want to obtain a data matrix of size N+1 where each element has the number of occurences of each number.

So if the input matrix is

0 0 0
1 1 0
0 0 2

Then my output should be

// occurences of  0  1  2
hist           = [6, 2, 1]

Is there an easy (built-in) way to accomplish this in C++ OpenCV, like the hist function in MATLAB?

Thanks !

jeff
  • 13,055
  • 29
  • 78
  • 136

2 Answers2

3

Just to provide an alternative to OpenCV calcHist, you can use a std::vector, and increment the counter at the grayscale value position:

#include <opencv2\opencv.hpp>
#include <iostream>
#include <algorithm>
#include <numeric>
using namespace std;
using namespace cv;

int main(void)
{
    // Grayscale image
    Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);

    // Compute histogram
    vector<int> hist(256, 0);
    for (int r = 0; r < img.rows; ++r)
        for (int c = 0; c < img.cols; ++c)
            ++hist[img(r, c)];

    cout << "number of 0: " << hist[0] << endl;
    cout << "number of 1: " << hist[1] << endl;
    // etc...


    // Sort according to frequency

    vector<int> indices(256);
    iota(indices.begin(), indices.end(), 0); // 0, 1, ... 255
    sort(indices.begin(), indices.end(), [&hist](int lhs, int rhs) { return hist[lhs] > hist[rhs]; });

    cout << "1st frequent number: " << indices[0] << " with N: " << hist[indices[0]] << endl;
    cout << "2nd frequent number: " << indices[1] << " with N: " << hist[indices[1]] << endl;
    // etc

    return 0;
}

Updated the snippet to sort result according to decreasing frequency.

Miki
  • 40,887
  • 13
  • 123
  • 202
1

This code reads all the grayscale values from an image and results in frequent occurring values (Number of times the value as occurred). i.e

Number of times pixel value '0' as appeared,

Number of times pixel value '1' as appeared, ... & so on till 256.

#include <opencv\cv.h>
#include <highgui\highgui.hpp>
using namespace std;
using namespace cv;
    int main()
{
cv::Mat img = cv::imread("5.jpg",0);

//for(int j=0;j<img.rows;j++) 
//{
//  for (int i=0;i<img.cols;i++)
//  {
//    int a;
//  a=img.at<uchar>(j,i);
//     cout<<a<<endl; 
//  }
//}
vector<int> values_rgb;
for(int i=0; i<20; i++)
{
    for(int j=0; j<20; j++)
    {
        int value_rgb = img.at<uchar>(i,j);
        values_rgb.push_back(value_rgb);
        //cout << "(" << i << "," << j << ") : " << value_rgb <<endl;
    }
}
// Sorting of values in ascending order 
vector<int> counter_rg_values;
for(int l=0; l<256; l++)

{
    for(int k=0; k<values_rgb.size(); k++)
    {
        if(values_rgb.at(k) == l)
        {
            counter_rg_values.push_back(l);
        }
    }
}
//for(int m=0;m<counter_rg_values.size();m++)
//cout<<m<<" "<< counter_rg_values[m] <<endl;
int m=0;
for(int n=0;n<256;n++)
{
    int c=0;
    for(int q=0;q<counter_rg_values.size();q++)
    {
        if(n==counter_rg_values[q])
        {
            //int c;
        c++;
        m++;
        }
    }

    cout<<n<<"= "<< c<<endl;
}
cout<<"Total number of elements "<< m<<endl;

cv::imshow("After",img);
waitKey(0);
}

Link for the above discussion about https://stackoverflow.com/a/32902450/3853072

Community
  • 1
  • 1