mexopencv  0.1
mex interface for opencv library
calcHist.cpp
Go to the documentation of this file.
1 
8 #include "mexopencv.hpp"
9 using namespace std;
10 using namespace cv;
11 
12 namespace {
13 int check_arguments(int dims, bool uniform,
14  const vector<vector<float> > &ranges, const vector<int> &channels,
15  const vector<int> &histSize)
16 {
17  // some defensive checks not covered in cv::calcHist
18  // TODO: we could also infer dims/histSize from hist0 if supplied
19  if (!histSize.empty() && !ranges.empty()) {
20  if (histSize.size() != ranges.size())
21  mexErrMsgIdAndTxt("mexopencv:error",
22  "HistSize must match histogram dimensionality");
23  if (!uniform) {
24  for (mwIndex i=0; i<ranges.size(); ++i) {
25  if (histSize[i] != (ranges[i].size() - 1))
26  mexErrMsgIdAndTxt("mexopencv:error",
27  "HistSize must match non-uniform ranges");
28  }
29  }
30  }
31  else if (!histSize.empty() && ranges.empty()) {
32  if (uniform)
33  dims = histSize.size(); // infer dims from histSize not ranges
34  }
35  if (!channels.empty() && channels.size() < dims)
36  mexErrMsgIdAndTxt("mexopencv:error",
37  "Channels must match histogram dimensionality");
38  return dims;
39 }
40 }
41 
49 void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
50 {
51  // Check the number of arguments
52  nargchk(nrhs>=2 && (nrhs%2)==0 && nlhs<=1);
53 
54  // Argument vector
55  vector<MxArray> rhs(prhs, prhs+nrhs);
56 
57  // source arrays (cell array of images)
58  vector<Mat> arrays;
59  {
60  vector<MxArray> arrays_(rhs[0].toVector<MxArray>());
61  arrays.reserve(arrays_.size());
62  for (vector<MxArray>::const_iterator it = arrays_.begin(); it != arrays_.end(); ++it)
63  arrays.push_back(it->toMat(it->isUint8() ? CV_8U :
64  (it->isUint16() ? CV_16U : CV_32F)));
65  }
66 
67  // channels: default to use all channels from all images to compute hist
68  int total_channels = 0;
69  for (vector<Mat>::const_iterator it = arrays.begin(); it != arrays.end(); ++it)
70  total_channels += it->channels();
71  vector<int> channels(total_channels);
72  for (int i=0; i<total_channels; ++i)
73  channels[i] = i;
74 
75  // ranges (cell array of vectors): bin boundaries in each hist dimension
76  vector<vector<float> > ranges(MxArrayToVectorVectorPrimitive<float>(rhs[1]));
77  int dims = static_cast<int>(ranges.size()); // histogram dimensionality
78  vector<const float*> ranges_ptr(dims);
79  for (mwIndex i=0; i<dims; ++i)
80  ranges_ptr[i] = (!ranges[i].empty() ? &ranges[i][0] : NULL);
81 
82  // histSize: number of levels in each hist dimension (non-uniform case)
83  vector<int> histSize(dims);
84  for (mwIndex i=0; i<dims; ++i)
85  histSize[i] = (!ranges[i].empty() ? ranges[i].size() - 1 : 0);
86 
87  // Option processing
88  Mat mask;
89  bool uniform = false;
90  MxArray hist0(static_cast<mxArray*>(NULL));
91  bool accumulate = false;
92  bool sparse = false;
93  for (int i=2; i<nrhs; i+=2) {
94  string key(rhs[i].toString());
95  if (key == "Channels")
96  channels = rhs[i+1].toVector<int>();
97  else if (key == "Mask")
98  mask = rhs[i+1].toMat(CV_8U);
99  else if (key == "HistSize")
100  histSize = rhs[i+1].toVector<int>();
101  else if (key == "Uniform")
102  uniform = rhs[i+1].toBool();
103  else if (key == "Hist") {
104  hist0 = rhs[i+1]; // either MatND or SparseMat
105  accumulate = true;
106  }
107  else if (key == "Sparse")
108  sparse = rhs[i+1].toBool();
109  else
110  mexErrMsgIdAndTxt("mexopencv:error",
111  "Unrecognized option %s", key.c_str());
112  }
113 
114  // Process
115  dims = check_arguments(dims, uniform, ranges, channels, histSize);
116  if (sparse) {
117  SparseMat hist;
118  if (accumulate) hist = hist0.toSparseMat(CV_32F);
119  calcHist((!arrays.empty() ? &arrays[0] : NULL), arrays.size(),
120  (!channels.empty() ? &channels[0] : NULL), mask, hist, dims,
121  (!histSize.empty() ? &histSize[0] : NULL),
122  (!ranges_ptr.empty() ? &ranges_ptr[0] : NULL),
123  uniform, accumulate);
124  plhs[0] = MxArray(hist); // 2D sparse matrix
125  }
126  else {
127  MatND hist;
128  if (accumulate) hist = hist0.toMatND(CV_32F);
129  calcHist((!arrays.empty() ? &arrays[0] : NULL), arrays.size(),
130  (!channels.empty() ? &channels[0] : NULL), mask, hist, dims,
131  (!histSize.empty() ? &histSize[0] : NULL),
132  (!ranges_ptr.empty() ? &ranges_ptr[0] : NULL),
133  uniform, accumulate);
134  plhs[0] = MxArray(hist); // multi-dim dense array
135  }
136 }
cv::MatND toMatND(int depth=CV_USRTYPE1, bool transpose=true) const
Convert MxArray to a single-channel cv::Mat.
Definition: MxArray.cpp:601
mxArray object wrapper for data conversion and manipulation.
Definition: MxArray.hpp:123
void nargchk(bool cond)
Alias for input/ouput arguments number check.
Definition: mexopencv.hpp:166
bool toBool() const
Convert MxArray to bool.
Definition: MxArray.cpp:510
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
Main entry called from Matlab.
Definition: calcHist.cpp:49
Global constant definitions.
cv::SparseMat toSparseMat(int depth=CV_USRTYPE1) const
Convert double sparse MxArray to 2D single-channel cv::SparseMat.
Definition: MxArray.cpp:647