加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

vb.net 教程 5-14 图像处理之内存处理基础5

发布时间:2020-12-17 07:34:25 所属栏目:百科 来源:网络整理
导读:通过前期的教程,大家对于通过像素来处理图像有了一定认识,那么为什么还需要继续学习复杂的内存处理呢? 当然,一切都是为了效率。 这一篇我们就来谈谈图像处理的效率问题。 正如我之前在 图像处理之像素处理的系列教程开头所说的,vb相对于vc对于处理图像

通过前期的教程,大家对于通过像素来处理图像有了一定认识,那么为什么还需要继续学习复杂的内存处理呢?

当然,一切都是为了效率。

这一篇我们就来谈谈图像处理的效率问题。

正如我之前在 图像处理之像素处理的系列教程开头所说的,vb相对于vc对于处理图像之类都处于劣势,vc可以使用指针来处理内存,vb不行。

到了.net框架下,c#也可以使用指针,vb.net我试了下,还是可以的,但是使用指针读写的效率却比用一维数组还要略低,更比不上c#,当然造成这个的原因我还不太清楚。

但是既然同是在vb.net下处理图像,那么我们还是需要尽可能地使用高效率的方法。下面我就几种处理图像的方法做个对比,当然这几种方法的名称是我自己想出来的。

使用以下代码之前,需要引用

Imports System.Drawing.Imaging  
Imports System.Runtime.InteropServices  

