1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html
4 
5 #include "precomp.hpp"
6 #include "opencv2/core/mat.hpp"
7 #include "opencv2/core/types_c.h"
8 
9 #ifndef OPENCV_EXCLUDE_C_API
10 // glue
11 
cvMatND(const cv::Mat & m)12 CvMatND cvMatND(const cv::Mat& m)
13 {
14     CvMatND self;
15     cvInitMatNDHeader(&self, m.dims, m.size, m.type(), m.data );
16     int i, d = m.dims;
17     for( i = 0; i < d; i++ )
18         self.dim[i].step = (int)m.step[i];
19     self.type |= m.flags & cv::Mat::CONTINUOUS_FLAG;
20     return self;
21 }
22 
cvIplImage(const cv::Mat & m)23 _IplImage cvIplImage(const cv::Mat& m)
24 {
25     _IplImage self;
26     CV_Assert( m.dims <= 2 );
27     cvInitImageHeader(&self, cvSize(m.size()), cvIplDepth(m.flags), m.channels());
28     cvSetData(&self, m.data, (int)m.step[0]);
29     return self;
30 }
31 
32 namespace cv {
33 
cvMatToMat(const CvMat * m,bool copyData)34 static Mat cvMatToMat(const CvMat* m, bool copyData)
35 {
36     Mat thiz;
37 
38     if( !m )
39         return thiz;
40 
41     if( !copyData )
42     {
43         thiz.flags = Mat::MAGIC_VAL + (m->type & (CV_MAT_TYPE_MASK|CV_MAT_CONT_FLAG));
44         thiz.dims = 2;
45         thiz.rows = m->rows;
46         thiz.cols = m->cols;
47         thiz.datastart = thiz.data = m->data.ptr;
48         size_t esz = CV_ELEM_SIZE(m->type), minstep = thiz.cols*esz, _step = m->step;
49         if( _step == 0 )
50             _step = minstep;
51         thiz.datalimit = thiz.datastart + _step*thiz.rows;
52         thiz.dataend = thiz.datalimit - _step + minstep;
53         thiz.step[0] = _step; thiz.step[1] = esz;
54     }
55     else
56     {
57         thiz.datastart = thiz.dataend = thiz.data = 0;
58         Mat(m->rows, m->cols, m->type, m->data.ptr, m->step).copyTo(thiz);
59     }
60 
61     return thiz;
62 }
63 
cvMatNDToMat(const CvMatND * m,bool copyData)64 static Mat cvMatNDToMat(const CvMatND* m, bool copyData)
65 {
66     Mat thiz;
67 
68     if( !m )
69         return thiz;
70     thiz.datastart = thiz.data = m->data.ptr;
71     thiz.flags |= CV_MAT_TYPE(m->type);
72     int _sizes[CV_MAX_DIM];
73     size_t _steps[CV_MAX_DIM];
74 
75     int d = m->dims;
76     for( int i = 0; i < d; i++ )
77     {
78         _sizes[i] = m->dim[i].size;
79         _steps[i] = m->dim[i].step;
80     }
81 
82     setSize(thiz, d, _sizes, _steps);
83     finalizeHdr(thiz);
84 
85     if( copyData )
86     {
87         Mat temp(thiz);
88         thiz.release();
89         temp.copyTo(thiz);
90     }
91 
92     return thiz;
93 }
94 
iplImageToMat(const IplImage * img,bool copyData)95 static Mat iplImageToMat(const IplImage* img, bool copyData)
96 {
97     Mat m;
98 
99     if( !img )
100         return m;
101 
102     m.dims = 2;
103     CV_DbgAssert(CV_IS_IMAGE(img) && img->imageData != 0);
104 
105     int imgdepth = IPL2CV_DEPTH(img->depth);
106     size_t esz;
107     m.step[0] = img->widthStep;
108 
109     if(!img->roi)
110     {
111         CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL);
112         m.flags = Mat::MAGIC_VAL + CV_MAKETYPE(imgdepth, img->nChannels);
113         m.rows = img->height;
114         m.cols = img->width;
115         m.datastart = m.data = (uchar*)img->imageData;
116         esz = CV_ELEM_SIZE(m.flags);
117     }
118     else
119     {
120         CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL || img->roi->coi != 0);
121         bool selectedPlane = img->roi->coi && img->dataOrder == IPL_DATA_ORDER_PLANE;
122         m.flags = Mat::MAGIC_VAL + CV_MAKETYPE(imgdepth, selectedPlane ? 1 : img->nChannels);
123         m.rows = img->roi->height;
124         m.cols = img->roi->width;
125         esz = CV_ELEM_SIZE(m.flags);
126         m.datastart = m.data = (uchar*)img->imageData +
127             (selectedPlane ? (img->roi->coi - 1)*m.step*img->height : 0) +
128             img->roi->yOffset*m.step[0] + img->roi->xOffset*esz;
129     }
130     m.datalimit = m.datastart + m.step.p[0]*m.rows;
131     m.dataend = m.datastart + m.step.p[0]*(m.rows-1) + esz*m.cols;
132     m.step[1] = esz;
133     m.updateContinuityFlag();
134 
135     if( copyData )
136     {
137         Mat m2 = m;
138         m.release();
139         if( !img->roi || !img->roi->coi ||
140             img->dataOrder == IPL_DATA_ORDER_PLANE)
141             m2.copyTo(m);
142         else
143         {
144             int ch[] = {img->roi->coi - 1, 0};
145             m.create(m2.rows, m2.cols, m2.type());
146             mixChannels(&m2, 1, &m, 1, ch, 1);
147         }
148     }
149 
150     return m;
151 }
152 
cvarrToMat(const CvArr * arr,bool copyData,bool,int coiMode,AutoBuffer<double> * abuf)153 Mat cvarrToMat(const CvArr* arr, bool copyData,
154                bool /*allowND*/, int coiMode, AutoBuffer<double>* abuf )
155 {
156     if( !arr )
157         return Mat();
158     if( CV_IS_MAT_HDR_Z(arr) )
159         return cvMatToMat((const CvMat*)arr, copyData);
160     if( CV_IS_MATND(arr) )
161         return cvMatNDToMat((const CvMatND*)arr, copyData );
162     if( CV_IS_IMAGE(arr) )
163     {
164         const IplImage* iplimg = (const IplImage*)arr;
165         if( coiMode == 0 && iplimg->roi && iplimg->roi->coi > 0 )
166             CV_Error(CV_BadCOI, "COI is not supported by the function");
167         return iplImageToMat(iplimg, copyData);
168     }
169     if( CV_IS_SEQ(arr) )
170     {
171         CvSeq* seq = (CvSeq*)arr;
172         int total = seq->total, type = CV_MAT_TYPE(seq->flags), esz = seq->elem_size;
173         if( total == 0 )
174             return Mat();
175         CV_Assert(total > 0 && CV_ELEM_SIZE(seq->flags) == esz);
176         if(!copyData && seq->first->next == seq->first)
177             return Mat(total, 1, type, seq->first->data);
178         if( abuf )
179         {
180             abuf->allocate(((size_t)total*esz + sizeof(double)-1)/sizeof(double));
181             double* bufdata = abuf->data();
182             cvCvtSeqToArray(seq, bufdata, CV_WHOLE_SEQ);
183             return Mat(total, 1, type, bufdata);
184         }
185 
186         Mat buf(total, 1, type);
187         cvCvtSeqToArray(seq, buf.ptr(), CV_WHOLE_SEQ);
188         return buf;
189     }
190     CV_Error(CV_StsBadArg, "Unknown array type");
191 }
192 
extractImageCOI(const CvArr * arr,OutputArray _ch,int coi)193 void extractImageCOI(const CvArr* arr, OutputArray _ch, int coi)
194 {
195     Mat mat = cvarrToMat(arr, false, true, 1);
196     _ch.create(mat.dims, mat.size, mat.depth());
197     Mat ch = _ch.getMat();
198     if(coi < 0)
199     {
200         CV_Assert( CV_IS_IMAGE(arr) );
201         coi = cvGetImageCOI((const IplImage*)arr)-1;
202     }
203     CV_Assert(0 <= coi && coi < mat.channels());
204     int _pairs[] = { coi, 0 };
205     mixChannels( &mat, 1, &ch, 1, _pairs, 1 );
206 }
207 
insertImageCOI(InputArray _ch,CvArr * arr,int coi)208 void insertImageCOI(InputArray _ch, CvArr* arr, int coi)
209 {
210     Mat ch = _ch.getMat(), mat = cvarrToMat(arr, false, true, 1);
211     if(coi < 0)
212     {
213         CV_Assert( CV_IS_IMAGE(arr) );
214         coi = cvGetImageCOI((const IplImage*)arr)-1;
215     }
216     CV_Assert(ch.size == mat.size && ch.depth() == mat.depth() && 0 <= coi && coi < mat.channels());
217     int _pairs[] = { 0, coi };
218     mixChannels( &ch, 1, &mat, 1, _pairs, 1 );
219 }
220 
221 } // cv::
222 
223 // operations
224 
cvSetIdentity(CvArr * arr,CvScalar value)225 CV_IMPL void cvSetIdentity( CvArr* arr, CvScalar value )
226 {
227     cv::Mat m = cv::cvarrToMat(arr);
228     cv::setIdentity(m, value);
229 }
230 
231 
cvTrace(const CvArr * arr)232 CV_IMPL CvScalar cvTrace( const CvArr* arr )
233 {
234     return cvScalar(cv::trace(cv::cvarrToMat(arr)));
235 }
236 
237 
cvTranspose(const CvArr * srcarr,CvArr * dstarr)238 CV_IMPL void cvTranspose( const CvArr* srcarr, CvArr* dstarr )
239 {
240     cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
241 
242     CV_Assert( src.rows == dst.cols && src.cols == dst.rows && src.type() == dst.type() );
243     transpose( src, dst );
244 }
245 
246 
cvCompleteSymm(CvMat * matrix,int LtoR)247 CV_IMPL void cvCompleteSymm( CvMat* matrix, int LtoR )
248 {
249     cv::Mat m = cv::cvarrToMat(matrix);
250     cv::completeSymm( m, LtoR != 0 );
251 }
252 
253 
cvCrossProduct(const CvArr * srcAarr,const CvArr * srcBarr,CvArr * dstarr)254 CV_IMPL void cvCrossProduct( const CvArr* srcAarr, const CvArr* srcBarr, CvArr* dstarr )
255 {
256     cv::Mat srcA = cv::cvarrToMat(srcAarr), dst = cv::cvarrToMat(dstarr);
257 
258     CV_Assert( srcA.size() == dst.size() && srcA.type() == dst.type() );
259     srcA.cross(cv::cvarrToMat(srcBarr)).copyTo(dst);
260 }
261 
262 
263 CV_IMPL void
cvReduce(const CvArr * srcarr,CvArr * dstarr,int dim,int op)264 cvReduce( const CvArr* srcarr, CvArr* dstarr, int dim, int op )
265 {
266     cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
267 
268     if( dim < 0 )
269         dim = src.rows > dst.rows ? 0 : src.cols > dst.cols ? 1 : dst.cols == 1;
270 
271     if( dim > 1 )
272         CV_Error( CV_StsOutOfRange, "The reduced dimensionality index is out of range" );
273 
274     if( (dim == 0 && (dst.cols != src.cols || dst.rows != 1)) ||
275         (dim == 1 && (dst.rows != src.rows || dst.cols != 1)) )
276         CV_Error( CV_StsBadSize, "The output array size is incorrect" );
277 
278     if( src.channels() != dst.channels() )
279         CV_Error( CV_StsUnmatchedFormats, "Input and output arrays must have the same number of channels" );
280 
281     cv::reduce(src, dst, dim, op, dst.type());
282 }
283 
284 
285 CV_IMPL CvArr*
cvRange(CvArr * arr,double start,double end)286 cvRange( CvArr* arr, double start, double end )
287 {
288     CvMat stub, *mat = (CvMat*)arr;
289     int step;
290     double val = start;
291 
292     if( !CV_IS_MAT(mat) )
293         mat = cvGetMat( mat, &stub);
294 
295     int rows = mat->rows;
296     int cols = mat->cols;
297     int type = CV_MAT_TYPE(mat->type);
298     double delta = (end-start)/(rows*cols);
299 
300     if( CV_IS_MAT_CONT(mat->type) )
301     {
302         cols *= rows;
303         rows = 1;
304         step = 1;
305     }
306     else
307         step = mat->step / CV_ELEM_SIZE(type);
308 
309     if( type == CV_32SC1 )
310     {
311         int* idata = mat->data.i;
312         int ival = cvRound(val), idelta = cvRound(delta);
313 
314         if( fabs(val - ival) < DBL_EPSILON &&
315             fabs(delta - idelta) < DBL_EPSILON )
316         {
317             for( int i = 0; i < rows; i++, idata += step )
318                 for( int j = 0; j < cols; j++, ival += idelta )
319                     idata[j] = ival;
320         }
321         else
322         {
323             for( int i = 0; i < rows; i++, idata += step )
324                 for( int j = 0; j < cols; j++, val += delta )
325                     idata[j] = cvRound(val);
326         }
327     }
328     else if( type == CV_32FC1 )
329     {
330         float* fdata = mat->data.fl;
331         for( int i = 0; i < rows; i++, fdata += step )
332             for( int j = 0; j < cols; j++, val += delta )
333                 fdata[j] = (float)val;
334     }
335     else
336         CV_Error( CV_StsUnsupportedFormat, "The function only supports 32sC1 and 32fC1 datatypes" );
337 
338     return arr;
339 }
340 
341 
342 CV_IMPL void
cvSort(const CvArr * _src,CvArr * _dst,CvArr * _idx,int flags)343 cvSort( const CvArr* _src, CvArr* _dst, CvArr* _idx, int flags )
344 {
345     cv::Mat src = cv::cvarrToMat(_src);
346 
347     if( _idx )
348     {
349         cv::Mat idx0 = cv::cvarrToMat(_idx), idx = idx0;
350         CV_Assert( src.size() == idx.size() && idx.type() == CV_32S && src.data != idx.data );
351         cv::sortIdx( src, idx, flags );
352         CV_Assert( idx0.data == idx.data );
353     }
354 
355     if( _dst )
356     {
357         cv::Mat dst0 = cv::cvarrToMat(_dst), dst = dst0;
358         CV_Assert( src.size() == dst.size() && src.type() == dst.type() );
359         cv::sort( src, dst, flags );
360         CV_Assert( dst0.data == dst.data );
361     }
362 }
363 
364 CV_IMPL int
cvKMeans2(const CvArr * _samples,int cluster_count,CvArr * _labels,CvTermCriteria termcrit,int attempts,CvRNG *,int flags,CvArr * _centers,double * _compactness)365 cvKMeans2( const CvArr* _samples, int cluster_count, CvArr* _labels,
366            CvTermCriteria termcrit, int attempts, CvRNG*,
367            int flags, CvArr* _centers, double* _compactness )
368 {
369     cv::Mat data = cv::cvarrToMat(_samples), labels = cv::cvarrToMat(_labels), centers;
370     if( _centers )
371     {
372         centers = cv::cvarrToMat(_centers);
373 
374         centers = centers.reshape(1);
375         data = data.reshape(1);
376 
377         CV_Assert( !centers.empty() );
378         CV_Assert( centers.rows == cluster_count );
379         CV_Assert( centers.cols == data.cols );
380         CV_Assert( centers.depth() == data.depth() );
381     }
382     CV_Assert( labels.isContinuous() && labels.type() == CV_32S &&
383         (labels.cols == 1 || labels.rows == 1) &&
384         labels.cols + labels.rows - 1 == data.rows );
385 
386     double compactness = cv::kmeans(data, cluster_count, labels, termcrit, attempts,
387                                     flags, _centers ? cv::_OutputArray(centers) : cv::_OutputArray() );
388     if( _compactness )
389         *_compactness = compactness;
390     return 1;
391 }
392 
393 #endif  // OPENCV_EXCLUDE_C_API
394