00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "Matlab/mexConverts.H"
00040
00041 #include "Image/Image.H"
00042 #include "Image/Pixels.H"
00043 #include "Matlab/mexLog.H"
00044 #include "Util/sformat.H"
00045 #include "rutz/shared_ptr.h"
00046
00047
00048 template <class T>
00049 Image<T> mexArray2Image(const mxArray* arrptr)
00050 {
00051 const int* intptr = mxGetDimensions(arrptr);
00052 const int num_dim = mxGetNumberOfDimensions(arrptr);
00053 const int height = *intptr++;
00054 const int width = *intptr++;
00055
00056
00057 if (num_dim != 2)
00058 mexFatal(sformat("Wrong number of dimensions for gray scale image: %i "
00059 "- should be 2.",num_dim));
00060
00061
00062 Image<T> img(width, height, NO_INIT);
00063
00064 if (mxIsUint8(arrptr))
00065 {
00066 const byte *src_ptr, *src_ptr2;
00067 src_ptr = (byte*)mxGetPr(arrptr);
00068 typename Image<T>::iterator tgt_ptr = img.beginw();
00069 for (int y = 0; y < height; y++)
00070 {
00071 src_ptr2 = src_ptr;
00072 for (int x = 0; x < width; x++)
00073 {
00074 conv(src_ptr2,&*(tgt_ptr++));
00075 src_ptr2 += height;
00076 }
00077 src_ptr++;
00078 }
00079 }
00080 else if (mxIsDouble(arrptr))
00081 {
00082 const double *src_ptr, *src_ptr2;
00083 src_ptr = (double*)mxGetPr(arrptr);
00084 typename Image<T>::iterator tgt_ptr = img.beginw();
00085 for (int y = 0; y < height; y++)
00086 {
00087 src_ptr2 = src_ptr;
00088 for (int x = 0; x < width; x++)
00089 {
00090 conv(src_ptr2,&*(tgt_ptr++));
00091 src_ptr2 += height;
00092 }
00093 src_ptr++;
00094 }
00095 }
00096 else mexFatal("Image data type must be uint8 or double.");
00097
00098 return img;
00099 }
00100
00101
00102
00103 template <class T>
00104 Image< PixRGB<T> > mexArray2RGBImage(const mxArray* arrptr)
00105 {
00106 const int* intptr = mxGetDimensions(arrptr);
00107 const int num_dim = mxGetNumberOfDimensions(arrptr);
00108 const int height = *intptr++;
00109 const int width = *intptr++;
00110 const int size = width * height;
00111 int RGBcount = 0;
00112
00113
00114 if (num_dim > 2)
00115 {
00116 if (*intptr == 3) RGBcount = size;
00117 else if (*intptr != 1)
00118 mexFatal(sformat("Wrong number of dimensions for image: %d "
00119 "- should be 2 for grayscale or 3 for RGB",num_dim));
00120 }
00121 int RGBcount2 = RGBcount + RGBcount;
00122
00123
00124 Image< PixRGB<T> > img(width, height, NO_INIT);
00125 if (mxIsUint8(arrptr))
00126 {
00127 const byte *src_ptr, *src_ptr2;
00128 src_ptr = (byte*)mxGetPr(arrptr);
00129 T dummy;
00130 typename Image<PixRGB<T> >::iterator tgt_ptr = img.beginw();
00131 for (int y = 0; y < height; y++)
00132 {
00133 src_ptr2 = src_ptr;
00134 for (int x = 0; x < width; x++)
00135 {
00136 tgt_ptr->setRed (conv(src_ptr2, &dummy));
00137 tgt_ptr->setGreen(conv(src_ptr2 + RGBcount, &dummy));
00138 tgt_ptr->setBlue (conv(src_ptr2 + RGBcount2, &dummy));
00139 tgt_ptr++;
00140 src_ptr2 += height;
00141 }
00142 src_ptr++;
00143 }
00144 }
00145 else if (mxIsDouble(arrptr))
00146 {
00147 const double *src_ptr, *src_ptr2;
00148 src_ptr = (double*)mxGetPr(arrptr);
00149 T dummy;
00150 typename Image<PixRGB<T> >::iterator tgt_ptr = img.beginw();
00151 for (int y = 0; y < height; y++)
00152 {
00153 src_ptr2 = src_ptr;
00154 for (int x = 0; x < width; x++)
00155 {
00156 tgt_ptr->setRed (conv(src_ptr2, &dummy));
00157 tgt_ptr->setGreen(conv(src_ptr2 + RGBcount, &dummy));
00158 tgt_ptr->setBlue (conv(src_ptr2 + RGBcount2, &dummy));
00159 tgt_ptr++;
00160 src_ptr2 += height;
00161 }
00162 src_ptr++;
00163 }
00164 }
00165 else mexFatal("Image data type must be uint8 or double.");
00166
00167 return img;
00168 }
00169
00170
00171 template <class T>
00172 mxArray* Image2mexArray(const Image<T>& img)
00173 {
00174 if (img.getSize() == 0) return mxCreateScalarDouble(0);
00175 double *tgt_ptr, *tgt_ptr2;
00176 int height = img.getHeight(), width = img.getWidth();
00177 mxArray* arrptr = mxCreateDoubleMatrix(height, width, mxREAL);
00178 tgt_ptr = (double*)mxGetPr(arrptr);
00179 typename Image<T>::const_iterator src_ptr = img.begin();
00180 for (int y = 0; y < height; y++)
00181 {
00182 tgt_ptr2 = tgt_ptr;
00183 for (int x = 0; x < width; x++)
00184 {
00185 conv(&*(src_ptr++),tgt_ptr2);
00186 tgt_ptr2 += height;
00187 }
00188 tgt_ptr++;
00189 }
00190 return arrptr;
00191 }
00192
00193
00194 mxArray* Image2mexArrayUint8(const Image<byte>* img)
00195 {
00196 const int height = img->getHeight();
00197 const int width = img->getWidth();
00198 mxArray* arrptr =
00199 mxCreateNumericMatrix(height, width, mxUINT8_CLASS, mxREAL);
00200 byte* tgt_ptr = reinterpret_cast<byte*>(mxGetPr(arrptr));
00201 Image<byte>::const_iterator src_ptr = img->begin();
00202 for (int y = 0; y < height; ++y)
00203 {
00204 byte* tgt_ptr2 = tgt_ptr;
00205 for (int x = 0; x < width; ++x)
00206 {
00207 *tgt_ptr2 = *src_ptr++;
00208 tgt_ptr2 += height;
00209 }
00210 ++tgt_ptr;
00211 }
00212 return arrptr;
00213 }
00214
00215
00216 template <class T>
00217 mxArray* RGBImage2mexArray(const Image< PixRGB<T> >& img)
00218 {
00219 if (img.getSize() == 0) return mxCreateScalarDouble(0);
00220 double *tgt_ptr, *tgt_ptr2;
00221 T r, g, b;
00222 int dims[3];
00223 dims[0] = img.getHeight();
00224 dims[1] = img.getWidth();
00225 dims[2] = 3;
00226 int size = dims[0] * dims[1], size2 = size + size;
00227 mxArray* arrptr = mxCreateNumericArray(3, dims, mxDOUBLE_CLASS, mxREAL);
00228 tgt_ptr = (double*)mxGetPr(arrptr);
00229 typename Image<PixRGB<T> >::const_iterator src_ptr = img.begin();
00230 for (int y = 0; y < dims[0]; y++)
00231 {
00232 tgt_ptr2 = tgt_ptr;
00233 for (int x = 0; x < dims[1]; x++)
00234 {
00235 r = src_ptr->red(); g = src_ptr->green(); b = src_ptr->blue();
00236 conv(&r,tgt_ptr2); conv(&g,tgt_ptr2 + size); conv(&b, tgt_ptr2 + size2);
00237 src_ptr++;
00238 tgt_ptr2 += dims[0];
00239 }
00240 tgt_ptr++;
00241 }
00242 return arrptr;
00243 }
00244
00245
00246 mxArray* RGBImage2mexArrayUint8(const Image< PixRGB<byte> >* img)
00247 {
00248 const int dims[3] =
00249 {
00250 img->getHeight(),
00251 img->getWidth(),
00252 3
00253 };
00254 const int size = dims[0] * dims[1];
00255 const int size2 = size + size;
00256 mxArray* arrptr =
00257 mxCreateNumericArray(3, dims, mxUINT8_CLASS, mxREAL);
00258 byte* tgt_ptr = reinterpret_cast<byte*>(mxGetPr(arrptr));
00259 Image<PixRGB<byte> >::const_iterator src_ptr = img->begin();
00260
00261 for (int y = 0; y < dims[0]; ++y)
00262 {
00263 byte* tgt_ptr2 = tgt_ptr;
00264 for (int x = 0; x < dims[1]; ++x)
00265 {
00266 tgt_ptr2[0] = src_ptr->red();
00267 tgt_ptr2[size] = src_ptr->green();
00268 tgt_ptr2[size2] = src_ptr->blue();
00269 ++src_ptr;
00270 tgt_ptr2 += dims[0];
00271 }
00272 ++tgt_ptr;
00273 }
00274
00275 return arrptr;
00276 }
00277
00278
00279 template <class T>
00280 std::vector<T> mexArr2Vector(const mxArray* vecptr, uint num_elements)
00281 {
00282 if (!mxIsDouble(vecptr))
00283 mexErrMsgTxt("Can only convert vectors of type double.");
00284 if((uint)mxGetNumberOfElements(vecptr) < num_elements)
00285 mexErrMsgTxt("Not enough data to convert to vector.");
00286
00287 double* src_ptr = (double*)mxGetPr(vecptr);
00288 std::vector<T> result;
00289 for (uint i = 0; i < num_elements; i++)
00290 result.push_back((T)(*src_ptr++));
00291
00292 return result;
00293 }
00294
00295
00296 template <class T>
00297 std::vector<T> mexArr2Vector(const mxArray* vecptr)
00298 {
00299 return mexArr2Vector<T>(vecptr, (uint)mxGetNumberOfElements(vecptr));
00300 }
00301
00302
00303 template <class T>
00304 mxArray* Vector2mexArr(const std::vector<T>& vect, uint num_elements)
00305 {
00306 if (vect.size() < num_elements)
00307 mexFatal(sformat("std::vector too small to convert to mxArray: "
00308 "%"ZU", but should be %d.",vect.size(),num_elements));
00309
00310 if (vect.empty()) return mxCreateScalarDouble(0);
00311
00312 mxArray* result = mxCreateDoubleMatrix(1, num_elements, mxREAL);
00313 double* tgt_ptr = (double*)mxGetPr(result);
00314 for (uint i = 0; i < num_elements; i++)
00315 *tgt_ptr++ = (double)vect[i];
00316 return result;
00317 }
00318
00319
00320 template <class T>
00321 mxArray* Vector2mexArr(const std::vector<T>& vect)
00322 {
00323 return Vector2mexArr(vect, vect.size());
00324 }
00325
00326
00327 std::vector<Point2D<int> > mexArr2Point2DVec(const mxArray* arrptr)
00328 {
00329 if (!mxIsDouble(arrptr))
00330 mexFatal("Can only convert vectors of type double.");
00331 if (mxGetNumberOfDimensions(arrptr) != 2)
00332 mexFatal("mxArray must be 2D to be converted to vector<Point2D<int> >.");
00333 if (mxGetM(arrptr) != 2)
00334 mexFatal("mxArray must be of dimensions 2 x N to be converted "
00335 "to vector<Point2D<int> >");
00336 int n = mxGetN(arrptr);
00337 const double* src_ptr = (double*) mxGetPr(arrptr);
00338 std::vector<Point2D<int> > result;
00339
00340 for (int i = 0; i < n; i++)
00341 {
00342 result.push_back(Point2D<int>((int)src_ptr[0], (int)src_ptr[1]));
00343 src_ptr += 2;
00344 }
00345 return result;
00346 }
00347
00348
00349 mxArray* Point2DVec2mexArr(const std::vector<Point2D<int> >& vect)
00350 {
00351 if (vect.empty()) return mxCreateScalarDouble(0);
00352 mxArray* result = mxCreateDoubleMatrix(2, vect.size(), mxREAL);
00353 double* tgt_ptr = (double*)mxGetPr(result);
00354 for (uint i = 0; i < vect.size(); i++)
00355 {
00356 *tgt_ptr++ = (double)vect[i].i;
00357 *tgt_ptr++ = (double)vect[i].j;
00358 }
00359 return result;
00360 }
00361
00362
00363 template <class T>
00364 mxArray* ImgVec2mexArr(const ImageSet<T>& vect)
00365 {
00366 if (vect.isEmpty()) return mxCreateScalarDouble(0);
00367
00368 int dims[3];
00369 dims[0] = vect.size();
00370 dims[1] = vect[0].getHeight();
00371 dims[2] = vect[0].getWidth();
00372 int inc = dims[0] * dims[1];
00373 mxArray* result = mxCreateNumericArray(3, dims, mxDOUBLE_CLASS, mxREAL);
00374 double *tgt, *tgt2, *tgt3;
00375 tgt = (double*)mxGetPr(result);
00376
00377 for (int i = 0; i < dims[0]; i++)
00378 {
00379 tgt2 = tgt;
00380 if (!vect[i].isSameSize(vect[0]))
00381 mexFatal("All images in an ImageSet must have the same dimensions.");
00382 typename Image<T>::const_iterator src = vect[i].begin();
00383 for (int y = 0; y < dims[1]; y++)
00384 {
00385 tgt3 = tgt2;
00386 for (int x = 0; x < dims[2]; x++)
00387 {
00388 conv(&*(src++),tgt3);
00389 tgt3 += inc;
00390 }
00391 tgt2 += dims[0];
00392 }
00393 tgt++;
00394 }
00395 return result;
00396 }
00397
00398
00399 template <class T>
00400 ImageSet<T> mexArr2ImgVec(const mxArray* arrptr)
00401 {
00402 const int num_dim = mxGetNumberOfDimensions(arrptr);
00403 const int* dims = mxGetDimensions(arrptr);
00404 int num_img=0, height=0, width=0;
00405
00406 switch(num_dim)
00407 {
00408 case 2:
00409 {
00410 num_img = 1;
00411 height = dims[0];
00412 width = dims[1];
00413 break;
00414 }
00415
00416 case 3:
00417 {
00418 num_img = dims[0];
00419 height = dims[1];
00420 width = dims[2];
00421 break;
00422 }
00423
00424 default:
00425 {
00426 mexFatal(sformat("Array must have 2 or 3 dimensions to be converted to "
00427 "a grayscale image vector, but not %d.",num_dim));
00428 break;
00429 }
00430 }
00431 const int inc = num_img * height;
00432 ImageSet<T> result(num_img, Dims(dims[2], dims[1]), NO_INIT);
00433
00434 if (mxIsUint8(arrptr))
00435 {
00436 const byte *src, *src2, *src3;
00437 src = (byte*)mxGetPr(arrptr);
00438 for (int img_no = 0; img_no < num_img; ++img_no)
00439 {
00440 src2 = src;
00441 typename Image<T>::iterator tgt = result[img_no].beginw();
00442 for (int y = 0; y < height; ++y)
00443 {
00444 src3 = src2;
00445 for (int x = 0; x < width; ++x)
00446 {
00447 conv(src3,&*(tgt++));
00448 src3 += inc;
00449 }
00450 src2 += num_img;
00451 }
00452 src++;
00453 }
00454 }
00455 else if (mxIsDouble(arrptr))
00456 {
00457 const double *src, *src2, *src3;
00458 src = (double*)mxGetPr(arrptr);
00459 for (int img_no = 0; img_no < num_img; ++img_no)
00460 {
00461 src2 = src;
00462 typename Image<T>::iterator tgt = result[img_no].beginw();
00463 for (int y = 0; y < height; ++y)
00464 {
00465 src3 = src2;
00466 for (int x = 0; x < width; ++x)
00467 {
00468 conv(src3,&*(tgt++));
00469 src3 += inc;
00470 }
00471 src2 += num_img;
00472 }
00473 src++;
00474 }
00475 }
00476 else mexFatal("Image data type must be uint8 or double.");
00477
00478 return result;
00479 }
00480
00481
00482 template <class T>
00483 mxArray* ImageSet2cellArr(const ImageSet<T>& imset)
00484 {
00485 int num = imset.size();
00486 mxArray *result = mxCreateCellArray(1,&num);
00487
00488 for (int i = 0; i < num; ++i)
00489 mxSetCell(result,i,Image2mexArray(imset[i]));
00490
00491 return result;
00492 }
00493
00494
00495 template <class T>
00496 ImageSet<T> cellArr2ImageSet(const mxArray* arrptr)
00497 {
00498 if (!mxIsCell(arrptr)) mexFatal("cellArr2ImageSet: expected cell array");
00499
00500 int num = mxGetNumberOfElements(arrptr);
00501 ImageSet<T> result(num);
00502
00503 for (int i = 0; i < num; ++i)
00504 result[i] = mexArray2Image<T>(mxGetCell(arrptr,i));
00505
00506 return result;
00507 }
00508
00509
00510 template <class T>
00511 mxArray* ImageSetVec2cellArr(const std::vector< ImageSet<T> >& vec)
00512 {
00513 int dims[2],idx[2];
00514 dims[0] = vec.size();
00515 dims[1] = vec.size();
00516
00517 mxArray *result = mxCreateCellArray(2,dims);
00518
00519 for (idx[0] = 0; idx[0] < dims[0]; ++idx[0])
00520 for (idx[1] = 0; idx[1] < dims[1]; ++idx[1])
00521 {
00522 int sub = mxCalcSingleSubscript(result,2,idx);
00523 mxSetCell(result,sub,Image2mexArray(vec[idx[0]][idx[1]]));
00524 }
00525 return result;
00526 }
00527
00528
00529 template <class T>
00530 std::vector< ImageSet<T> > cellArr2ImageSetVec(const mxArray* arrptr)
00531 {
00532 if (!mxIsCell(arrptr)) mexFatal("arrPtr needs to be a 2D cell array.");
00533
00534 if (mxGetNumberOfDimensions(arrptr) == 1)
00535 {
00536 std::vector< ImageSet<T> > result(1);
00537 result[0] = cellArr2ImageSet<T>(arrptr);
00538 return result;
00539 }
00540 else if (mxGetNumberOfDimensions(arrptr) != 2)
00541 mexFatal("arrPtr needs to be a 2D cell array.");
00542
00543 int numSets = mxGetM(arrptr);
00544 int numImgs = mxGetN(arrptr);
00545 int idx[2];
00546
00547 std::vector< ImageSet<T> > result(numSets,ImageSet<T>(uint(numImgs)));
00548
00549 for (idx[0] = 0; idx[0] < numSets; ++idx[0])
00550 for (idx[1] = 0; idx[1] < numImgs; ++idx[1])
00551 {
00552 int sub = mxCalcSingleSubscript(arrptr,2,idx);
00553 result[idx[0]][idx[1]] = mexArray2Image<T>(mxGetCell(arrptr,sub));
00554 }
00555 return result;
00556 }
00557
00558
00559
00560
00561 MexReturn::MexReturn(int nlhs, mxArray **plhs)
00562 : itsNlhs(nlhs),
00563 itsPlhs(plhs)
00564 {}
00565
00566
00567 MexReturn::~MexReturn()
00568 {
00569 bool okay = true;
00570 for(int i = 0; i < itsNlhs; ++i)
00571 if (!itsPlhs[i])
00572 {
00573 mexError(sformat("Return argument %i is not assigned.",i+1));
00574 okay = false;
00575 }
00576
00577 if (!okay) mexFatal("There were unassigned return arguments.");
00578 }
00579
00580
00581 int MexReturn::numArgs()
00582 { return itsNlhs; }
00583
00584
00585 bool MexReturn::isNumOK(int num)
00586 { return ((num >= 0) && (num < numArgs())); }
00587
00588
00589 bool MexReturn::store(int num, mxArray *val)
00590 {
00591 if (!isNumOK(num)) return false;
00592 itsPlhs[num] = val;
00593 return true;
00594 }
00595
00596
00597 bool MexReturn::store(int num, double val)
00598 { return store(num,mxCreateScalarDouble(val)); }
00599
00600
00601 template <class T>
00602 bool MexReturn::store(int num, const std::vector<T>& val)
00603 {
00604 if (!isNumOK(num)) return false;
00605 return store(num,Vector2mexArr(val));
00606 }
00607
00608
00609 template <class T>
00610 bool MexReturn::store(int num, const Image<T>& val)
00611 {
00612 if (!isNumOK(num)) return false;
00613 return store(num,Image2mexArray(val));
00614 }
00615
00616
00617 template <class T>
00618 bool MexReturn::store(int num, const Image< PixRGB<T> >& val)
00619 {
00620 if (!isNumOK(num)) return false;
00621 return store(num,RGBImage2mexArray(val));
00622 }
00623
00624
00625
00626
00627 #define INSTANTIATE(T) \
00628 template Image<T> mexArray2Image(const mxArray* arrptr); \
00629 template Image< PixRGB<T> > mexArray2RGBImage(const mxArray* arrptr); \
00630 template mxArray* Image2mexArray(const Image<T>& img); \
00631 template mxArray* RGBImage2mexArray(const Image< PixRGB<T> >& img); \
00632 template mxArray* ImgVec2mexArr(const ImageSet<T>& vect); \
00633 template ImageSet<T> mexArr2ImgVec(const mxArray* arrptr); \
00634 template mxArray* ImageSet2cellArr(const ImageSet<T>& imset); \
00635 template ImageSet<T> cellArr2ImageSet(const mxArray* arrptr); \
00636 template mxArray* ImageSetVec2cellArr(const std::vector< ImageSet<T> >& vec); \
00637 template std::vector< ImageSet<T> > cellArr2ImageSetVec(const mxArray* arrptr); \
00638 template bool MexReturn::store(int num, const Image<T>& val); \
00639 template bool MexReturn::store(int num, const Image< PixRGB<T> >& val); \
00640
00641
00642 INSTANTIATE(byte);
00643 INSTANTIATE(float);
00644
00645
00646 template mxArray* Image2mexArray(const Image<double>& img);
00647
00648 #define INSTANTIATE2(T) \
00649 template std::vector<T> mexArr2Vector(const mxArray* vecptr, uint num_elements); \
00650 template std::vector<T> mexArr2Vector(const mxArray* vecptr); \
00651 template mxArray* Vector2mexArr(const std::vector<T>& vect, uint num_elements); \
00652 template mxArray* Vector2mexArr(const std::vector<T>& vect); \
00653 template bool MexReturn::store(int num, const std::vector<T>& val); \
00654
00655 INSTANTIATE2(byte);
00656 INSTANTIATE2(float);
00657 INSTANTIATE2(int);
00658 INSTANTIATE2(double);
00659
00660
00661
00662
00663
00664
00665