原创 (原创)图像处理学习系列5:灰度操作1

2009-3-16 21:50 4297 8 10 分类: 软件与OS


    灰度操作,也可以说是对像素点的操作,虽然写了一些程序,对里面的道理还算明白,但是我觉得太过于直观化,图片处理的好不好完全是个人的看法(似乎图像的预处理都这样)。
    图像点的操作,很简单,一看就明白

   灰度变换的种类很多,线性变换,灰度拉伸,对数变换、幂次变换、窗口变换很多,但是总的来是都是把像素的值从一个值通过一定的关系变换到另外一个值。每种变换都有其用武之处:
窗口变换:对背景的处理,可以使用阈值变化的拓展,是像素小于某个值的时候为0 大于某个值的时候为255,中间的值时候不变
反转变换:可以改变图像的视觉效果
对数变换:减少图像的动态显示范围
幂次变换,又叫做伽玛变化,在监视器上有用,他的矫正曲线就是指数曲线,在指数值大于1和小于1,得到的结果相反,其次就是可以用作灰度变化,扩大和压缩都可以,只是系数不一样而已;注意的是:在做前面的变换的时候,要把像素归一化。
拉伸变换:有选择的改善输出tu图像,是分段线性变换的一种,如果图像集中在比较亮的区域,可以通过使斜率小于1,来改善。

