im2uint8函数分析
环境:Win7 64位 + Matlab R2010a
本次分析的函数为im2uint8,这个函数在图像处理中要用到,主要把图像数据类转换到uint8
uint8函数有效的输入的图像数据类为:logical,uint8,uint16,double,single和int16
- 如果输入类型为logical,则输入数据为1时转换为255,数据为0还是0。
- 如果输入类型为uint8,则输入数据保持不变。
- 如果输入类型为uint16,则输入数据除以255,然后四舍五入。
- 如果输入数据为double,则输入数据乘以255,小于0的数设置为0,大于255的数设置为255,其他的数四舍五入。
- 如果输入数据为single,处理方式和double一样。
- 如果输入数据为int16,处理暂且没弄清楚。
上面输出的结果根据Matlab提供的M文件进行分析,M文件如下
function u = im2uint8(varargin) %IM2UINT8 Convert image to 8-bit unsigned integers. % IM2UINT8 takes an image as input, and returns an image of class uint8. If % the input image is of class uint8, the output image is identical to it. If % the input image is not uint8, IM2UINT8 returns the equivalent image of class % uint8, rescaling or offsetting the data as necessary. % % I2 = IM2UINT8(I1) converts the intensity image I1 to uint8, rescaling the % data if necessary. % % RGB2 = IM2UINT8(RGB1) converts the truecolor image RGB1 to uint8, rescaling % the data if necessary. % % I = IM2UINT8(BW) converts the binary image BW to a uint8 intensity image, % changing one-valued elements to 255. % % X2 = IM2UINT8(X1,'indexed') converts the indexed image X1 to uint8, % offsetting the data if necessary. Note that it is not always possible to % convert an indexed image to uint8. If X1 is double, then the maximum value % of X1 must be 256 or less. If X1 is uint16, the maximum value of X1 must be % 255 or less. % % Class Support % ------------- % Intensity and truecolor images can be uint8, uint16, double, logical, % single, or int16. Indexed images can be uint8, uint16, double or % logical. Binary input images must be logical. The output image is uint8. % % Example % ------- % I1 = reshape(uint16(linspace(0,65535,25)),[5 5]) % I2 = im2uint8(I1) % % See also IM2DOUBLE, IM2INT16, IM2SINGLE, IM2UINT16, UINT8. % Copyright 1993-2004 The MathWorks, Inc. % $Revision: 1.20.4.5 $ $Date: 2005/11/15 00:58:23 $ iptchecknargin(1,2,nargin,mfilename); img = varargin{1}; iptcheckinput(img,{'double','logical','uint8','uint16','single','int16'}, ... {'nonsparse'},mfilename,'Image',1); if nargin == 2 typestr = varargin{2}; iptcheckstrs(typestr,{'indexed'},mfilename,'type',2); end % 如果图像类型为uint8,则不改变 if isa(img, 'uint8') u = img; % 如果图像类型为logical(二值),则将1转为255和0仍然为0 elseif isa(img, 'logical') u=uint8(img); u(img)=255; else %double, single, uint16, or int16 if nargin == 1 %输入参数个数为1 if isa(img, 'int16') %如果图像类型为int16,则将其转为int16--这是因为grayto8函数不支持int16 img = int16touint16(img); end % intensity image; call MEX-file u = grayto8(img); else %输入参数个数为2 if isa(img, 'int16') eid = sprintf('Images:%s:invalidIndexedImage',mfilename); msg1 = 'An indexed image can be uint8, uint16, double, single, or '; msg2 = 'logical.'; error(eid,'%s %s',msg1, msg2); elseif isa(img, 'uint16') if (max(img(:)) > 255) msg = 'Too many colors for 8-bit integer storage.'; eid = sprintf('Images:%s:tooManyColorsFor8bitStorage',mfilename); error(eid,msg); else u = uint8(img); end else %double or single 值范围1-256 if max(img(:)) >= 257 msg = 'Too many colors for 8-bit integer storage.'; eid = sprintf('Images:%s:tooManyColorsFor8bitStorage',mfilename); error(eid,msg); elseif min(img(:)) < 1 msg = 'Invalid indexed image: an index was less than 1.'; eid = sprintf('Images:%s:invalidIndexedImage',mfilename); error(eid,msg); else u = uint8(img-1); end end end end
这其中有个grayto8函数,这个函数在MEX文件中,具体源代码google找了一份,注释了一下
/* * GRAYTO8 MEX-file * * B = GRAYTO8(A) converts the double array A to uint8 by scaling A by 255 * and then rounding. NaN's in A are converted to 0. Values in A greater * than 1.0 are converted to 255; values less than 0.0 are converted to 0. * * B = GRAYTO8(A) converts the uint16 array A by scaling the elements of A * 255/65535, rounding, and then casting to uint8. * * Copyright 1993-2007 The MathWorks, Inc. * */ #include "mex.h" #include "math.h" #include "mwsize.h" // double类型转换 void ConvertFromDouble(double *pr, uint8_T *qr, mwSize numElements) { mwSize k; double val; for (k = 0; k < numElements; k++) { val = *pr++; if (mxIsNaN(val)) { *qr++ = 0; } else { val = val * 255.0 + 0.5; // 数据加0.5是为了四舍五入需要 例如 uint8(245.1+0.5)=245 和 uint8(245.6+0.5)=246 if (val > 255.0) val = 255.0; if (val < 0.0) val = 0.0; *qr++ = (uint8_T) val; } } } // single类型转换(处理方式和double类型一样) void ConvertFromSingle(float *pr, uint8_T *qr, mwSize numElements) { mwSize k; float val; for (k = 0; k < numElements; k++) { val = *pr++; if (mxIsNaN(val)) *qr++ = 0; else { val = val * 255.0f + 0.5f; if (val > 255.0) val = 255.0; if (val < 0.0) val = 0.0; *qr++ = (uint8_T) val; } } } // uint16类型转换 void ConvertFromUint16(uint16_T *pr, uint8_T *qr, mwSize numElements) { mwSize k; /* 除以257的原因来自于uint16数字映射到uint8 例如数字x转换到uint8 y = x*255/65535 由于257 = 65535/255,则y=x/257 */ double factor = 1.0 / 257.0; for (k = 0; k < numElements; k++) *qr++ = (uint8_T) ( (double) (*pr++) * factor + 0.5 ); } void ValidateInputs(int nrhs, const mxArray *prhs[]) { if (nrhs < 1) { mexErrMsgIdAndTxt("Images:grayto8:tooFewInputs", "%s","Too few input arguments."); } if (nrhs > 1) { mexErrMsgIdAndTxt("Images:grayto8:tooManyInputs", "%s","Too many input arguments."); } if (!mxIsDouble(prhs[0]) && !mxIsUint16(prhs[0]) && !mxIsSingle(prhs[0])) { mexErrMsgIdAndTxt("Images:grayto8:invalidType", "%s","Input must be double, single, or uint16."); } if (mxIsComplex(prhs[0])) { mexWarnMsgIdAndTxt("Images:grayto8:ignoringImaginaryPartOfInput", "%s","Ignoring imaginary part of input."); } } void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { uint8_T *qr; (void) nlhs; /* unused parameter */ ValidateInputs(nrhs, prhs); plhs[0] = mxCreateNumericArray(mxGetNumberOfDimensions(prhs[0]), mxGetDimensions(prhs[0]), mxUINT8_CLASS, mxREAL); qr = (uint8_T *) mxGetData(plhs[0]); if (mxIsDouble(prhs[0])) ConvertFromDouble((double *) mxGetData(prhs[0]), qr, mxGetNumberOfElements(prhs[0])); else if (mxIsUint16(prhs[0])) ConvertFromUint16((uint16_T *) mxGetData(prhs[0]), qr, mxGetNumberOfElements(prhs[0])); else ConvertFromSingle((float *) mxGetData(prhs[0]), qr, mxGetNumberOfElements(prhs[0])); }
posted on 2015-06-29 10:53 C Pointer 阅读(5327) 评论(0) 编辑 收藏 举报