当前位置: 首页 > news >正文

图像的处理(一)----灰度图像像素颜色亮度处理

以前看了一些有关图像处理的书,对我起到了很大的帮助。所以,今天我就将我学过的知识整理出来,一方面可以给人学习,另一方面也可以请各位高手指点指点。

我要说的图像处理是针对程序方面的。所以,先做一个程序来放置图形。在这里,我使用了Delphi作为工具。因为,在我使用过的众多编译器当中,Delphi对图形的支持最好。还有,这里我并不是讲语法。所以,有些代码我就不详细说明。不便之处,敬请原谅。

注意:本文章的示例程序所用的东西不超过GDI的范围。

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

在图像处理中,速度是很重要的。因此,我们得重新处理一下TBitmap,得到TVczhBitmap。这只是因为GetPixelsSetPixels的速度太慢,换一个方法而已。

unit untBitmapProc;

interface

uses Graphics, SysUtils;

type

TVczhBitmap=class(TBitmap)

private

Data:PByteArray;

Line:Integer;

procedure SetFormat;

function GetBytePointer(X,Y:Integer):PByte;

procedure SetBytes(X,Y:Integer;Value:Byte);

function GetBytes(X,Y:Integer):Byte;

protected

published

constructor Create;

public

property Bytes[X,Y:Integer]:Byte read GetBytes write SetBytes;

procedure LoadFromFile(FileName:String);

procedure ToGray;

end;

implementation

procedure TVczhBitmap.SetFormat;

begin

HandleType:=bmDIB;

PixelFormat:=pf24bit;

end;

function TVczhBitmap.GetBytePointer(X,Y:Integer):PByte;

begin

if Line<>Y then

begin

Line:=Y;

Data:=ScanLine[Y];

end;

Longint(result):=Longint(Data)+X;

end;

procedure TVczhBitmap.SetBytes(X,Y:Integer;Value:Byte);

begin

GetBytePointer(X,Y)^:=Value;

end;

function TVczhBitmap.GetBytes(X,Y:Integer):Byte;

begin

result:=GetBytePointer(X,Y)^;

end;

constructor TVczhBitmap.Create;

begin

inherited Create;

SetFormat;

Line:=-1;

end;

procedure TVczhBitmap.LoadFromFile(FileName:String);

begin

inherited LoadFromFile(FileName);

SetFormat;

Line:=-1;

end;

procedure TVczhBitmap.ToGray;

var X,Y,R:Integer;

B:Byte;

begin

for Y:=0 to Height-1 do

for X:=0 to Width-1 do

begin

R:=0;

for B:=0 to 2 do

R:=R+GetBytes(X*3+B,Y);

for B:=0 to 2 do

SetBytes(X*3+B,Y,R div 3);

end;

end;

end.

此后,我们需要建立几个窗体。第一个用来显示图片,第二个用来处理图片,其他的窗体都继承自第二个窗体,包含实际的处理方法。

先看第二个窗口:

unit untProc;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, ExtCtrls, untBitmapProc, StdCtrls, ComCtrls;

type

TfrmProcessor = class(TForm)

pbBar: TPaintBox;

gpProc: TGroupBox;

Button1: TButton;

procedure FormCreate(Sender: TObject);

procedure FormDestroy(Sender: TObject);

procedure FormShow(Sender: TObject);

procedure pbBarPaint(Sender: TObject);

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

BarData:array[0..255]of Byte;

Bar:TVczhBitmap;

procedure DrawBar;

end;

var

frmProcessor: TfrmProcessor;

implementation

{$R *.dfm}

uses untViewer;

procedure TfrmProcessor.DrawBar;

var I:Integer;

begin

Bar.Canvas.FillRect(Bar.Canvas.ClipRect);

Bar.Canvas.MoveTo(0,255-BarData[0]);

for I:=1 to 255 do

Bar.Canvas.LineTo(I,255-BarData[I]);

end;

procedure TfrmProcessor.FormCreate(Sender: TObject);

begin

Bar:=TVczhBitmap.Create;

Bar.Width:=256;

Bar.Height:=256;

Bar.Canvas.Brush.Color:=clWhite;

Bar.Canvas.Brush.Style:=bsSolid;

end;

procedure TfrmProcessor.FormDestroy(Sender: TObject);

begin

Bar.Free;

end;

