|||
Visual Basic与图像处理(二)
8、灰度拉伸
灰度拉伸是将图像中不同灰度等级按照预定的方式进行拉伸,从实质上来说灰度拉伸是灰度线性变换的一种延伸,当然也不完全等同于灰度线性变换,而是对灰度等级进行分段,然后分别进行线性变换。灰度拉伸可以用下面的函数表达式表示:
式中(x1, y1)和(x2, y2)是灰度拉伸中两个转折点的坐标,如下图中的A,B两点。
相比于线性变换,灰度拉伸可以更灵活更改图像的灰度,可以根据需要选择性的变换某个灰度等级范围内的像素点。在本例中,采用图形化控制的方法设定上述两个转折点,这里涉及了一个平时称为“橡皮筋”的技术,在网络上有很多介绍橡皮筋技术的文章,在Visual Basic中利用DrawMode属性可以非常便捷的实现所谓的橡皮筋效果。在本例中专门放置了一个用于设定转折点的PictureBox控件,在PictureBox中鼠标左键按下时,选择第一个转折点,然后鼠标拖动到第二个转折点松开鼠标左键,当鼠标左键再次按下时,将PictureBox清空,重新设置转折点。整个系统的运行界面如下:
其中灰度拉伸按钮对应的代码如下:
Private Sub cmdGrayStrech_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 Map(255) As Integer '采用映射模式计算拉伸后的灰度
Dim k(2) As Single, t(2) As Integer '存放三条直线的斜率和截距
Dim NGrayValue As Integer
ThresholdValue = Val(txtThreshold)
'设置目标图像的高度和宽度
DestImHeight = SourceImHeight
DestImWidth = SourceImWidth
'设置目标PictureBox的大小
PicDest.Height = DestImHeight
PicDest.Width = DestImWidth
'第一条直线斜率和截距
k(0) = (255 - StartPY - 0) / (StartPX - 0)
t(0) = 0
For i = 0 To StartPX
Map(i) = i * k(0) + t(0)
Next i
'第二条直线斜率和截距
k(1) = ((255 - EndPY) - (255 - StartPY)) / (EndPX - StartPX)
t(1) = (255 - EndPY) - k(1) * EndPX
For i = StartPX + 1 To EndPX
Map(i) = i * k(1) + t(1)
Next i
'第二条直线斜率和截距
k(2) = (255 - (255 - EndPY)) / (255 - EndPX)
t(2) = (255 - EndPY) - k(2) * EndPX
For i = EndPX + 1 To 255
Map(i) = i * k(2) + t(2)
Next i
'图像的灰度拉伸变换
For i = 0 To SourceImHeight - 1
For j = 0 To SourceImWidth - 1
PixelValue = PicSource.Point(j, i)
r = PixelValue Mod 256
g = (PixelValue 256) Mod 256
b = PixelValue 65536
'插入图像处理的过程,对r, g, b进行处理
GrayValue = 0.3 * r + 0.59 * g + 0.11 * b
NGrayValue = Map(GrayValue)
PicDest.PSet (j, i), RGB(NGrayValue, NGrayValue, NGrayValue)
Next j
Next i
End Sub
这里涉及的数组映射也是经常使用的一种技术,可以有效的提高软件的运行速度。
实现橡皮筋效应及转折点设置的代码分为三个部分,首先是鼠标左键按下,确定第一个转折点,然后是鼠标拖动时,实现的橡皮筋效果,最后鼠标左键抬起时,确定第二个转折点。第一个转折点和第二个转折点分别用窗口级变量来表示,分别是StartPX, StartPY, EndPX, EndPY,以便于后面计算直线的斜率和截距。
鼠标左键按下的代码如下:
Private Sub PicDraw_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = vbLeftButton Then
'将PictureBox清空
PicDraw.Cls
'画个边框
PicDraw.Line (0, 0)-(0, 255), RGB(255, 255, 255)
PicDraw.Line (0, 0)-(255, 0), RGB(255, 255, 255)
PicDraw.Line (0, 255)-(255, 255), RGB(255, 255, 255)
PicDraw.Line (255, 0)-(255, 255), RGB(255, 255, 255)
'鼠标左键已经按下
Flag = True
StartPX = X
StartPY = Y
txtFirst = "(" & Str(StartPX) & ", " & Str(255 - StartPY) & ")"
Label8.Left = StartPX
Label8.Top = StartPY
Label8.Caption = txtFirst
PicDraw.Line (0, PicDraw.Height - 1)-(StartPX, StartPY), RGB(255, 255, 0)
PicDraw.Line (StartPX, PicDraw.Height - 1)-(StartPX, StartPY), RGB(255, 0, 0)
PicDraw.Line (0, StartPY)-(StartPX, StartPY), RGB(255, 0, 0)
EndPX = X
EndPY = Y
End If
End Sub
由于DrawMode模式是异或,因此设置颜色时需要根据互补色。
鼠标拖动的代码如下,注意观察如何实现橡皮筋效果:
Private Sub PicDraw_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Flag = True Then
'擦去前面的线条
PicDraw.Line (StartPX, StartPY)-(EndPX, EndPY), RGB(255, 255, 0) '由于取的是异或,为了画蓝色的线,将前面两个量满置
EndPX = X
EndPY = Y
'画上新的线条,实现橡皮筋效果
PicDraw.Line (StartPX, StartPY)-(EndPX, EndPY), RGB(255, 255, 0)
End If
End Sub
鼠标左键抬起的时候,确定第二个转折点,代码如下:
Private Sub PicDraw_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
EndPX = X
EndPY = Y
txtSecond = "(" & Str(EndPX) & ", " & Str(255 - EndPY) & ")"
Label9.Left = EndPX
Label9.Top = EndPY
Label9.Caption = txtSecond
PicDraw.Line (EndPX, EndPY)-(PicDraw.Width - 1, 0), RGB(255, 255, 0)
PicDraw.Line (PicDraw.Width - 1, EndPY)-(EndPX, EndPY), RGB(255, 0, 0)
PicDraw.Line (EndPX, 0)-(EndPX, EndPY), RGB(255, 0, 0)
Flag = False
End Sub
需要注意的是DrawMode设置为Xor Pen表示在同一位置画同样的线时,将把原来的线擦除,从而可以实现橡皮筋效应,在窗体窗体时对DrawMode进行设置,代码如下:
Private Sub Form_Load()
PicDraw.DrawMode = 7 ' vbXorPen
End Sub
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-5-18 22:08
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社