vb.net中的图像二值化
请查看测试2的结果。为什么当我在photoshop中稍微调整图像大小时,输出(二进制图像)会倾斜?但是,如果我将同一图像的像素格式转换为Format32bppArgb,那么输出很好 我已经将其缩小到GetPixel()pixel方法(请参见BitmapParser类)。我不明白为什么这个方法返回了错误的像素颜色的大小图像 包括源代码 测试:1(有效输出)vb.net中的图像二值化,vb.net,image,gdi+,Vb.net,Image,Gdi+,请查看测试2的结果。为什么当我在photoshop中稍微调整图像大小时,输出(二进制图像)会倾斜?但是,如果我将同一图像的像素格式转换为Format32bppArgb,那么输出很好 我已经将其缩小到GetPixel()pixel方法(请参见BitmapParser类)。我不明白为什么这个方法返回了错误的像素颜色的大小图像 包括源代码 测试:1(有效输出) 源图像:Test_200x200.jpg 宽度:200 高度:200 像素格式:格式化24bpprgb 输出: 测试:2(无效输出) 源
源图像:Test_200x200.jpg
宽度:200
高度:200
像素格式:格式化24bpprgb
输出:
测试:2(无效输出)
源图像:Test_203x203.jpg(相同的图像,只是在Photoshop中稍微调整了大小)
宽度:203
高度:203
像素格式:格式化24bpprgb
输出:
测试:3(有效输出)
源图像:test203x203.jpg(与Test#2相同)
宽度:203
高度:203
像素格式:在内存中转换为格式32bppargb
输出:
测试#1和2
Private Sub ConvertJpegToBiIMage(p_fullFileName As String)
Dim _BinaryImage As BinaryImage = Nothing
Dim _outPutFolder As String = "C:\BinaryImages\"
Dim _fileName As String = Path.GetFileNameWithoutExtension(p_fullFileName)
Dim _outBoundFileName As String = _outPutFolder + "BI__" + _fileName + ".jpeg"
_BinaryImage = New BinaryImage(Image.FromFile(p_fullFileName))
_BinaryImage.GetImage.Save(_outBoundFileName, System.Drawing.Imaging.ImageFormat.Jpeg)
End Sub
测试#3
Private Sub ConvertJpegToBiIMage(p_fullFileName As String)
Dim _BinaryImage As BinaryImage = Nothing
Dim _outPutFolder As String = "C:\BinaryImages\"
Dim _fileName As String = Path.GetFileNameWithoutExtension(p_fullFileName)
Dim _outBoundFileName As String = _outPutFolder + "BI__" + _fileName + ".jpeg"
Dim _bmp As Bitmap = Nothing
Using _obmp = New Bitmap(p_fullFileName)
_bmp = New Bitmap(_obmp.Width, _obmp.Height, Imaging.PixelFormat.Format32bppArgb)
Using g As Graphics = Graphics.FromImage(_bmp)
g.DrawImage(_obmp, New Rectangle(0, 0, _bmp.Width, _bmp.Height))
End Using
End Using
_BinaryImage = New BinaryImage(_bmp)
_BinaryImage.GetImage.Save(_outBoundFileName, System.Drawing.Imaging.ImageFormat.Jpeg)
End Sub
问题是图像中的填充字节。图像中每行的总字节数必须是4的倍数。因此,203像素(24bpp)的线具有
203*3=609
,这不是4的倍数。行中添加了3个字节,因此总字节数为612,是4的倍数。32bpp的图像没有这个问题,因为它总是4的倍数。谢谢。这是一个可以接受的答案。请随时发布。请注意,您不必自己进行此计算-它已在BitmapData.Stride中为您计算。问题在于图像中的填充字节。图像中每行的总字节数必须是4的倍数。因此,203像素(24bpp)的线具有203*3=609
,这不是4的倍数。行中添加了3个字节,因此总字节数为612,是4的倍数。32bpp的图像没有这个问题,因为它总是4的倍数。谢谢。这是一个可以接受的答案。请随时发布。请注意,您不必自己进行此计算-它已在BitmapData.Stride中为您计算。
Public MustInherit Class AbstractBinaryImage
Implements IDisposable
Private _width As Integer
Private _height As Integer
''' <summary>
''' Left to right, top to bottom
''' </summary>
''' <remarks></remarks>
Private _index As Integer
Private _pixels As Integer()
Public ReadOnly Property Width As Integer
Get
Return _width
End Get
End Property
Public ReadOnly Property Height As Integer
Get
Return _height
End Get
End Property
Public ReadOnly Property PixelColor(p_x As Integer, p_y As Integer) As Integer
Get
Return PixelColor(p_y * Width + p_x)
End Get
End Property
Public ReadOnly Property PixelColor(p_Index As Integer) As BinaryColor
Get
Return CType(Pixel(p_Index), BinaryColor)
End Get
End Property
Public ReadOnly Property Pixel(p_x As Integer, p_y As Integer) As Integer
Get
Return Pixel(p_y * Width + p_x)
End Get
End Property
Private ReadOnly Property Pixel(p_Index As Integer) As Integer
Get
Return _pixels(p_Index)
End Get
End Property
Public Sub New(p_width As Integer, p_height As Integer)
_width = p_width
_height = p_height
ReDim _pixels(p_width * p_height)
End Sub
Public Sub SetPixel(p_x As Integer, p_y As Integer, p_biColor As BinaryColor)
_pixels(p_y * Width + p_x) = p_biColor
End Sub
#Region "IDisposable Support"
Private disposedValue As Boolean ' To detect redundant calls
' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
_pixels = Nothing
End If
' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
' TODO: set large fields to null.
End If
Me.disposedValue = True
End Sub
' TODO: override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources.
'Protected Overrides Sub Finalize()
' ' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
' Dispose(False)
' MyBase.Finalize()
'End Sub
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
Public Class BinaryImage
Inherits AbstractBinaryImage
Implements IDisposable
Private Const _DefaultThresh As Integer = 1500
Private _bgColor As Integer = BLACK
Private _Thresh As Integer = _DefaultThresh
Private Function GrayRGB(p_Color As Color) As Integer
Return CInt(((p_Color.R * 11) + (p_Color.G * 16) + (p_Color.B * 5) / 32))
End Function
Private Function Luminance(p_color As Color) As Integer
Dim _rgbRed As Double = Math.Pow(p_color.R, 2)
Dim _rgbGreen As Double = Math.Pow(p_color.G, 2)
Dim _rgbBlue As Double = Math.Pow(p_color.B, 2)
Return CInt(Math.Sqrt((_rgbRed * 0.299) + (_rgbGreen * 0.587) + (_rgbBlue * 0.114)))
End Function
Public ReadOnly Property BackgroundColor As Integer
Get
Return _bgColor
End Get
End Property
Private Sub ParseImage(p_Image As Image)
Dim _bmpParser As New BitmapParser(CType(p_Image, Bitmap))
_bmpParser.LockBits()
Dim _blackCnt As Integer = 1
Dim _whiteCnt As Integer = 0
For y As Integer = 0 To _bmpParser.Height - 1
For x As Integer = 0 To _bmpParser.Width - 1
Dim _grgb As Integer = GrayRGB(_bmpParser.GetPixel(x, y))
If _grgb >= _Thresh Then
SetPixel(x, y, BinaryColor.Black)
Else
SetPixel(x, y, BinaryColor.White)
End If
Next
Next
_bmpParser.UnlockBits()
End Sub
Public Sub New(p_image As Image)
MyBase.New(p_image.Width, p_image.Height)
ParseImage(p_image)
End Sub
Public Function GetImage() As Bitmap
Dim _index As Integer = 0
Dim _bmp As New Bitmap(Width, Height, Imaging.PixelFormat.Format32bppArgb)
Dim _bmpParser As New BitmapParser(_bmp)
_bmpParser.LockBits()
For y As Integer = 0 To _bmpParser.Height - 1
For x As Integer = 0 To _bmpParser.Width - 1
Dim _color As Color = If(Pixel(x, y) > 0, Color.White, Color.Black)
_bmpParser.SetPixel(x, y, _color)
Next
Next
_bmpParser.UnlockBits()
Return _bmp
End Function
#Region "IDisposable Support"
Private disposedValue As Boolean ' To detect redundant calls
' IDisposable
Protected Overridable Shadows Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
MyBase.Dispose()
End If
' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
' TODO: set large fields to null.
End If
Me.disposedValue = True
End Sub
' TODO: override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources.
'Protected Overrides Sub Finalize()
' ' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
' Dispose(False)
' MyBase.Finalize()
'End Sub
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Shadows Sub Dispose()
' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
Private Sub ConvertJpegToBiIMage(p_fullFileName As String)
Dim _BinaryImage As BinaryImage = Nothing
Dim _outPutFolder As String = "C:\BinaryImages\"
Dim _fileName As String = Path.GetFileNameWithoutExtension(p_fullFileName)
Dim _outBoundFileName As String = _outPutFolder + "BI__" + _fileName + ".jpeg"
_BinaryImage = New BinaryImage(Image.FromFile(p_fullFileName))
_BinaryImage.GetImage.Save(_outBoundFileName, System.Drawing.Imaging.ImageFormat.Jpeg)
End Sub
Private Sub ConvertJpegToBiIMage(p_fullFileName As String)
Dim _BinaryImage As BinaryImage = Nothing
Dim _outPutFolder As String = "C:\BinaryImages\"
Dim _fileName As String = Path.GetFileNameWithoutExtension(p_fullFileName)
Dim _outBoundFileName As String = _outPutFolder + "BI__" + _fileName + ".jpeg"
Dim _bmp As Bitmap = Nothing
Using _obmp = New Bitmap(p_fullFileName)
_bmp = New Bitmap(_obmp.Width, _obmp.Height, Imaging.PixelFormat.Format32bppArgb)
Using g As Graphics = Graphics.FromImage(_bmp)
g.DrawImage(_obmp, New Rectangle(0, 0, _bmp.Width, _bmp.Height))
End Using
End Using
_BinaryImage = New BinaryImage(_bmp)
_BinaryImage.GetImage.Save(_outBoundFileName, System.Drawing.Imaging.ImageFormat.Jpeg)
End Sub