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