resizeColor.cc 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. #include <math.h>
  2. #include <assert.h>
  3. #include <string.h>
  4. #include "mex.h"
  5. /*
  6. * Fast image subsampling.
  7. * This is used to construct the feature pyramid.
  8. */
  9. // struct used for caching interpolation values
  10. struct alphainfo {
  11. int si, di;
  12. double alpha;
  13. };
  14. // copy src into dst using pre-computed interpolation values
  15. void alphacopy(double *src, double *dst, struct alphainfo *ofs, int n) {
  16. struct alphainfo *end = ofs + n;
  17. while (ofs != end) {
  18. dst[ofs->di] += ofs->alpha * src[ofs->si];
  19. ofs++;
  20. }
  21. }
  22. // resize along each column
  23. // result is transposed, so we can apply it twice for a complete resize
  24. void resize1dtran(double *src, int sheight, double *dst, int dheight,
  25. int width, int chan) {
  26. double scale = (double)dheight/(double)sheight;
  27. double invscale = (double)sheight/(double)dheight;
  28. // we cache the interpolation values since they can be
  29. // shared among different columns
  30. int len = (int)ceil(dheight*invscale) + 2*dheight;
  31. alphainfo ofs[len];
  32. int k = 0;
  33. for (int dy = 0; dy < dheight; dy++) {
  34. double fsy1 = dy * invscale;
  35. double fsy2 = fsy1 + invscale;
  36. int sy1 = (int)ceil(fsy1);
  37. int sy2 = (int)floor(fsy2);
  38. if (sy1 - fsy1 > 1e-3) {
  39. assert(k < len);
  40. assert(sy-1 >= 0);
  41. ofs[k].di = dy*width;
  42. ofs[k].si = sy1-1;
  43. ofs[k++].alpha = (sy1 - fsy1) * scale;
  44. }
  45. for (int sy = sy1; sy < sy2; sy++) {
  46. assert(k < len);
  47. assert(sy < sheight);
  48. ofs[k].di = dy*width;
  49. ofs[k].si = sy;
  50. ofs[k++].alpha = scale;
  51. }
  52. if (fsy2 - sy2 > 1e-3) {
  53. assert(k < len);
  54. assert(sy2 < sheight);
  55. ofs[k].di = dy*width;
  56. ofs[k].si = sy2;
  57. ofs[k++].alpha = (fsy2 - sy2) * scale;
  58. }
  59. }
  60. // resize each column of each color channel
  61. bzero(dst, chan*width*dheight*sizeof(double));
  62. for (int c = 0; c < chan; c++) {
  63. for (int x = 0; x < width; x++) {
  64. double *s = src + c*width*sheight + x*sheight;
  65. double *d = dst + c*width*dheight + x;
  66. alphacopy(s, d, ofs, k);
  67. }
  68. }
  69. }
  70. // main function
  71. // takes a double color image and a scaling factor
  72. // returns resized image
  73. mxArray *resize(const mxArray *mxsrc, const mxArray *mxscale) {
  74. double *src = (double *)mxGetPr(mxsrc);
  75. const int *sdims = mxGetDimensions(mxsrc);
  76. if (mxGetNumberOfDimensions(mxsrc) != 3 ||
  77. mxGetClassID(mxsrc) != mxDOUBLE_CLASS)
  78. mexErrMsgTxt("Invalid input");
  79. double scale = mxGetScalar(mxscale);
  80. if (scale > 1)
  81. mexErrMsgTxt("Invalid scaling factor");
  82. int ddims[3];
  83. ddims[0] = (int)round(sdims[0]*scale);
  84. ddims[1] = (int)round(sdims[1]*scale);
  85. ddims[2] = sdims[2];
  86. mxArray *mxdst = mxCreateNumericArray(3, ddims, mxDOUBLE_CLASS, mxREAL);
  87. double *dst = (double *)mxGetPr(mxdst);
  88. double *tmp = (double *)mxCalloc(ddims[0]*sdims[1]*sdims[2], sizeof(double));
  89. resize1dtran(src, sdims[0], tmp, ddims[0], sdims[1], sdims[2]);
  90. resize1dtran(tmp, sdims[1], dst, ddims[1], ddims[0], sdims[2]);
  91. mxFree(tmp);
  92. return mxdst;
  93. }
  94. // matlab entry point
  95. // dst = resize(src, scale)
  96. // image should be color with double values
  97. void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
  98. if (nrhs != 2)
  99. mexErrMsgTxt("Wrong number of inputs");
  100. if (nlhs != 1)
  101. mexErrMsgTxt("Wrong number of outputs");
  102. plhs[0] = resize(prhs[0], prhs[1]);
  103. }