prrsw的个人博客分享 http://blog.sciencenet.cn/u/prrsw

博文

Visual Basic与图像处理15

已有 2774 次阅读 2012-10-11 16:12 |系统分类:教学心得|关键词:学者| Visual, Basic与图像处理

Visual Basic与图像处理(三)

通过动态数组减少Point方法的使用次数,可以有效的提高图像处理的速度,C系列语言之所以在处理图像的时候速度较快,其实很大原因就是因为是从内存中直接读取图像数据。如果能完全放弃使用PointPSet方法,直接获得图像数据,那么Visual BasicC系列语言处理图像的速度并无明显差异,一种方法是直接读取文件的方法,对于初学者,还是不建议使用,因此没有必要,如果需要可以直接参考文件读取和写入的方法即可。这里推荐一种通过API函数直接完成图像读写的方法,主要涉及这样几个API函数:

(1)    PictureBox读入图像数据到数组中,用于取代Point方法。

Declare Function GetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long

(2)    将数组数据直接映射到PictureBox中,用于取代PSet方法。

Declare Function SetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long

(3)    获得控件句柄

Declare Function GetObject Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long

 

为了便于对图像进行操作,自定义了一个数据类型BIPMAP,定义如下:

Type BITMAP

    bmType As Long

    bmWidth As Long

    bmHeight As Long

    bmWidthBytes As Long

    bmPlanes As Integer

    bmBitsPixel As Integer

    bmBits As Long

End Type

 

上述API函数定义和自定义变量都放置于标准模块之中。

 

在获取图像数据时,首先定义一个整型变量用于存放PictureBox中的图像句柄,然后调用GetBitmapBits函数获取图像数据,存放于数组中,需要注意的时,Visual Basic获得的数据都默认为彩色图像,因此定义数组大小时,需要按照真彩色图像进行处理。将读取图像按钮代码做调整,使得读入图像的同时就获得图像数据,代码调整如下:

Private Sub cmdReadImage_Click()

    Dim strFileName As String

    CDialog1.Filter = "bmp|*.bmp|jpg|*.jpg|gif|*.gif"  '文件过滤,可以打开上述三类图像

    CDialog1.ShowOpen

    If CDialog1.FileName <> "" Then

        strFileName = CDialog1.FileName

        PicSource.Picture = LoadPicture(strFileName)

    End If

    SourceImHeight = PicSource.Height

    SourceImWidth = PicSource.Width

   

   

    Dim tSBmpInfo As BITMAP

    Dim hSrcBmp As Long

    Dim x As Integer, y As Integer

   

    hSrcBmp = PicSource.Image.Handle '注意,这里只能使用image,而不能使用picture

   

    '获得位图信息

    Call GetObject(hSrcBmp, Len(tSBmpInfo), tSBmpInfo)

    ReDim ImageArray(1 To tSBmpInfo.bmWidthBytes, 1 To SourceImHeight) As Byte

       

    '获得源图与目标图二进制位

    Call GetBitmapBits(hSrcBmp, tSBmpInfo.bmWidthBytes * tSBmpInfo.bmHeight, ImageArray(1, 1)) '注意起点是(1,1)

       

    ReDim sbits(SourceImHeight - 1, SourceImWidth - 1, 2) As Byte '通过下面的转换,将数组转置为习惯的格式,当然也可以不转置,只是后面使用起来比较麻烦

  

    For y = 1 To SourceImHeight

        For x = 1 To SourceImWidth

            sbits(y - 1, x - 1, 2) = ImageArray((x - 1) * 4 + 1, y)

            sbits(y - 1, x - 1, 1) = ImageArray((x - 1) * 4 + 2, y)

            sbits(y - 1, x - 1, 0) = ImageArray((x - 1) * 4 + 3, y)

        Next x

    Next y

   

End Sub

 

在处理程序时,同样定义动态数组用于存储目标图像数据,处理完成后再利用SetBitmapBits一次性将数组显示于目标的PictureBox控件之中,同样以直方图均衡化为例,对应的“直方图均衡化按钮代码调整如下:

