图形学-灰度变换

Photoshop里的灰度变换可以使R,G,B 3色按任何比例增强再混合,原理和下面的差不多。
黑白图片的黑白变换叫灰度变换,彩色图片的色彩变换也叫灰度变换,PhotoShop里叫色阶变换

一幅彩色图像的象素矩阵中每个象素由RGB 3种颜色按一定的比例混合形成一种颜色来表示,比如黑色使RGB(0,0,0) ,纯红色是RGB(0,1,0)...。在处理相片时,有时可能因为环境光源太暗,使RGB色的值偏小,就会使图形太暗看不清,如果环境光源太光,又使图像泛白,通过灰度变换,就可以使RGB值调和到合适的程度,使相片变得漂亮。

变换原理是这样的:
首先提取一幅图像的一个象素,在BMP格式中一个象素由8位红色亮度值,8位绿色亮度值和8位蓝色亮度值组成,只要按一定的变换函数去变换

这种3种颜色的亮度值就可以起到灰度变换的目的。

比如线性变换
可以用一个线性函数
f(x,y)=a'+(b'-a')/(b-a)×(f(x,y)-a)
f(x,y)代表一个象素
[a,b]是原始图像的灰度范围,[a',b']是变换后新图像的灰度范围
用这个线性函数分别对R,G,B分量进行变换可以起到单色增强的目的,然后再混合输出。
如果b'-a' > b-a ,则使得图像灰度范围增大,即对比度增大,图像会变得清晰
如果b'-a' < b-a ,则使得图像灰度范围缩小,即对比度减小。


分段线性变换
和线性变换差不多
不过对于单一一个R或G或B分量采用分段函数进行变换。

f(x,y)=a'+(b'-a')/(b-a)×(f(x,y)-a)    当f(x,y)在[a,b]范围内
f(x,y)=0                                           当f(x,y)<m
f(x,y)=255                                       当f(x,y)>n
这样就指定了一个变换段 a,b,只有灰度在a,b段内的点才会增强,灰度<a的编程黑色,>b的变成白色。

非线性变换
可以根据需要制定非线性函数对灰度进行变换,典型的有
对数变换
f(x,y)=a+ ln[f(x,y)+1]/(b×lnc) 这里a,b,c是参数而不是灰度范围了,对数变换用于扩展低灰度区
指数变换
f(x,y)=b^(c*[f(x,y)]-a]) ,a,b,c同样是参数,指数变换用来压缩低灰度区

下面用BCB实现一个对256色无压缩BMP图像的灰度变换

 

//-----------------------------------------BCB6程序----------------------------
#include <vcl.h>
#pragma hdrstop
#include<stdio.h>
#include "Unit1.h"
#include"File1.h"

#pragma pack(1)//----强制结构用1字节对齐
struct BITMAPFILEHEADER_
{
 short type;
        int bfSize;
 short re1,re2;
        int Offbits;
};

struct BITMAPINFO_
{
 long size;
 long width,height;
 short planes,bitCount;
 long comp,sizeImg;
 long xpels,ypels;
 long used,important;
};

//-------------将BMP彩色表的数据校正到BCB TColor的数据。
void SwitchColor(long &c)
{
        long blue=c&  0x000000ff;
        long green=c& 0x0000ff00;
        long red=c&   0x00ff0000;
        c=(blue<<16) | green | (red>>16);
}

//---------线性灰度变换,rr,gg,bb为增强系数
void strengthen (long &c,double rr,double gg,double bb)
{
      unsigned char r=(c & 0x00ff0000)>>16;
      unsigned char g=(c & 0x0000ff00)>>8;
      unsigned char b=(c & 0x000000ff);

      unsigned char nr;
      unsigned char ng;
      unsigned char nb;

      if(rr*r>255)
        nr=255;
      else
        nr=rr*r;

      if(gg*g>255)
        ng=255;
      else
        ng=gg*g;

      if(bb*b>255)
        nb=255;
      else
        nb=bb*b;

      c=(nr<<16) | (ng<<8) | (nb);
}
void xxx()
{
        FILE *f=fopen("F://FX3.bmp","rb");
        if(f==NULL)             /*判断文件是否打开成功*/
        {
             ShowMessage("File open error");
             return;
        }

        fseek(f,0,0);//移动到开头

        //----------读BMP文件头
        BITMAPFILEHEADER_ *bmph=new BITMAPFILEHEADER_();
        if(fread((char*)bmph,sizeof(BITMAPFILEHEADER_),1,f)==NULL)
        {
              ShowMessage("File read error");
             return;
        }

        //-----------读BMP信息头
        BITMAPINFO_ *bmpi=new BITMAPINFO_();
        if(fread((char*)bmpi,sizeof(BITMAPINFO_),1,f)==NULL)
        {
                ShowMessage("File read error2");
                return;
        }

        //--------------读彩色表
        long *c=new long[bmph->Offbits-sizeof(BITMAPFILEHEADER_)-sizeof(BITMAPINFO_)];
        fread((char*)c,bmph->Offbits-sizeof(BITMAPFILEHEADER_)-sizeof(BITMAPINFO_),1,f);

        //----------显示一些信息
        Form1->Edit1->Text=IntToStr(bmph->bfSize);
        Form1->Edit2->Text=IntToStr(bmpi->width);
        Form1->Edit3->Text=IntToStr(bmpi->height);
        Form1->Edit4->Text=IntToStr(bmpi->comp);
        Form1->Edit5->Text=IntToStr(bmpi->used);
        //------------显示图形
        unsigned char *p=new unsigned char[4];
        int i=0,j=0,k=0,wc=0;
        TColor *tc;
        if(bmpi->width%4==0)//-----------因为BMP图像4字节对齐
                wc=bmpi->width/4;
        else
                wc=bmpi->width/4+1;

        for( i=0;i<bmpi->height;i++)
        {
                for(j=0;j<wc;j++)
                {
                        fread(p,4,1,f);
                        for(k=0;k<4;k++)
                        {
                                long x=c[p[k]];
                                //--------这里开始增强色彩
                                strengthen(x,1.1,1.1,1.5); //1.1  1.1  和1.5  为RGB各分量的增强系数
                                //---------校正数据
                                SwitchColor(x);//----------因为BCB的TCOLOR和BMP的彩色表反了。
                                Form1->Canvas->Pixels[200+j*4+k][300-i]=x; //------200和300是定位到Canvas的中间而已。
                        }
                }
        }
        fclose(f);
};
对于要进行非线性变换或其他特殊的变换,只需要修改strengthen函数里的变换操作。
经过实际运行,变换效果不过~~~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值