From: Gordon L. K. <gl...@uc...> - 2012-12-04 06:07:13
|
Hi again, And now you can use "unu resample -s a" to do aspect-ratio preserving resampling. For example, to resample an RGB image so that the horizontal axis is 640 samples wide, and the vertical axis is resampled to whatever preserves the aspect ratio of the image, you'd use: "unu resample -s = 640 a". Since "unu resample" has undergone a number of improvements since the last release, I'm including the full usage info below. The -off, -min, and -max options are also relatively new. Gordon Begin forwarded message: > From: kin...@us... > Subject: [Teem-commit] SF.net SVN: teem:[5880] teem/trunk/src/unrrdu > Date: December 3, 2012 11:53:17 PM CST > To: tee...@li... > > Revision: 5880 > http://teem.svn.sourceforge.net/teem/?rev=5880&view=rev > Author: kindlmann > Date: 2012-12-04 05:53:16 +0000 (Tue, 04 Dec 2012) > Log Message: > ----------- > adding unu resample -s a for aspect-ratio-preserving resampling > > Modified Paths: > -------------- > teem/trunk/src/unrrdu/flotsam.c > teem/trunk/src/unrrdu/resample.c > teem/trunk/src/unrrdu/unrrdu.h > > Modified: teem/trunk/src/unrrdu/flotsam.c > =================================================================== > --- teem/trunk/src/unrrdu/flotsam.c 2012-12-03 08:36:19 UTC (rev 5879) > +++ teem/trunk/src/unrrdu/flotsam.c 2012-12-04 05:53:16 UTC (rev 5880) > @@ -334,6 +334,7 @@ > ** parse the strings used with "unu resample -s" to indicate > ** the new number of samples. > ** = : unrrduScaleNothing > +** a : unrrduScaleAspectRatio > ** x<float> : unrrduScaleMultiply > ** x=<float> : unrrduScaleMultiply > ** /<float> : unrrduScaleDivide > @@ -356,11 +357,10 @@ > if (!strcmp("=", str)) { > scale[0] = AIR_CAST(double, unrrduScaleNothing); > scale[1] = 0.0; > - return 0; > - } > - > - /* else */ > - if (strlen(str) > 2 > + } else if (!strcmp("a", str)) { > + scale[0] = AIR_CAST(double, unrrduScaleAspectRatio); > + scale[1] = 0.0; > + } else if (strlen(str) > 2 > && ('x' == str[0] || '/' == str[0]) > && '=' == str[1]) { > if (1 != sscanf(str+2, "%lf", scale+1)) { > > Modified: teem/trunk/src/unrrdu/resample.c > =================================================================== > --- teem/trunk/src/unrrdu/resample.c 2012-12-03 08:36:19 UTC (rev 5879) > +++ teem/trunk/src/unrrdu/resample.c 2012-12-04 05:53:16 UTC (rev 5880) > @@ -51,10 +51,11 @@ > int type, bb, pret, norenorm, neb, older, E, defaultCenter, > verbose, overrideCenter, minSet=AIR_FALSE, maxSet=AIR_FALSE, > offSet=AIR_FALSE; > - unsigned int scaleLen, ai, samplesOut, minLen, maxLen, offLen; > + unsigned int scaleLen, ai, samplesOut, minLen, maxLen, offLen, > + aspRatNum, nonAspRatNum, nonAspRatIdx; > airArray *mop; > double *scale; > - double padVal, *min, *max, *off; > + double padVal, *min, *max, *off, aspRatScl=AIR_NAN; > NrrdResampleInfo *info; > NrrdResampleContext *rsmc; > NrrdKernelSpec *unuk; > @@ -77,7 +78,11 @@ > "\b\bo \"/<float>\": divide number of samples by <float>\n " > "\b\bo \"+=<uint>\", \"-=<uint>\": add <uint> to or subtract " > "<uint> from number input samples to get number output samples\n " > - "\b\bo \"<uint>\": exact number of output samples", > + "\b\bo \"<uint>\": exact number of output samples\n " > + "\b\bo \"a\": resample this axis to whatever number of samples " > + "preserves the aspect ratio of other resampled axes. Currently " > + "needs to be used on all but one of the resampled axes, " > + "if at all. ", > &scaleLen, NULL, &unrrduHestScaleCB); > hestOptAdd(&opt, "off,offset", "off0", airTypeDouble, 0, -1, &off, "", > "For each axis, an offset or shift to the position (in index " > @@ -270,6 +275,29 @@ > airMopError(mop); > return 1; > } > + aspRatNum = nonAspRatNum = 0; > + for (ai=0; ai<nin->dim; ai++) { > + int dowhat = AIR_CAST(int, scale[0 + 2*ai]); > + if (!(unrrduScaleNothing == dowhat)) { > + if (unrrduScaleAspectRatio == dowhat) { > + aspRatNum++; > + } else { > + nonAspRatNum++; > + nonAspRatIdx = ai; > + } > + } > + } > + if (aspRatNum) { > + if (1 != nonAspRatNum) { > + fprintf(stderr, "%s: sorry, aspect-ratio-preserving " > + "resampling must currently be used on all but one " > + "(not %u) resampled axis, if any\n", me, > + nonAspRatNum); > + airMopError(mop); > + return 1; > + } > + } > + > rsmc = nrrdResampleContextNew(); > rsmc->verbose = verbose; > airMopAdd(mop, rsmc, (airMopper)nrrdResampleContextNix, airMopAlways); > @@ -315,6 +343,7 @@ > samplesOut = nin->axis[ai].size - incr; > break; > } > + aspRatScl = AIR_CAST(double, samplesOut)/nin->axis[ai].size; > if (!E) E |= nrrdResampleSamplesSet(rsmc, ai, samplesOut); > break; > case unrrduScaleExact: > @@ -324,8 +353,17 @@ > } > if (!E) E |= nrrdResampleKernelSet(rsmc, ai, unuk->kernel, unuk->parm); > samplesOut = (size_t)scale[1 + 2*ai]; > + aspRatScl = AIR_CAST(double, samplesOut)/nin->axis[ai].size; > if (!E) E |= nrrdResampleSamplesSet(rsmc, ai, samplesOut); > break; > + case unrrduScaleAspectRatio: > + /* wants aspect-ratio preserving, but may not know # samples yet */ > + if (defaultCenter && overrideCenter) { > + if (!E) E |= nrrdResampleOverrideCenterSet(rsmc, ai, defaultCenter); > + } > + if (!E) E |= nrrdResampleKernelSet(rsmc, ai, unuk->kernel, unuk->parm); > + /* will set samples later, after aspRatScl has been set */ > + break; > default: > fprintf(stderr, "%s: sorry, unrecognized unrrduScale value %d\n", > me, dowhat); > @@ -346,6 +384,21 @@ > } > } > } > + if (!E && aspRatNum) { > + if (!AIR_EXISTS(aspRatScl)) { > + fprintf(stderr, "%s: confusion, should have learned scaling " > + "of aspect-ratio-preserving resampling by now", me); > + airMopError(mop); > + return 1; > + } > + for (ai=0; ai<nin->dim; ai++) { > + int dowhat = AIR_CAST(int, scale[0 + 2*ai]); > + if (unrrduScaleAspectRatio == dowhat) { > + samplesOut = AIR_ROUNDUP(nin->axis[ai].size*aspRatScl); > + if (!E) E |= nrrdResampleSamplesSet(rsmc, ai, samplesOut); > + } > + } > + } > if (!E) E |= nrrdResampleBoundarySet(rsmc, bb); > if (!E) E |= nrrdResampleTypeOutSet(rsmc, type); > if (!E) E |= nrrdResamplePadValueSet(rsmc, padVal); > > Modified: teem/trunk/src/unrrdu/unrrdu.h > =================================================================== > --- teem/trunk/src/unrrdu/unrrdu.h 2012-12-03 08:36:19 UTC (rev 5879) > +++ teem/trunk/src/unrrdu/unrrdu.h 2012-12-04 05:53:16 UTC (rev 5880) > @@ -201,6 +201,7 @@ > unrrduScaleDivide, /* e.g. "/2" */ > unrrduScaleAdd, /* e.g. "+2" */ > unrrduScaleSubtract, /* e.g. "-2" */ > + unrrduScaleAspectRatio, /* "a" */ > unrrduScaleExact, /* e.g. "128" */ > unrrduScaleLast > }; unu resample: Filtering and {up,down}sampling with a separable kernel. Provides simplified access to nrrdSpatialResample() by assuming (among other things) that the same kernel is used for resampling every axis that is being resampled. Only required option is "-s" to specify which axes to resample and how many output samples to generate. Resampling kernel "-k" defaults to an interpolating cubic, but many other choices are available. Be default, resampling an axis resamples the full extent of its samples, but it is possible to offset this range via "-off", or to crop and/or pad via "-min" and "-max". The resampling respects the difference between cell- and node-centered data, but you can over-ride known centering with "-co". * Uses the many nrrdResample* functions operating on a nrrdResampleContext Usage: unu resample [-old] -s,--size <sz0 ...> [-off,--offset [<off0 ...>]] \ [-min,--minimum [<min0 ...>]] [-max,--maximum [<max0 ...>]] \ [-k,--kernel <kern>] [-nrn] [-ne,--nonexistent <behavior>] \ [-b,--boundary <behavior>] [-v,--value <value>] [-t,--type <type>] \ [-cheap] [-c,--center <center>] [-co,--center-override] [-verbose <v>] \ [-i,--input <nin>] [-o,--output <nout>] -old = instead of using the new nrrdResampleContext implementation, use the old nrrdSpatialResample implementation -s <sz0 ...> , --size <sz0 ...> = For each axis, information about how many samples in output: o "=": leave this axis completely untouched: no resampling whatsoever o "x<float>": multiply the number of input samples by <float>, and round to the nearest integer, to get the number of output samples. Use "x1" to resample the axis but leave the number of samples unchanged o "/<float>": divide number of samples by <float> o "+=<uint>", "-=<uint>": add <uint> to or subtract <uint> from number input samples to get number output samples o "<uint>": exact number of output samples o "a": resample this axis to whatever number of samples preserves the aspect ratio of other resampled axes. Currently needs to be used on all but one of the resampled axes, if at all. (1 or more sampling specifications) -off [<off0 ...>] , --offset [<off0 ...>] = For each axis, an offset or shift to the position (in index space) of the lower end of the sampling domain. Either -off can be used, or -min and -max together, or none of these (so that, by default, the full domain of the axis is resampled). (0 or more doubles); default: "" -min [<min0 ...>] , --minimum [<min0 ...>] = For each axis, the lower end (in index space) of the domain of the resampling. Either -off can be used, or -min and -max together, or none of these (so that, by default, the full domain of the axis is resampled). (0 or more doubles); default: "" -max [<max0 ...>] , --maximum [<max0 ...>] = For each axis, the upper end (in index space) of the domain of the resampling. Either -off can be used, or -min and -max together, or none of these, so that (by default), the full domain of the axis is resampled. (0 or more doubles); default: "" -k <kern> , --kernel <kern> = The kernel to use for resampling. Kernels logically live in the input index space for upsampling, and in the output index space for downsampling. Possibilities include: o "box": nearest neighbor interpolation on upsampling, and uniform averaging on downsampling o "cheap": nearest neighbor interpolation for upsampling, and non-blurring sub-sampling (pick subset of input samples) on downsampling o "tent": linear interpolation o "cubic:B,C": Mitchell/Netravali BC-family of cubics: "cubic:1,0": B-spline; maximal blurring "cubic:0,0.5": Catmull-Rom; good interpolating kernel o "c4h": 6-sample-support, C^4 continuous, accurate o "c4hai": discrete pre-filter to make c4h interpolate o "bspl3", "bspl5", "bspl7": cubic (same as cubic:1,0), quintic, and 7th order B-spline o "bspl3ai", "bspl5ai", "bspl7ai": discrete pre-filters to make bspl3, bspl5, bspl7 interpolate o "hann:R": Hann (cosine bell) windowed sinc, radius R o "black:R": Blackman windowed sinc, radius R o "gauss:S,C": Gaussian blurring, with standard deviation S and cut-off at C standard deviations o "dgauss:S,C": Lindeberg's discrete Gaussian. default: "cubic:0,0.5" -nrn = do NOT do per-pass kernel weight renormalization. Doing the renormalization is not a performance hit (hence is enabled by default), and the renormalization is sometimes needed to avoid "grating" on non-integral down-sampling. Disabling the renormalization is needed for correct results with artificially narrow kernels. -ne <behavior> , --nonexistent <behavior> = When resampling floating-point values, how to handle non-existent values within kernel support: o "noop": do nothing; let them pollute result o "renorm": ignore them and renormalize weights of existent values o "wght": ignore them and simply use weights of existent values default: "noop" -b <behavior> , --boundary <behavior> = How to handle samples beyond the input bounds: o "pad": use some specified value o "bleed": extend border values outward o "mirror": repeated reflections o "wrap": wrap-around to other side default: "bleed" -v <value> , --value <value> = for "pad" boundary behavior, pad with this value (double); default: "0.0" -t <type> , --type <type> = type to save OUTPUT as. By default (not using this option), the output type is the same as the input type; default: "default" -cheap = [DEPRECATED: the "-k cheap" option is the new (and more reliable) way to access this functionality. "-cheap" is only here for legacy use in combination with "-old".] When downsampling (reducing number of samples), don't try to do correct filtering by scaling kernel to match new (stretched) index space; keep it in old index space. When used in conjunction with "-k box", this can implement subsampling which chooses every Nth value. -c <center> , --center <center> = (not available with "-old") default centering of axes when input nrrd axes don't have a known centering: "cell" or "node" ; default: "cell" -co , --center-override = (not available with "-old") centering info specified via "-c" should *over-ride* known centering, rather than simply be used when centering is unknown. -verbose <v> = (not available with "-old") verbosity level (int); default: "0" -i <nin> , --input <nin> = input nrrd; default: "-" -o <nout> , --output <nout> = output nrrd (string); default: "-" |