总的来说对于图像点的操作,例如阈值变换,二值化,灰度变换都可以通过查找表来解决,而且这种方法可以通过改变查找表就可以了。
对于直方图的操作也可以通过对查找表的操作来实现
//**********************************************************************
//像素点操作(对灰度图片)
//图像信息头
//图像数据
//映射表   ,共有256个,用原有的数据作为索引,存储变换后的结果
//处理的有效区域,如果为NULL,对整个图片进行处理
//**********************************************************************
BOOL ImgOperateDot(BITMAPINFO* pbmpinfo,BYTE* pbmpdata,BYTE *map_table,CRect *valid_rect)
{

    LONG imagewidth=pbmpinfo->bmiHeader.biWidth;
    LONG imageheigth=pbmpinfo->bmiHeader.biHeight;    //data is not null

    //image size
    LONG  Linebyte =(pbmpinfo->bmiHeader.biBitCount * imagewidth +31)/32*4;
    LONG  ImageSize=Linebyte * imageheigth;

    LONG i=0,j=0,k=0,heigth=0,width=0;

    if (pbmpdata == NULL)
    {
        return FALSE;
    }
    //color must be gray
    if (pbmpinfo->bmiHeader.biBitCount != 8)
    {
        AfxMessageBox("只对灰度图像进行操作!");
        return FALSE;
    }
    ////////////////////
    BYTE *psrc=NULL;

    if (valid_rect == NULL)
    {
            for (heigth = 0 ; heigth < imageheigth  ;heigth++ )
            {
           
                for ( width = 0 ; width < imagewidth  ; width++)
                {
                           psrc  = (unsigned char *)pbmpdata+(ImageSize-Linebyte-heigth*Linebyte)+width;
                        *psrc = map_table[*psrc];
                }
            }
    }
    else
    {
        //处理范围检测
        ///////////////////////////////////
        if (valid_rect->left < 0 )
        {
            valid_rect->left = 0;
        }
        if (valid_rect->top < 0)
        {
            valid_rect->top = 0;
        }
        if (valid_rect->bottom > imageheigth)
        {
            valid_rect->bottom = imageheigth;
        }
       
        if (valid_rect->right > imagewidth)
        {
            valid_rect->right = imagewidth;
        }
       
    ////////////////////////////////////
        for (heigth = valid_rect->top ; heigth < valid_rect->bottom + 1  ;heigth++ )
        {
           
            for ( width = valid_rect->left ; width < valid_rect->right + 1; width++)
            {
                psrc  = (unsigned char *)pbmpdata+(ImageSize-Linebyte-heigth*Linebyte)+width;
                *psrc = map_table[*psrc];
            }
        }

    }
    return TRUE;


/*************************************************************
灰度变换
图片信息
图片数据
灰度变换的区域,如果为NULL,对全局进行处理
参数1    
参数2
参数3
参数4
参数5 操作方法
1、2个参数在线性变换f=a*src + b;
        窗口变化中的2个阈值
        拉伸变换中要变换的范围 srcxb srcxe
        对数变换中的系数   
        指数变化(伽玛变化)中的指数和系数
3,4参数是在拉伸变换中使用    destxs  destxe
灰度变化可以有很多种,要具体分析图片的灰度分布情况来使用不同的变换
//定于灰度操作类型
#define  IMG_GRAY_LINE        1
#define  IMG_GRAY_WINDOW      2
#define  IMG_GRAY_STRETCH     3
#define  IMG_GRAY_LOG         4
#define  IMG_GRAY_EXPONENTIAL 5
#define  IMG_GRAY_INV         6
***************************************************************/
BOOL ImgOperateGray(BITMAPINFO *pbmpinfo,BYTE *pbmpdata,CRect *valid_rect,float flag1,float flag2,int flag3,int flag4,int type)
{
    //图片信息
    LONG  imagewidth=pbmpinfo->bmiHeader.biWidth;
    LONG  imageheigth=pbmpinfo->bmiHeader.biHeight;
    LONG  Linebyte =( pbmpinfo->bmiHeader.biBitCount * imagewidth +31)/32*4;
    LONG  ImageSize=Linebyte * imageheigth;

    int i=0,j=0;
    //color must be gray
    if (pbmpinfo->bmiHeader.biBitCount != 8)
    {
        AfxMessageBox("只对灰度图像进行操作!");
        return FALSE;
    }
    ////////////////////
    //建立映射表
    BYTE map_table[256] = {0};
    //反变换 DEST = 255-SRC
    if (type==IMG_GRAY_INV)
    {
            for (i=0;i<256;i++)
            {
                    map_table = (BYTE)(255 - i);
            }
    }
    //线性变换 f=a*src + b;
    if (type==IMG_GRAY_LINE)
    {

        if (flag1 < 0)
        {
            flag1 =0;
        }
        if (flag2>255 || flag2 < -255)
        {
            return FALSE;
        }
        for (i=0;i<256;i++)
        {
            map_table = (BYTE)(flag1 * i + flag2);
        }

    }
    //窗口变化
    if (type==IMG_GRAY_WINDOW)
    {
        if (flag1 < 0 || flag2  > 255)
        {
            return FALSE;
        }

        for (i=0;    i<256;    i++)
        {
            map_table = i;

            if (i <= flag1)
            {
                map_table =0;
            }
            if (i >= flag2)
            {
                map_table = 255;
            } 
        }
    }
    //灰度拉伸
    if (type == IMG_GRAY_STRETCH)
    {
        int src_b  = (int)flag1;
        int src_e  = (int)flag2;
        int dest_b = flag3;
        int dest_e = flag4;
        
        if (src_b > src_e || src_e < 0 )
        {
            return FALSE;
        }
        if (dest_b > dest_e || dest_e < 0)
        {
            return FALSE;
        }
        for (i=0;    i<256;    i++)
        {
            if (i < src_b)
            {
                map_table =(BYTE) ( (dest_b * i)/src_b );
            }
            if (i >= src_b && i <= src_e)
            {
                map_table =(BYTE) ( (dest_e - src_e) * ( i - src_b)/(dest_b - src_b) + dest_b );
            }
            if (i > src_e)
            {
                map_table =(BYTE) ( (255-dest_e)*(i-src_e) /( 255 - src_e) + dest_e);
            }
       
        }

    }
    //对数变换
    if (type == IMG_GRAY_LOG)
    {
             //
    }
    //指数变换
    if (type == IMG_GRAY_EXPONENTIAL)
    {
          if (flag1 < 0)
          {
              flag1 = 1;
          }
          if (flag2 == 0)
          {
              flag2 =1;
          }

          float temp = 0;

          for (i=0;i<256;i++)
          {
              temp = (float)pow((float)((float)i / (float)255),flag1);
              map_table = (BYTE)(flag2 * temp*255) ;
          }             
    }
    if (!ImgOperateDot(pbmpinfo,pbmpdata,map_table,valid_rect))
    {
          return FALSE;
    }
   
    ///////////////////////////////////
    return TRUE;

文章评论2条评论)

登录后参与讨论

zhangshaobing517_935512703 2009-4-1 13:53

网上不是挺多的吗?介绍图像处理的书基本都会讲的

用户190621 2009-4-1 12:47

问一下,我现在做毕业设计,可以到哪里找到一些关于灰度处理的文章?
相关推荐阅读
zhangshaobing517_935512703 2011-03-21 01:28
KC24RT-300调试笔记
项目中需要使用LED驱动器,主要是为了让一串LED发出的光照一致,所以在试验中采用LED串联的方式比较好点,LED并联容易导致LED发光的 不均匀以及寿命减少。我在项目中采用金升阳公司的KC24RT-...
zhangshaobing517_935512703 2010-11-19 14:53
线程中CreateEvent和SetEvent及WaitForSingleObj
首先介绍CreateEvent是创建windows事件的意思,作用主要用在判断线程退出,程锁定方面.CreateEvent 函功能描述:创建或打开一个命名的或无名的事件对象.EVENT有两种状态:发信...
zhangshaobing517_935512703 2010-11-15 13:29
VS2008 BEGIN
Visual Studio 2008环境与VC6.0的环境存在着比较大的区别,下面就一些小小的区别在这里做一些探讨,欢迎指教!1、如果是调试控制台程序,很多时候点击“启动调试”后是一闪而过,此时可有两...
zhangshaobing517_935512703 2010-11-01 20:38
使用MFC的数组类
 MFC的数组类支持的数组类似于C++中的常规数组,可以存放任何数据类型。C++的常规数组在使用前必须将其定义成能够容纳所有可能需要的元素,而MFC数组类创建的对象可以根据需要动态地增大或减小,数组的...
zhangshaobing517_935512703 2010-09-07 13:14
循环
 循环设计的注意的事情:(1)双重循环的跳出问题,break只挑出所在的循环,如果使用双层FOR循环,单个BREAK就不可能跳出所有的双层(2)在迭代的时候,注意起始和终止的条件,尤其是终止问题(3)...
zhangshaobing517_935512703 2010-09-02 01:09
图像处理改进
1.特征点提取的算法  标志点的提取算法对结果的影响虽然没有经过试验或者计算的推算,每1个pix的偏差对结果的影响有多大,但是不可避免的,要想获得高精度的  测量结果,高精度的提取对结果的影响还是很大...
我要评论
2
8
关闭 站长推荐上一条 /2 下一条