procedure TfrmProcessor.FormShow(Sender: TObject);

var I:Integer;

begin

for I:=0 to 255 do

BarData[I]:=I;

DrawBar;

end;

procedure TfrmProcessor.pbBarPaint(Sender: TObject);

begin

pbBar.Canvas.Draw(0,0,Bar);

end;

procedure TfrmProcessor.Button1Click(Sender: TObject);

var X,Y:Integer;

begin

for Y:=0 to Buffer.Height-1 do

for X:=0 to Buffer.Width*3-1 do

Played.Bytes[X,Y]:=BarData[Buffer.Bytes[X,Y]];

frmViewer.FormPaint(frmViewer);

end;

end.

之后,做一个窗口继承自它,则调整BarData[]后,按Apply即可看到结果。

现在开始将图像处理。具体效果见示例程序。

一、颜色反转。

灰度图像的颜色都是从0~255,所以,为了使颜色反转,我们可以用255减去该颜色值以得到反转后的颜色。

var I:Integer;

begin

inherited;

for I:=0 to 255 do

BarData[I]:=255-I;//255减去该颜色值

DrawBar;

pbBarPaint(pbBar);

end;

二、缩小颜色范围以增强或减弱亮度

颜色本来是从0~255的。如果调节它的范围,例如从0~16,则会是图像明显变暗。我们可以把起始值设为a,把终止值设为b,则新的颜色值New=a+(b-1)*Old/255。这样做的话可以改变亮度,并且不会破坏原先颜色的顺序。代码如下

var I:Integer;

begin

for I:=0 to 255 do

BarData[I]:=(255-sbMin.Position)+Round((sbMin.Position-sbMax.Position)/255*I);

DrawBar;

pbBarPaint(pbBar);

Button1Click(Button1);

end;

这里的sbMin.PositionsbMaxPosition都是反转过的。所以使用时要用255去减

三、增加某个范围内的颜色范围

如果图像本身的颜色范围很小的画,你可以通过这种方法来加大图像的对比度,有利于对图像的分析。具体做法:

选取一个值a做为起始值,选取一个值b做为终止值,然后按以下公式变形:

| 0 (X<=a)

f(X)= | 255/(b-a)*(X-a)

| 255(X>=b)

var I:Integer;

begin

for I:=0 to 255 do

begin

if I<=sbMin.Position then

BarData[I]:=0

else if I>=sbMax.Position then

BarData[I]:=255

else

BarData[I]:=Round(255/(sbMax.Position-sbMin.Position)*(I-sbMin.Position));

end;

DrawBar;

pbBarPaint(pbBar);

Button1Click(Button1);

end;

四、变为黑白图片

在使用第三个功能的时候,你会发现当b<=a时,图像上的颜色除了黑色就是白色。这样操作的好处是不能直接显示出来的。这只要到了比较高级的图像处理如边缘检测等,才有作用。本例可以拿第三种方法的公式再变形,因此不作详细阐述。

五、指数级亮度调整

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><group id="_x0000_s1026" style="MARGIN-TOP: 7.8pt; Z-INDEX: 1; LEFT: 0px; MARGIN-LEFT: 18pt; WIDTH: 180pt; POSITION: absolute; HEIGHT: 156pt; TEXT-ALIGN: left" wrapcoords="-180 208 -450 935 -180 21704 20520 22119 20970 22119 21510 21808 21870 21185 540 20146 990 18485 1350 16823 1800 15162 2970 11838 4500 8515 5490 6854 7020 5192 9360 3531 14220 1869 20790 1142 20520 935 180 208 -180 208" coordsize="3600,3120" coordorigin="2340,5652"><line id="_x0000_s1027" style="POSITION: absolute; flip: y; mso-wrap-edited: f" wrapcoords="0 0 0 19938 0 20458 0 21600 0 21600 0 21600 0 21185 0 20562 0 19938 0 0 0 0" to="2340,8772" from="2340,5652"><stroke endarrow="block"></stroke></line><line id="_x0000_s1028" style="POSITION: absolute; mso-wrap-edited: f" wrapcoords="20520 0 -90 0 -90 0 20520 0 20970 0 21690 0 21690 0 21060 0 20520 0" to="5940,8772" from="2340,8772"><stroke endarrow="block"></stroke></line><shape id="_x0000_s1029" style="LEFT: 2340px; WIDTH: 3420px; POSITION: absolute; TOP: 5808px; HEIGHT: 2964px; mso-wrap-edited: f" wrapcoords="3300 0 2805 30 1770 180 1770 240 1605 299 1245 464 960 719 885 808 765 958 600 1198 375 1677 60 2635 0 2874 -15 2964 1725 2964 1725 2874 30 2874 30 2635 1725 2635 195 2395 345 1916 675 1198 1035 719 1335 479 1845 240 3450 15 3450 0 3300 0" coordsize="3420,2964" filled="f" path="m,2964c255,2041,510,1118,1080,624,1650,130,2535,65,3420,e"><path arrowok="t"></path></shape><?xml:namespace prefix = w ns = "urn:schemas-microsoft-com:office:word" /><wrap type="tight"></wrap></group>

