分享
 
 
 

VB图像处理,(二)二次线性插值的应用

王朝c#·作者佚名  2006-12-17
窄屏简体版  字體: |||超大  

上次讲到了用DIB方法来获取图像的像素。从这次开始将如果运用已经得到的像素来处理图像。

图像插值放大的方法有很多,最主要的有二次线性插值和三次线性插值这两种。

这次我把自己的程序中所用的二次线性插值的算法公布给大家,希望对各位要使用VB写类似程序的朋友有所帮助。

程序中用到的API、数据类型、全局变量的定义请参考上一篇:

《VB图像处理,(一)像素的获取和输出 》

Public Sub ZoomImage(ByVal OutPutWidth As Long, ByVal OutputHeight As Long)

Dim I As Long

Dim L As Long

Dim X As Long

Dim Y As Long

Dim Xb As Long

Dim Yb As Long

Dim Xe As Long

Dim Ye As Long

Dim M As Integer

Dim N As Integer

Dim CurR As Long

Dim CurG As Long

Dim CurB As Long

Dim NxtR As Integer

Dim NxtG As Integer

Dim NxtB As Integer

Dim DR As Single

Dim DG As Single

Dim DB As Single

Dim DRt As Single

Dim DGt As Single

Dim DBt As Single

Dim Xratio As Single

Dim Yratio As Single

Dim CurStep As Single

Dim NxtStep As Single

Dim NegN As Single

On Error GoTo ErrLine

If Not CanZoom Then Exit Sub

Done = False

OutPutWid = OutPutWidth - 1

OutPutHei = OutputHeight - 1

I = (Bits \ 8) - 1

ReDim ColTmp(I, InPutWid, OutPutHei) '先从Y方向进行缩放处理,结果保存在此中间数组内

ReDim ColOut(I, OutPutWid, OutPutHei)

Xratio = OutPutWid / InPutWid

Yratio = OutPutHei / InPutHei

TimeZoom = timeGetTime

NegN = 1 / Int(Yratio + 1)

For X = 0 To InPutWid

CurR = ColVal(0, X, 0)

CurG = ColVal(1, X, 0)

CurB = ColVal(2, X, 0)

CurStep = 0

NxtStep = 0

For Y = 0 To InPutHei - 1

NxtStep = CurStep + Yratio

Yb = CurStep

Ye = NxtStep

N = Ye - Yb

ColTmp(0, X, Yb) = CurR

ColTmp(1, X, Yb) = CurG

ColTmp(2, X, Yb) = CurB

M = Y + 1

NxtR = ColVal(0, X, M)

NxtG = ColVal(1, X, M)

NxtB = ColVal(2, X, M)

If N > 1 Then

DRt = (NxtR - CurR) * NegN

DGt = (NxtG - CurG) * NegN

DBt = (NxtB - CurB) * NegN

DR = 0

DG = 0

DB = 0

For L = Yb + 1 To Ye - 1

DR = DR + DRt

DG = DG + DGt

DB = DB + DBt

ColTmp(0, X, L) = CurR + DR

ColTmp(1, X, L) = CurG + DG

ColTmp(2, X, L) = CurB + DB

Next

End If

CurStep = NxtStep

CurR = NxtR

CurG = NxtG

CurB = NxtB

Next

ColTmp(0, X, OutPutHei) = NxtR

ColTmp(1, X, OutPutHei) = NxtG

ColTmp(2, X, OutPutHei) = NxtB

Next

NegN = 1 / Int(Xratio + 1)

For Y = 0 To OutPutHei

CurR = ColTmp(0, 0, Y)

CurG = ColTmp(1, 0, Y)

CurB = ColTmp(2, 0, Y)

CurStep = 0

NxtStep = 0

For X = 0 To InPutWid - 1

NxtStep = CurStep + Xratio

Xb = CurStep

Xe = NxtStep

N = Xe - Xb

ColOut(0, Xb, Y) = CurR

ColOut(1, Xb, Y) = CurG

ColOut(2, Xb, Y) = CurB

M = X + 1

NxtR = ColTmp(0, M, Y)

NxtG = ColTmp(1, M, Y)

NxtB = ColTmp(2, M, Y)

If N > 1 Then

DRt = (NxtR - CurR) * NegN

DGt = (NxtG - CurG) * NegN

DBt = (NxtB - CurB) * NegN

DR = 0

DG = 0

DB = 0

For L = Xb + 1 To Xe - 1

DR = DR + DRt

DG = DG + DGt

DB = DB + DBt

ColOut(0, L, Y) = CurR + DR

ColOut(1, L, Y) = CurG + DG

ColOut(2, L, Y) = CurB + DB

Next

End If