一维数组处理代码(同 vb.net 教程 5-14 图像处理之内存处理基础4):

    '一维数组处理代码
    'http://blog.csdn.net/uruseibest
    Private Sub Button4_Click(sender As Object,e As EventArgs) Handles Button4.Click

        Dim timeStart,timeEnd As DateTime
        Dim timeDiff As TimeSpan

        timeStart = Now()

        '定义目标图片
        Dim destImg As New Bitmap(sourceImg.Width,sourceImg.Height)
        '定义源BitmapData,锁定区域是整个图片,只需要读取模式,采用24位RGB
        Dim sourceData As BitmapData = sourceImg.LockBits(New Rectangle(0,sourceImg.Width,sourceImg.Height),ImageLockMode.ReadOnly,PixelFormat.Format24bppRgb)
        '定义目标BitmapData,锁定区域是整个图片,只需要写入模式,采用24位RGB
        Dim destData As BitmapData = destImg.LockBits(New Rectangle(0,ImageLockMode.WriteOnly,PixelFormat.Format24bppRgb)
        '获得源BitmapData的起始指针位置
        Dim pSource As IntPtr = sourceData.Scan0
        '获得源BitmapData占用内存空间的总的字节数
        Dim allBytes As Integer = sourceData.Stride * sourceData.Height
        '定义数组,用来放置源BitmapData的数据
        Dim rgbvalues() As Byte
        ReDim rgbvalues(allBytes - 1)
        '把指针位置开始allBytes个字节数据拷贝到rgbvalues()数组中
        Marshal.Copy(pSource,rgbvalues,allBytes)

        '数组中第一个字节的序号
        Dim pos As Integer = 0
        Dim R,G,B As Integer
        Dim avgValue As Integer

        '先高度,后宽度
        For j As Integer = 0 To sourceData.Height - 1
            For i As Integer = 0 To sourceData.Width - 1
                '图片上(i,j)像素对应的蓝色分量值
                B = rgbvalues(pos)
                '图片上(i,j)像素对应的蓝色分量值
                G = rgbvalues(pos + 1)
                '图片上(i,j)像素对应的蓝色分量值
                R = rgbvalues(pos + 2)
                '这里使用的是均值法
                avgValue = (B + G + R) / 3
                '把求出的数据写回去
                rgbvalues(pos) = avgValue
                rgbvalues(pos + 1) = avgValue
                rgbvalues(pos + 2) = avgValue
                '终归是在一维数组里面取数据,向前推进3个字节
                pos = pos + 3
            Next
            '一行数据取完了,继续推进到下一行
            pos = pos + sourceData.Stride - sourceData.Width * 3
        Next

        '获得目标BitmapData的起始指针位置
        Dim pDest As IntPtr = destData.Scan0
        '将数组的内容拷到pDest指针开始的内存
        Marshal.Copy(rgbvalues,pDest,allBytes)
        '不要忘了解锁
        sourceImg.UnlockBits(sourceData)
        destImg.UnlockBits(destData)

        picDest.Image = destImg

        timeEnd = Now
        timeDiff = timeEnd - timeStart
        ListBox1.Items.Add("一维数组:" & timeDiff.TotalMilliseconds)
    End Sub

二维数组处理代码:

    '二维数组处理代码
    'http://blog.csdn.net/uruseibest
    Private Sub Button7_Click(sender As Object,e As EventArgs) Handles Button7.Click
        Dim timeStart,timeEnd As DateTime
        Dim timeDiff As TimeSpan

        timeStart = Now()
        Dim destImg As New Bitmap(sourceImg.Width,sourceImg.Height)
        Dim sourceData As BitmapData = sourceImg.LockBits(New Rectangle(0,PixelFormat.Format24bppRgb)
        Dim destData As BitmapData = destImg.LockBits(New Rectangle(0,PixelFormat.Format24bppRgb)

        Dim pSource As IntPtr = sourceData.Scan0
        Dim allBytes As Integer = sourceData.Stride * sourceData.Height
        Dim rgbvalues1() As Byte
        ReDim rgbvalues1(allBytes - 1)

        Marshal.Copy(pSource,rgbvalues1,allBytes)

        Dim rgbvalues2(,) As Byte
        ReDim rgbvalues2(destData.Height - 1,destData.Stride - 1)

        Dim pDestArray2 As IntPtr
        pDestArray2 = Marshal.UnsafeAddrOfPinnedArrayElement(rgbvalues2,0)
        Marshal.Copy(rgbvalues1,pDestArray2,allBytes)

        Dim pos As Integer = 0
        Dim R,B As Integer
        Dim avgValue As Integer

        For j As Integer = 0 To sourceData.Height - 1
            For i As Integer = 0 To sourceData.Width - 1
                B = rgbvalues2(j,i * 3)
                G = rgbvalues2(j,i * 3 + 1)
                R = rgbvalues2(j,i * 3 + 2)
                avgValue = (B + G + R) / 3
                rgbvalues2(j,i * 3) = avgValue
                rgbvalues2(j,i * 3 + 1) = avgValue
                rgbvalues2(j,i * 3 + 2) = avgValue
            Next
        Next

        Marshal.Copy(pDestArray2,allBytes)

        Dim pDest As IntPtr = destData.Scan0
        Marshal.Copy(rgbvalues1,allBytes)

        sourceImg.UnlockBits(sourceData)
        destImg.UnlockBits(destData)
        picDest.Image = destImg

        timeEnd = Now

        timeDiff = timeEnd - timeStart
        ListBox1.Items.Add("二维数组:" & timeDiff.TotalMilliseconds)
    End Sub

非常之遗憾,我没有在.net中找到一维数组直接拷贝到二维数组的方法,我也没有尝试使用copymemory,有兴趣的朋友可以自己试一下。

内存指针处理代码:

需要说明的是,.net2.0下面没有提供指针加减方法,需要引用.net 4.0 以上版本目标框架,直接在项目属性中调整后自动重启动项目即可。

    '内存指针处理代码
    'http://blog.csdn.net/uruseibest
    Private Sub Button5_Click(sender As Object,e As EventArgs) Handles Button5.Click

        Dim timeStart,PixelFormat.Format24bppRgb)

        Dim allBytes As Integer = sourceData.Stride * sourceData.Height
        Dim rgbvalues() As Byte
        ReDim rgbvalues(allBytes - 1)

        Dim pSource As IntPtr = sourceData.Scan0
        Dim pDest As IntPtr = destData.Scan0
        Marshal.Copy(pSource,allBytes)
        Marshal.Copy(rgbvalues,allBytes)

        Dim pos As IntPtr = pDest
        Dim R,B As Integer
        Dim avgValue As Byte
        For j As Integer = 0 To sourceData.Height - 1
            For i As Integer = 0 To sourceData.Width - 1

                B = Marshal.ReadByte(pos)
                G = Marshal.ReadByte(pos + 1)
                R = Marshal.ReadByte(pos + 2)


                avgValue = (B + G + R) / 3
                Marshal.WriteByte(pos,avgValue)
                Marshal.WriteByte(pos + 1,avgValue)
                Marshal.WriteByte(pos + 2,avgValue)

                pos = pos + 3
            Next
            pos = pos + sourceData.Stride - sourceData.Width * 3
        Next
        sourceImg.UnlockBits(sourceData)
        destImg.UnlockBits(destData)

        picDest.Image = destImg

        timeEnd = Now
        timeDiff = timeEnd - timeStart
        ListBox1.Items.Add("指针处理:" & timeDiff.TotalMilliseconds)
    End Sub

内存指针处理代码中,采用了Marshal.ReadByte()和Marshal.WriteByte()直接读写内存,不过效率似乎和数组差不多。

像素处理代码:

    '像素处理代码
    'http://blog.csdn.net/uruseibest
    Private Sub Button8_Click(sender As Object,e As EventArgs) Handles Button8.Click
        Dim pSourceColor As Color
        Dim pDestColor As Color

        Dim timeStart,timeEnd As DateTime
        Dim timeDiff As TimeSpan

        timeStart = Now
        Dim destImg As New Bitmap(sourceImg.Width,sourceImg.Height)
        Dim R,B As Integer
        Dim gray As Integer
        For i As Integer = 0 To sourceImg.Width - 1
            For j As Integer = 0 To sourceImg.Height - 1
                pSourceColor = sourceImg.GetPixel(i,j)
                R = pSourceColor.R
                G = pSourceColor.G
                B = pSourceColor.B
                gray = (R + G + B) / 3
                pDestColor = Color.FromArgb(gray,gray,gray)
                destImg.SetPixel(i,j,pDestColor)
            Next
        Next
        picDest.Image = destImg
        timeEnd = Now

        timeDiff = timeEnd - timeStart
        ListBox1.Items.Add("像素处理:" & timeDiff.TotalMilliseconds)
    End Sub


由于.net平台下C#和vb.NET很相似,本文也可以为C#爱好者提供参考。

学习更多vb.net知识,请参看 vb.net 教程 目录

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读