我们假设这个图的定义域是[0,1],值域也是[0,1]。那么,定义函数f(x)=x^c,则f(x)的图像有一段如上图。我们再用鼠标操作时,可以在上面取一点P(a,b),然后使f(x)通过点P,则c=ln(b)/ln(a)。有了c之后,我们就可以对颜色进行操作了:

New=(Old/255)^c*255=exp(ln(old/255)*c)*255

var ea,eb,ec:Extended;

I:Integer;

begin

ea:=A/255;

eb:=B/255;

ec:=Ln(eb)/Ln(ea);

for I:=1 to 255 do

BarData[I]:=Round(Exp(Ln((I/255))*ec)*255);

DrawBar;

pbBarPaint(pbBar);

Button1Click(Button1);

end;

这样做可以调节图像的亮度。

先到这里,在下一篇文章中,我会向大家整理出彩色图像亮度调整的方法。

示例程序:http://vczh.cstc.net.cn/vczh/Article/A_Files/Gray256.rar 打开后按右键弹菜单

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 重要的 NLP 任务总结与20本最佳深度学习书籍[附带源码]
  • CSDNBlog使用方法(非官方,持续更新)(已更新二次)
  • NLP模型笔记2022-01:浅谈语言模型
  • 发文庆祝,俺上榜了!
  • NLP模型笔记2022-02:关于规则与语料对语言模型的理解
  • NLP模型笔记2022-03:简单理解nlp句法分析
  • 嘻嘻,感谢阿好!
  • NLP模型笔记2022-04:一个简单案例理解语言模型预测句子的原理
  • 呵呵,添加照片成功
  • NLP模型笔记2022-05:实体识别与句法分析实战
  • 什么是博客?
  • 【博士论文】使用压缩表示的 中文分词词性标注研究
  • python使用技巧(二十八):判断并计算列表不同数据类型的基数
  • 几个logo多多和免费计数器的网址
  • NLP模型笔记2022-06:pyhanlp加载训练完的语言模型路径进行预测
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • Debian下无root权限使用Python访问Oracle
  • ES6简单总结(搭配简单的讲解和小案例)
  • HashMap ConcurrentHashMap
  • Javascript Math对象和Date对象常用方法详解
  • JS学习笔记——闭包
  • Linux gpio口使用方法
  • mongodb--安装和初步使用教程
  • Octave 入门
  • SpiderData 2019年2月25日 DApp数据排行榜
  • spring security oauth2 password授权模式
  • 订阅Forge Viewer所有的事件
  • 缓存与缓冲
  • 将回调地狱按在地上摩擦的Promise
  • 目录与文件属性:编写ls
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 如何邀请好友注册您的网站(模拟百度网盘)
  • 入门到放弃node系列之Hello Word篇
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 消息队列系列二(IOT中消息队列的应用)
  • 掌握面试——弹出框的实现(一道题中包含布局/js设计模式)
  • 不要一棍子打翻所有黑盒模型,其实可以让它们发挥作用 ...
  • ## 1.3.Git命令
  • ######## golang各章节终篇索引 ########
  • #《AI中文版》V3 第 1 章 概述
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (不用互三)AI绘画工具应该如何选择
  • (规划)24届春招和25届暑假实习路线准备规划
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • (全注解开发)学习Spring-MVC的第三天
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • (一)SvelteKit教程:hello world
  • (一)基于IDEA的JAVA基础1
  • **python多态
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法
  • .bat批处理(八):各种形式的变量%0、%i、%%i、var、%var%、!var!的含义和区别