2

here is the line of code I want to implement

kb = [];
    for k = 1:length(nRef)
        for n=1:length(dCmpInd{k})
            x = [centroid(nRef{k}, 1), centroid(dCmpInd{k}(n),1)];
            y = [centroid(nRef{k}, 2), centroid(dCmpInd{k}(n),2)];

            [x,ind] = sort(x);
            y = y(ind);
            kb = [kb diff(y) / diff(x)];
        end
    end

    theta = (atan(kb));

    [N, X] = hist(abs(theta),2);

here is my c++ code:

 std::vector<double> kb;
    std::vector<double> theta;
    for (int k = 0; k < nRef.size(); k++)
    {
        for (int n = 0; n < dCmpInd[k].size(); n++)
        {
            double x1 = centroids[nRef[k]].m_X; double x2 = centroids[dCmpInd[k][n]].m_X;
            double y1 = centroids[nRef[k]].m_Y; double y2 = centroids[dCmpInd[k][n]].m_Y;
            if (x1 <x2)
            {
                double tempdiff = (y2-y1)/(x2-x1);              
                kb.push_back(tempdiff);
                theta.push_back(abs(atan(tempdiff)));
            }
            else
            {
                double tempdiff = (y1-y2)/(x1-x2);
                kb.push_back(tempdiff);
                theta.push_back(abs(atan(tempdiff)));
            }
        }
    }

is there a quick way to implement :

[N,X] = hist(theta,2);

I can use openCV 2.4.10 as well but calcHist() isn't really the same, I need to create 2 bins.

my input is 1D array:

0.00598881028540019 1.56120677124307    0.00598881028540019 0.00669537049433832 1.37723800334516    1.37723800334516    1.36424594043624    1.56120677124307    0.0152220988707370

the output is:

X= 0.394793300524817    1.17240228100365
 N = 4 5
Gilad
  • 6,437
  • 14
  • 61
  • 119
  • What's wrong with using with OpenCV's fuction? Anyway, implementing a custom histogram class/function should not be necessary (unless you want some practice), there are enough examples available. – Baiz Mar 29 '15 at 16:00
  • @Baiz there is a functionality for matlab where you can sort a 1D array into number of bins you want. in my case =2. I can't achieve that in openCV. maybe i just don't how to but I have tried. – Gilad Mar 29 '15 at 16:12
  • How did you call OpenCV's calcHist-function? Looking at the [documentation](http://docs.opencv.org/modules/imgproc/doc/histograms.html?highlight=calchist#calchist), the parameter histSize is what you need to specify. Cause all you really want is a histogram with two bins. – Baiz Mar 29 '15 at 16:40

2 Answers2

1

calcHist works fine. Try the below way of choosing the histSize and range. Hope it helps !.

float ary[9] = { 0.00598881028540019, 1.56120677124307,0.00598881028540019, 0.00669537049433832,1.37723800334516, 1.37723800334516, 1.36424594043624,1.56120677124307, 0.0152220988707370 };
cv::Mat srcMat = cv::Mat(1, 9, CV_32FC1, ary);
int histSize = 2;
float range[] = { 0.0, 2.0 };
const float* histRange = { range };
bool uniform = true;
bool accumulate = false;
cv::Mat histOut;
cv::calcHist(&srcMat, 1, 0, Mat(),histOut, 1, &histSize, &histRange, uniform, accumulate);
cout << histOut << endl;
sriram
  • 411
  • 2
  • 7
  • ok I see you point about the bins size, but where do i get X= 0.394793300524817 1.17240228100365 from ? – Gilad Mar 30 '15 at 12:34
  • I don't think so you can get that directly using calcHist or any functions. Those are nothing but the bin centers. You can use this matlab script to reproduce the result. `binwidth = (maxy - miny) ./ x; xx = miny + binwidth*(0:x); xx(length(xx)) = maxy; x = xx(1:length(xx)-1) + binwidth/2;` – sriram Mar 31 '15 at 09:39
1

Although this is not a full implementation here is what I did

HistogramResults Utilities::Hist(std::vector<double> vector, std::vector<double> x)
{
    if (vector.empty())
    {
        return HistogramResults();
    }
    if(x.empty())
    {
        x.push_back(10);
    }
    std::vector<double> N(x);
    std::vector<double>::iterator iter = std::min_element(std::begin(vector),std::end(vector));
    double minY = *iter;
    iter = std::max_element(std::begin(vector),std::end(vector));
    double maxY = *iter;
    std::vector<double> xx;
    if (x.size() == 1)
    {
        if (minY == maxY)
        {
            minY = minY - floor(x[0] /2) - 0.5;
            maxY = maxY - ceil(x[0] /2) - 0.5;
        }
        double binwidth = (maxY - minY)/x[0];

        xx.push_back(-1*std::numeric_limits<double>::infinity());
        for (int i = 0; i <= x[0]; i++)
        {
            xx.push_back( minY +  binwidth * i);
        }
        xx[x[0]+1] = maxY;
        xx.push_back(std::numeric_limits<double>::infinity());
        x.clear();

        for (int i = 1; i < xx.size()-2; i++)
        {
            x.push_back(xx[i] + binwidth/2);
        }       
    }
    else
    {
    }

    std::vector<int> nn =HistC(vector,xx);
    nn[1] = nn[1] +nn[0];
    nn[nn.size()-1] == nn[nn.size()-1] + nn[nn.size()-2];
    nn.pop_back();
    nn.erase (nn.begin());
    return HistogramResults(nn,x);
}

std::vector<int> Utilities::HistC(std::vector<double> y, std::vector<double> edges)
{
    std::vector<int> bins(edges.size()-1);
    for (int i = 0; i < y.size(); i++)
    {
        for (int j = 0; j < edges.size()-1; j++)
        {
            if( (edges[j] < y[i]) && (y[i] <= edges[j+1]))
            {
                bins[j]= bins[j]+1;
            }
        }
    }
    return bins;
}

here is the class HistorgramResults

#include "HistogramResults.h"


HistogramResults::HistogramResults(std::vector<int> numberOfElementN, std::vector<double> averageX)
{
    m_numberOfElementN = numberOfElementN;
    m_averageX = averageX;
}

HistogramResults::HistogramResults(void)
{
}

HistogramResults::~HistogramResults(void)
{
}
Gilad
  • 6,437
  • 14
  • 61
  • 119