もじゅ2
' 画像加工
Module Module02_image_processing
Friend kaneru1() As Integer = {0, 1, 0,
1, -4, 1,
0, 1, 0} 'カーネル係数
Friend kaneru2() As Integer = {1, 1, 1,
1, -8, 1,
1, 1, 1} 'カーネル係数
' ガウスぼかし処理(From GaussianBlur)
Public Function GaussianBlurXY(ByVal src_bmp As Bitmap, ByVal zone As Integer) As Bitmap 'ソース画像 ,ぼかし度?
Dim range As Integer = zone * 3
Dim w As Integer = src_bmp.Width
Dim h As Integer = src_bmp.Height
' 短辺の1/5より大きい場合は無視する
If range <= 0 Or range >= Math.Min(w, h) \ 5 Then
Return Nothing
End If
Dim gf(range) As Double
For i As Integer = 0 To range
gf(i) = Math.Exp(-i * i / (2 * zone * zone))
Next
Dim sum, sa, sr, sg, sb, gauss As Double
Dim tmp_bmp As Bitmap = New Bitmap(src_bmp)
Dim dis_bmp As Bitmap = New Bitmap(src_bmp)
Dim rect As Rectangle = New Rectangle(0, 0, w, h)
Dim src_bmpData As Imaging.BitmapData = src_bmp.LockBits(rect, Imaging.ImageLockMode.ReadWrite, Imaging.PixelFormat.Format32bppArgb)
Dim src_ptr As IntPtr = src_bmpData.Scan0
Dim tmp_bmpData As Imaging.BitmapData = tmp_bmp.LockBits(rect, Imaging.ImageLockMode.ReadWrite, Imaging.PixelFormat.Format32bppArgb)
Dim tmp_ptr As IntPtr = tmp_bmpData.Scan0
Dim dis_bmpData As Imaging.BitmapData = dis_bmp.LockBits(rect, Imaging.ImageLockMode.ReadWrite, Imaging.PixelFormat.Format32bppArgb)
Dim dis_ptr As IntPtr = dis_bmpData.Scan0
Dim stride As Integer = dis_bmpData.Stride
Dim rgba_step As Integer = CInt(stride / dis_bmpData.Width) ' RGBの時は3,RGBAの時は4
Dim bytes As Integer = stride * h
Dim dis_argb(bytes - 1) As Byte
Dim tmp_argb(bytes - 1) As Byte
Dim src_argb(bytes - 1) As Byte
System.Runtime.InteropServices.Marshal.Copy(dis_ptr, dis_argb, 0, bytes)
System.Runtime.InteropServices.Marshal.Copy(tmp_ptr, tmp_argb, 0, bytes)
System.Runtime.InteropServices.Marshal.Copy(src_ptr, src_argb, 0, bytes)
' 水平方向に平均化(src_argb->tmp_argb)
For y As Integer = 0 To h - 1
For x As Integer = 0 To w - 1
sum = 0
sa = 0
sr = 0
sg = 0
sb = 0
Dim offset As Integer
For ix As Integer = x - range To x + range
If ix < 0 Or ix >= w Then Continue For
offset = stride * y + ix * rgba_step
gauss = gf(Math.Abs(ix - x))
sa += src_argb(offset + 3) * gauss
sr += src_argb(offset + 2) * gauss * src_argb(offset + 3)
sg += src_argb(offset + 1) * gauss * src_argb(offset + 3)
sb += src_argb(offset + 0) * gauss * src_argb(offset + 3)
sum += gauss
Next
offset = stride * y + x * rgba_step
If sa > 0 Then
tmp_argb(offset + 3) = AdjustByte(sa / sum)
tmp_argb(offset + 2) = AdjustByte(sr / sa)
tmp_argb(offset + 1) = AdjustByte(sg / sa)
tmp_argb(offset + 0) = AdjustByte(sb / sa)
Else
tmp_argb(offset + 3) = 0
tmp_argb(offset + 2) = 0
tmp_argb(offset + 1) = 0
tmp_argb(offset + 0) = 0
End If
Next
Next
' 垂直方向に平均化(tmp_argb->dis_argb)
For y As Integer = 0 To h - 1
For x As Integer = 0 To w - 1
sum = 0
sa = 0
sr = 0
sg = 0
sb = 0
Dim offset As Integer
For iy As Integer = y - range To y + range
If iy < 0 Or iy >= h Then Continue For
offset = stride * iy + x * rgba_step
gauss = gf(Math.Abs(iy - y))
sa += tmp_argb(offset + 3) * gauss
sr += tmp_argb(offset + 2) * gauss * tmp_argb(offset + 3)
sg += tmp_argb(offset + 1) * gauss * tmp_argb(offset + 3)
sb += tmp_argb(offset + 0) * gauss * tmp_argb(offset + 3)
sum += gauss
Next
offset = stride * y + x * rgba_step
If sa > 0 Then
dis_argb(offset + 3) = AdjustByte(sa / sum)
dis_argb(offset + 2) = AdjustByte(sr / sa)
dis_argb(offset + 1) = AdjustByte(sg / sa)
dis_argb(offset + 0) = AdjustByte(sb / sa)
Else
dis_argb(offset + 3) = 0
dis_argb(offset + 2) = 0
dis_argb(offset + 1) = 0
dis_argb(offset + 0) = 0
End If
Next
Next
' 処理結果を配列からコピー
System.Runtime.InteropServices.Marshal.Copy(dis_argb, 0, dis_ptr, bytes)
System.Runtime.InteropServices.Marshal.Copy(tmp_argb, 0, tmp_ptr, bytes)
System.Runtime.InteropServices.Marshal.Copy(src_argb, 0, src_ptr, bytes)
dis_bmp.UnlockBits(dis_bmpData)
tmp_bmp.UnlockBits(tmp_bmpData)
src_bmp.UnlockBits(src_bmpData)
tmp_bmp.Dispose()
tmp_bmp = Nothing
' src_bmpは呼び出し元で準備したものなので、操作しない
Return dis_bmp
End Function
' カラーコードを8ビット値に入るように調整する
Public Function AdjustByte(ByVal value As Integer) As Byte
If value < 0 Then
Return 0
ElseIf value > 255 Then
Return 255
End If
Return value
End Function
Public Function AdjustByte(ByVal value As Double) As Byte
If value < 0 Then
Return 0
ElseIf value > 255 Then
Return 255
End If
Return value
End Function
'グレーを算出
Public Function Gray_Calculation(r As Integer, g As Integer, b As Integer) '赤緑青
Dim re_color As Integer = r * 0.3 + g * 0.59 + b * 0.11
If re_color > 255 Then
re_color = 255
End If
Return re_color
End Function
'グレー画像を返す
Public Function RGB_to_Gray(n_bmp As Bitmap) '画像
Dim Re_bmp As Bitmap = n_bmp.Clone
' Bitmap処理の高速化開始
Dim bmpP As Module01_BitmapPlus = New Module01_BitmapPlus(Re_bmp)
bmpP.BeginAccess()
For i As Integer = 0 To Re_bmp.Width - 1
For j As Integer = 0 To Re_bmp.Height - 1
'グレーを算出
Dim n_Gray As Integer = Gray_Calculation(bmpP.GetPixel(i, j).R, bmpP.GetPixel(i, j).G, bmpP.GetPixel(i, j).B) '赤緑青
bmpP.SetPixel(i, j, Color.FromArgb(255, n_Gray, n_Gray, n_Gray)) 'アルファ(透明度)、赤、緑、青
Next
Next
' Bitmap処理の高速化終了
bmpP.EndAccess()
Return Re_bmp
End Function
'白黒
Public Function siro_kuro(n_bmp As Bitmap, border As Integer) '画像,白黒のしきい値
Dim Re_bmp As Bitmap = n_bmp.Clone
' Bitmap処理の高速化開始
Dim bmpP As Module01_BitmapPlus = New Module01_BitmapPlus(Re_bmp)
bmpP.BeginAccess()
For i As Integer = 0 To Re_bmp.Width - 1
For j As Integer = 0 To Re_bmp.Height - 1
'グレーの色を返す
Dim n_Gray As Integer = Gray_Calculation(bmpP.GetPixel(i, j).R, bmpP.GetPixel(i, j).G, bmpP.GetPixel(i, j).B) '赤緑青
'白黒
If n_Gray >= border Then 'しきい値
n_Gray = 255
Else
n_Gray = 0
End If
bmpP.SetPixel(i, j, Color.FromArgb(255, n_Gray, n_Gray, n_Gray)) 'アルファ(透明度)、赤、緑、青
Next
Next
' Bitmap処理の高速化終了
bmpP.EndAccess()
Return Re_bmp
End Function
'エッジ算出
Public Function rinkak_Calculation(n_arr(,) As Integer, a1() As Integer) '画像の2次元 値はグレースケール,倍率1-9 カーネル係数
Dim len0 As Integer = n_arr.GetLength(0) ' 0次元目の要素数を取得
Dim len1 As Integer = n_arr.GetLength(1) ' 1次元目の要素数を取得
Dim re_arr(len0, len1) As Integer
For i As Integer = 0 To len0 - 1 '横
For j As Integer = 0 To len1 - 1 '縦
If i = 0 Or i = len0 - 1 Or j = 0 Or j = len1 - 1 Then ' 端
re_arr(i, j) = 0 '輪郭なしとします
Else
re_arr(i, j) += n_arr(i - 1, j - 1) * a1(0) '左上
re_arr(i, j) += n_arr(i, j - 1) * a1(1) '上
re_arr(i, j) += n_arr(i + 1, j - 1) * a1(2) '右上
'
re_arr(i, j) += n_arr(i - 1, j) * a1(3) '左
re_arr(i, j) += n_arr(i, j) * a1(4) '真ん中
re_arr(i, j) += n_arr(i + 1, j) * a1(5) '右
'
re_arr(i, j) += n_arr(i - 1, j + 1) * a1(6) '左下
re_arr(i, j) += n_arr(i, j + 1) * a1(7) '下
re_arr(i, j) += n_arr(i + 1, j + 1) * a1(8) '右下
End If
If re_arr(i, j) > 255 Then
re_arr(i, j) = 255
ElseIf re_arr(i, j) < 0 Then
re_arr(i, j) = 0
End If
Next
Next
Return re_arr
End Function
'エッジ画像を返す
Public Function rinkak_ga(n_bmp As Bitmap, Black_white As Integer, kaneru() As Integer) '画像 , 白黒しきい値 ,倍率1-9 カーネル係数
Dim Re_bmp As Bitmap = n_bmp.Clone
' Bitmap処理の高速化開始
Dim bmpP1 As Module01_BitmapPlus = New Module01_BitmapPlus(Re_bmp)
bmpP1.BeginAccess()
Dim len0 As Integer = Re_bmp.Width - 1 ' 0次元目の要素数を取得
Dim len1 As Integer = Re_bmp.Height - 1 ' 1次元目の要素数を取得
Dim n_arr1(len0, len1) As Integer
Dim n_arr2(len0, len1) As Integer
For i As Integer = 0 To len0 - 1
For j As Integer = 0 To len1 - 1
'グレーの色を返す
Dim n_Gray As Integer = Gray_Calculation(bmpP1.GetPixel(i, j).R, bmpP1.GetPixel(i, j).G, bmpP1.GetPixel(i, j).B) '赤緑青
'白黒
If n_Gray >= Black_white Then 'しきい値
n_Gray = 255
Else
n_Gray = 0
End If
n_arr1(i, j) = n_Gray
Next
Next
n_arr2 = rinkak_Calculation(n_arr1, kaneru) '画像の2次元 値はグレースケール,倍率1-9
For i As Integer = 0 To len0 - 1
For j As Integer = 0 To len1 - 1
bmpP1.SetPixel(i, j, Color.FromArgb(255, n_arr2(i, j), n_arr2(i, j), n_arr2(i, j))) 'アルファ(透明度)、赤、緑、青
Next
Next
' Bitmap処理の高速化終了
bmpP1.EndAccess()
Return Re_bmp
End Function
End Module