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]));

}
时间: 2024-08-03 15:57:54

im2uint8函数分析的相关文章

linux C函数之strdup函数分析

一.函数分析 1.函数原型: #include <string.h>char *strdup(const char *s); 2.功能: strdup()函数主要是拷贝字符串s的一个副本,由函数返回值返回,这个副本有自己的内存空间,和s没有关联.strdup函数复制一个字符串,使用完后,要使用delete函数删除在函数中动态申请的内存,strdup函数的参数不能为NULL,一旦为NULL,就会报段错误,因为该函数包括了strlen函数,而该函数参数不能是NULL. 3.strdup函数实现 c

如何验证一个地址可否使用—— MmIsAddressValid函数分析

又是一篇内核函数分析的博文,我个人觉得Windows的内核是最好的老师,当你想实现一个功能之前可以看看Windows内核是怎么做的,说不定就有灵感呢:) 首先看下官方的注释说明: /*++ Routine Description: For a given virtual address this function returns TRUE if no page fault will occur for a read operation on the address, FALSE otherwis

page_address()函数分析--如何通过page取得虚拟地址

由于X86平台上面,内存是划分为低端内存和高端内存的,所以在两个区域内的page查找对应的虚拟地址是不一样的. 一. x86上关于page_address()函数的定义 在include/linux/mm.h里面,有对page_address()函数的三种宏定义,主要依赖于不同的平台: 首先来看看几个宏的定义:CONFIG_HIGHMEM:顾名思义,就是是否支持高端内存,可以查看config文件,一般推荐内存超过896M的时候,才配置为支持高端内存.WANT_PAGE_VIRTUAL:X86平台

Oracle官网JNI简介和接口函数分析

第一章 概述 本章主要介绍JNI(Java Native Interface),JNI是一种本地编程接口.它允许运行在JAVA虚拟机中的JAVA代码和用其他编程语言,诸如C语言.C++.汇编,写的应用和库之间的交互操作. JNI的最大优势在于没有强加任何限制在JAVA虚拟机的下层实现上,因此,JAVA虚拟机供应商能够提供JNI的支持而不影响虚拟机的其他部分,程序员只需写出一个版本的本地应用和库,就可使之运行在一切支持JNI的JAVA虚拟机上. 本章包含了以下的要点: ? JNI概述 ? 目标 ?

linux 内核移植(七)——rest_init函数分析

代码在start_kernel函数运行的最后到了rest_init()函数中 1:rest_init()函数分析 (1)rest_init中调用kernel_thread函数启动了2个内核线程,分别是:kernel_init和kthreadd (2)调用schedule函数开启了内核的调度系统,从此linux系统开始转起来了. (3)rest_init最终调用cpu_idle函数结束了整个内核的启动.也就是说linux内核最终结束了一个函数cpu_idle.这个函数里面肯定是死循环. (4)简单

如何验证一个地址可否使用——MmIsAddressValid函数分析

又是一篇内核函数分析的博文,我个人觉得Windows的内核是最好的老师,当你想实现一个功能之前可以看看Windows内核是怎么做的,说不定就有灵感呢:) 首先看下官方的注释说明: /*++ Routine Description: For a given virtual address this function returns TRUE if no page fault will occur for a read operation on the address, FALSE otherwis

Linux-0.11内核内存管理get_free_page()函数分析

/* *Author : DavidLin*Date : 2014-11-11pm*Email : [email protected] or [email protected]*world : the city of SZ, in China*Ver : 000.000.001*history : editor time do 1)LinPeng 2014-11-11 created this file! 2)*/Linux-0.11内存管理模块是源代码中比较难以理解的部分,现在把笔者个人的理解

Linux-0.11内核源代码分析系列:内存管理get_free_page()函数分析

Linux-0.11内存管理模块是源码中比較难以理解的部分,如今把笔者个人的理解发表 先发Linux-0.11内核内存管理get_free_page()函数分析 有时间再写其它函数或者文件的:) /*  *Author  : DavidLin  *Date    : 2014-11-11pm  *Email   : [email protected] or [email protected]  *world   : the city of SZ, in China  *Ver     : 000

string函数分析

string函数分析string函数包含在string.c文件中,经常被C文件使用.1. strcpy函数原型: char* strcpy(char* str1,char* str2);函数功能: 把str2指向的字符串拷贝到str1中去函数返回: 返回str1,即指向str1的指针 /** * strcpy - Copy a %NUL terminated string * @dest: Where to copy the string to * @src: Where to copy the