Private Sub cmdGrayEqua_Click()

    Dim i As Integer, j As Integer

    Dim PixelValue As Long

    Dim r As Integer, g As Integer, b As Integer

    Dim GrayValue As Integer

   

    Dim Hist(255) As Long '存放原直方图统计结果

    Dim P(255) As Single '存放原直方图概率

    Dim PA(255) As Single '存放原直方图累计分布概率

    Dim Map(255) As Single '存放灰度等级映射结果

   

   

    Dim NGrayValue As Integer

 

 

     '设置目标图像的高度和宽度

    DestImHeight = SourceImHeight

    DestImWidth = SourceImWidth

   

    '设置目标PictureBox的大小

    PicDest.Height = DestImHeight

    PicDest.Width = DestImWidth

     

    ReDim dbits(DestImHeight - 1, DestImWidth - 1, 2) As Byte '重新定义目标数组的维数

   

    '图像的直方图统计

    For i = 0 To SourceImHeight - 1

        For j = 0 To SourceImWidth - 1

               r = sbits(i, j, 0)

               g = sbits(i, j, 1)

               b = sbits(i, j, 2)

              '插入图像处理的过程,对r, g, b进行处理

               GrayValue = 0.3 * r + 0.59 * g + 0.11 * b

               Hist(GrayValue) = Hist(GrayValue) + 1

        Next j

    Next i

   

   

    P(0) = Hist(0) / SourceImHeight / SourceImWidth

    Map(0) = 255 * P(0)

    For i = 1 To 255

        P(i) = P(i - 1) + Hist(i) / SourceImHeight / SourceImWidth

        Map(i) = 255 * P(i)

    Next i

   

    '图像的直方图均衡化

    For i = 0 To SourceImHeight - 1

        For j = 0 To SourceImWidth - 1

               r = sbits(i, j, 0)

               g = sbits(i, j, 1)

               b = sbits(i, j, 2)

              '插入图像处理的过程,对r, g, b进行处理

               GrayValue = 0.3 * r + 0.59 * g + 0.11 * b

               dbits(i, j, 0) = Map(GrayValue)

               dbits(i, j, 1) = Map(GrayValue)

               dbits(i, j, 2) = Map(GrayValue)

         Next j

    Next i

       

    Dim tDBmpInfo As BITMAP

    Dim hDestBmp As Long

       

    hDestBmp = PicDest.Image.Handle

 

        '获得位图信息

    Call GetObject(hDestBmp, Len(tDBmpInfo), tDBmpInfo)

    ReDim ImageArray(1 To DestImWidth * 4, 1 To DestImHeight) As Byte

         

    For i = 1 To DestImHeight

        For j = 1 To DestImWidth

            ImageArray((j - 1) * 4 + 1, i) = dbits(i - 1, j - 1, 2)

            ImageArray((j - 1) * 4 + 2, i) = dbits(i - 1, j - 1, 1)

            ImageArray((j - 1) * 4 + 3, i) = dbits(i - 1, j - 1, 0)

        Next j

    Next i

                

        '获得源图与目标图二进制位

        Call SetBitmapBits(hDestBmp, tDBmpInfo.bmWidthBytes * tDBmpInfo.bmHeight, ImageArray(1, 1))

 

End Sub

初学者可能觉得本例比较复杂,一下子跳跃的跨度较大,但只要熟悉下来,流程还是基本一致的,后面在做一些实例时,可能感觉更为明显。前面在做点运算时,每次计算只需要使用到一个点,本章开始讲述图像的增强,一般需要同时涉及到多个像素点,这里提出的数组存储数据的方法也便于这样的操作。

通过比对可以发现,采用本例的方法以后,Visual Basic处理图像的速度就跟平时见到的C系列语言处理的图像的速度基本一致,如果想要进一步提高处理速度,就需要研究算法方面的内容,这个就不在这里进行讨论了。

 

 



https://m.sciencenet.cn/blog-648901-621468.html

上一篇:Visual Basic与图像处理14
下一篇:Visual Basic与图像处理16

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-5-19 00:54

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部