CurStep = NxtStep

CurR = NxtR

CurG = NxtG

CurB = NxtB

Next

ColOut(0, OutPutWid, Y) = NxtR

ColOut(1, OutPutWid, Y) = NxtG

ColOut(2, OutPutWid, Y) = NxtB

Next

Done = True

TimeZoom = timeGetTime - TimeZoom

CanPut = True

Exit Sub

ErrLine:

MsgBox Err.Description

End Sub

全局变量定义:

Dim ColTmp() As Byte '用于保存插值中间变量

Dim OutPutHei As Long '要插值的目标高度

Dim OutPutWid As Long '要插值的目标宽度

Public TimeZoom As Long '插值运算使用的时间

简单解释一下关于二次线性插值算法。

(为了说明算法本身,我们只计算这个图片的红色分量,因为红绿蓝三种颜色的计算方法完全相同)

假设我们有一个很简单的图片,图片只有4个像素(2*2)

A B

C D

现在我们要把这个图片插值到9个像素:3*3

A ab B

ac abcd bd

C cd D

其中大写的字母代表原来的像素,小写字母代表插值得到的新像素。

想必看到这个图,大家心里已经有了这个算法了。

ab=(A+B) / 2

cd=(C+D) / 2

ac=(A+C) / 2

bd=(B+D) / 2

abcd=(ab+cd) / 2=(A+B+C+D) / 4

推导:ab= A + (B-A) / 2

cd=C +(D-C) / 2

...

很简单,对吧,先从一个方向把只涉及两个原始像素的新像素算出来。我们这里假定先计算水平方向。

而在算垂直方向的插值的时候,因为ab和cd已经在前面算好了,所以abcd的计算也和计算ac和bd没有任何区别了。

有可能为有朋友已经想到把原来的图像插值到4*4或5*5的方法了。

A ab1 ab2 B

ac1 ab1cd11 ab2cd21 bd1

ac2 ab1cd12 ab2cd22 bd2

C cd1 cd2 D

推导:ab1 = A + (B-A) * 1 / 3

ab2 = A + (B-A) * 2 / 3 =ab1+(B-A) / 3

cd1 = C + (D-C) * 1 / 3

cd1 = C + (D-C) * 2 / 3 =cd1+(D-C) / 3

...

以A和B为例,先求出原始像素的差(A-B)再算出每一步的递增量(A-B) / 3

然后每一个新的点就是在前面那个点的值加上这个递增量就是了。

这里我们假设A=100, B=255 放大倍率为3,水平方向插值

先计算出原始像素的差:(B-A) = 255-100 =155

再计算出水平方向每一步的递增量:(A-B) / 3=155 / 3 = 51.7

这里我们用一个变量DRt来记录这个递增量(这里只用红色来做例子)

ab1 = A + DRt = 100+51.7 =151

ab2 = ab1 + DRt = 151+51.7 = 202

好了,其实二次线性算法就是这么一个东西,并不复杂。

或许有写朋友会对于我给出的代码产生疑问。很简单的一个算法为什么要写这么多代码。

其实答案很简单:为了提高速度。

在VB中“+”和“-”永远是最快的,“*”要比“/”和“\”快。不论是什么类型的变量都是这样的。

下面再来分析一下我的程序。

在我的程序中把两个方向的插值分解成了两个单独的部分。

先把

A B

C D

变成:

A ab1...abN B

C cd1...cdN D

再变成

A ab1...abN B

ac1 ............. db1

... ............ ...

acN .............. bdN

C cd1...cdN D

这两个方向的插值算法完全相同

而Xratio 和Yratio 这两个变量则用来记录水平方向和垂直方向的放大倍率。

所以这个过程也能够让图像缩放不按照原始的纵横比进行。

好了,将这个模块和全局变量添加到上次建立的工程模块中。

把按钮中的代码改成:

sub command1_click()

With picture1

.ScaleMode=3

.BorderStyle=0

DibGet .hdc ,0 , 0 , .scalewidth , .scaleheight

ZoomImage , .scalewidth * 2 , .scaleheight * 2

End With

picture2.AutoRedraw=True

DibPut picture2.hdc

picture2.refresh

end sub

图像是否已经放大到原来的两倍了呢?速度不算很慢吧?

什么?很慢?先编译成EXE再运行吧。

关于二次线性插值就说到这里了,下一次将说一些基本的滤镜效果:锐化、柔化、扩散、雕刻

请大家继续关注

(这里只是说了我自己在写程序的时候用到的方法,存在很多的不足。并且因为在贴上来的时候作了部分修改,可能会存在部分错误,请各位高手不吝赐教,将您用到的更好的方法提供一下,我将不胜感激。)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有