Linux中国 Linux中国门户站!
设为主页 设为主页
收藏本站 收藏本站
 
当前位置 :首页 ->编程语言 ->ViualBasic ->正文

VB图像处理之二次线性插值的应用

来源:Linuxdby.com 作者:Webmaster 时间:2007-06-05 点击: [收藏] [投稿]
上次讲到了用DIB方法来获取图像的像素。从这次开始将如果运用已经得到的像素来处理图像。

  图像插值放大的方法有很多,最主要的有二次线性插值和三次线性插值这两种。这次我把自己的程序中所用的二次线性插值的算法公布给大家,希望对各位要使用VB写类似程序的朋友有所帮助。

  程序中用到的API、数据类型、全局变量的定义请参考上一篇:《VB实现图像在数据库的存储与显示》

->PublicSubZoomImage(ByValOutPutWidthAsLong,ByValOutputHeightAsLong)
 DimIAsLong
 DimLAsLong
 DimXAsLong
 DimYAsLong
 DimXbAsLong
 DimYbAsLong
 DimXeAsLong
 DimYeAsLong
 DimMAsInteger
 DimNAsInteger
 DimCurRAsLong
 DimCurGAsLong
 DimCurBAsLong
 DimNxtRAsInteger
 DimNxtGAsInteger
 DimNxtBAsInteger
 DimDRAsSingle
 DimDGAsSingle
 DimDBAsSingle
 DimDRtAsSingle
 DimDGtAsSingle
 DimDBtAsSingle
 DimXratioAsSingle
 DimYratioAsSingle
 DimCurStepAsSingle
 DimNxtStepAsSingle
 DimNegNAsSingle

 OnErrorGoToErrLine
 IfNotCanZoomThenExitSub
 Done=False

 OutPutWid=OutPutWidth-1
 OutPutHei=OutputHeight-1
 I=(Bits\8)-1
 ReDimColTmp(I,InPutWid,OutPutHei)'先从Y方向进行缩放处理,结果保存在此中间数组内
 ReDimColOut(I,OutPutWid,OutPutHei)
 Xratio=OutPutWid/InPutWid
 Yratio=OutPutHei/InPutHei

 TimeZoom=timeGetTime

 NegN=1/Int(Yratio 1)
 ForX=0ToInPutWid
  CurR=ColVal(0,X,0)
  CurG=ColVal(1,X,0)
  CurB=ColVal(2,X,0)
  CurStep=0
  NxtStep=0
  ForY=0ToInPutHei-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)
   IfN>1Then
    DRt=(NxtR-CurR)*NegN
    DGt=(NxtG-CurG)*NegN
    DBt=(NxtB-CurB)*NegN
    DR=0
    DG=0
    DB=0
    ForL=Yb 1ToYe-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
   EndIf
   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)
 ForY=0ToOutPutHei
  CurR=ColTmp(0,0,Y)
  CurG=ColTmp(1,0,Y)
  CurB=ColTmp(2,0,Y)
  CurStep=0
  NxtStep=0
  ForX=0ToInPutWid-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)
   IfN>1Then
    DRt=(NxtR-CurR)*NegN
    DGt=(NxtG-CurG)*NegN
    DBt=(NxtB-CurB)*NegN
    DR=0
    DG=0
    DB=0
    ForL=Xb 1ToXe-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
   EndIf
   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
 ExitSub
ErrLine:
 MsgBoxErr.Description
EndSub->

  全局变量定义:

->DimColTmp()AsByte'用于保存插值中间变量
DimOutPutHeiAsLong'要插值的目标高度
DimOutPutWidAsLong'要插值的目标宽度
PublicTimeZoomAsLong'插值运算使用的时间->

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

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

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

->AB
CD->

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

->AabB
acabcdbd
CcdD->

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

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

->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的方法了。

->Aab1ab2B
ac1ab1cd11ab2cd21bd1
ac2ab1cd12ab2cd22bd2
Ccd1cd2D->

  推导:

->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;然后每一个新的点就是在前面那个点的值加上这个递增量就是了。

 如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<



上一篇:VB图像处理之几个常用滤镜的实现   下一篇:VB实现图像在数据库的存储与显示

文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论
更多相关文章
Power by linux-cn.com 粤ICP备05006655号