Mean Removal

This algorithm is like Sharpen filter. Unlike the Sharpen filter, which only worked in the horizontal and vertical directions, this one spreads it's influence diagonally as well, with the following result on the same source image.

   



									Private Class ConvolutionMatrix
	Public Sub New()
		Pixel = 1
		Factor = 1
	End Sub

	Public Sub Apply(Val As Integer)
		TopLeft = Val
		TopMid = Val
		TopRight = Val
		MidLeft = Val
		MidRight = Val
		BottomLeft = Val
		BottomMid = Val
		BottomRight = Val
		Pixel = Val
	End Sub

	Public Property TopLeft() As Integer
		Get
			Return m_TopLeft
		End Get
		Set(value As Integer)
			m_TopLeft = value
		End Set
	End Property
	Private m_TopLeft As Integer

	Public Property TopMid() As Integer
		Get
			Return m_TopMid
		End Get
		Set(value As Integer)
			m_TopMid = value
		End Set
	End Property
	Private m_TopMid As Integer

	Public Property TopRight() As Integer
		Get
			Return m_TopRight
		End Get
		Set(value As Integer)
			m_TopRight = value
		End Set
	End Property
	Private m_TopRight As Integer

	Public Property MidLeft() As Integer
		Get
			Return m_MidLeft
		End Get
		Set(value As Integer)
			m_MidLeft = value
		End Set
	End Property
	Private m_MidLeft As Integer

	Public Property MidRight() As Integer
		Get
			Return m_MidRight
		End Get
		Set(value As Integer)
			m_MidRight = value
		End Set
	End Property
	Private m_MidRight As Integer

	Public Property BottomLeft() As Integer
		Get
			Return m_BottomLeft
		End Get
		Set(value As Integer)
			m_BottomLeft = value
		End Set
	End Property
	Private m_BottomLeft As Integer

	Public Property BottomMid() As Integer
		Get
			Return m_BottomMid
		End Get
		Set(value As Integer)
			m_BottomMid = value
		End Set
	End Property
	Private m_BottomMid As Integer

	Public Property BottomRight() As Integer
		Get
			Return m_BottomRight
		End Get
		Set(value As Integer)
			m_BottomRight = value
		End Set
	End Property
	Private m_BottomRight As Integer

	Public Property Pixel() As Integer
		Get
			Return m_Pixel
		End Get
		Set(value As Integer)
			m_Pixel = value
		End Set
	End Property
	Private m_Pixel As Integer

	Public Property Factor() As Integer
		Get
			Return m_Factor
		End Get
		Set(value As Integer)
			m_Factor = value
		End Set
	End Property
	Private m_Factor As Integer

	Public Property Offset() As Integer
		Get
			Return m_Offset
		End Get
		Set(value As Integer)
			m_Offset = value
		End Set
	End Property
	Private m_Offset As Integer
End Class

Private Class Convolution
	Public Sub Convolution3x3(ByRef bmp As Bitmap)
		Dim Factor As Integer = Matrix.Factor

		If Factor = 0 Then
			Return
		End If

		Dim TopLeft As Integer = Matrix.TopLeft
		Dim TopMid As Integer = Matrix.TopMid
		Dim TopRight As Integer = Matrix.TopRight
		Dim MidLeft As Integer = Matrix.MidLeft
		Dim MidRight As Integer = Matrix.MidRight
		Dim BottomLeft As Integer = Matrix.BottomLeft
		Dim BottomMid As Integer = Matrix.BottomMid
		Dim BottomRight As Integer = Matrix.BottomRight
		Dim Pixel As Integer = Matrix.Pixel
		Dim Offset As Integer = Matrix.Offset

		Dim TempBmp As Bitmap = bmp.Clone()

		Dim bmpData As BitmapData = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
		Dim TempBmpData As BitmapData = TempBmp.LockBits(New Rectangle(0, 0, TempBmp.Width, TempBmp.Height), ImageLockMode.[ReadOnly], PixelFormat.Format24bppRgb)

		Dim ptr As IntPtr = bmpData.Scan0
		Dim TempPtr As IntPtr = TempBmpData.Scan0

		Dim Pix As Integer = 0
		Dim Stride As Integer = bmpData.Stride
		Dim DoubleStride As Integer = Stride * 2
		Dim Width As Integer = bmp.Width - 2
		Dim Height As Integer = bmp.Height - 2
		Dim stopAddress As Integer = CInt(ptr) + bmpData.Stride * bmpData.Height

		For y As Integer = 0 To Height - 1
			For x As Integer = 0 To Width - 1
				Pix = (((((Marshal.ReadByte(TempPtr + 2) * TopLeft) + (Marshal.ReadByte(TempPtr + 5) * TopMid) + (Marshal.ReadByte(TempPtr + 8) * TopRight)) + _
						 ((Marshal.ReadByte(TempPtr + 2 + Stride) * MidLeft) + (Marshal.ReadByte(TempPtr + 5 + Stride) * Pixel) + (Marshal.ReadByte(TempPtr + 8 + Stride) * MidRight)) + _
						 ((Marshal.ReadByte(TempPtr + 2 + DoubleStride) * BottomLeft) + (Marshal.ReadByte(TempPtr + 5 + DoubleStride) * BottomMid) + (Marshal.ReadByte(TempPtr + 8 + DoubleStride) * BottomRight))) \ Factor) + Offset)

				If Pix < 0 Then
					Pix = 0
				ElseIf Pix > 255 Then
					Pix = 255
				End If

				Marshal.WriteByte(ptr + 5 + Stride, CByte(Pix))

				Pix = (((((Marshal.ReadByte(TempPtr + 1) * TopLeft) + (Marshal.ReadByte(TempPtr + 4) * TopMid) + (Marshal.ReadByte(TempPtr + 7) * TopRight)) + _
						 ((Marshal.ReadByte(TempPtr + 1 + Stride) * MidLeft) + (Marshal.ReadByte(TempPtr + 4 + Stride) * Pixel) + (Marshal.ReadByte(TempPtr + 7 + Stride) * MidRight)) + _
						 ((Marshal.ReadByte(TempPtr + 1 + DoubleStride) * BottomLeft) + (Marshal.ReadByte(TempPtr + 4 + DoubleStride) * BottomMid) + (Marshal.ReadByte(TempPtr + 7 + DoubleStride) * BottomRight))) \ Factor) + Offset)

				If Pix < 0 Then
					Pix = 0
				ElseIf Pix > 255 Then
					Pix = 255
				End If

				Marshal.WriteByte(ptr + 4 + Stride, CByte(Pix))

				Pix = (((((Marshal.ReadByte(TempPtr) * TopLeft) + (Marshal.ReadByte(TempPtr + 3) * TopMid) + (Marshal.ReadByte(TempPtr + 6) * TopRight)) + _
						 ((Marshal.ReadByte(TempPtr + Stride) * MidLeft) + (Marshal.ReadByte(TempPtr + 3 + Stride) * Pixel) + (Marshal.ReadByte(TempPtr + 6 + Stride) * MidRight)) + _
						 ((Marshal.ReadByte(TempPtr + DoubleStride) * BottomLeft) + (Marshal.ReadByte(TempPtr + 3 + DoubleStride) * BottomMid) + (Marshal.ReadByte(TempPtr + 6 + DoubleStride) * BottomRight))) \ Factor) + Offset)

				If Pix < 0 Then
					Pix = 0
				ElseIf Pix > 255 Then
					Pix = 255
				End If

				Marshal.WriteByte(ptr + 3 + Stride, CByte(Pix))

				ptr += 3
				TempPtr += 3
			Next
		Next

		bmp.UnlockBits(bmpData)
		TempBmp.UnlockBits(TempBmpData)
	End Sub

	Public Property Matrix() As ConvolutionMatrix
		Get
			Return m_Matrix
		End Get
		Set(value As ConvolutionMatrix)
			m_Matrix = value
		End Set
	End Property
	Private m_Matrix As ConvolutionMatrix
End Class

Public Shared Sub ApplyMeanRemoval(ByRef bmp As Bitmap, weight As Integer)
	Dim m As New ConvolutionMatrix()
	m.Apply(-1)
	m.Pixel = weight
	m.Factor = weight - 8

	Dim C As New Convolution()
	C.Matrix = m
	C.Convolution3x3(bmp)
End Sub
								


Example

									DIm b As Bitmap = CType(Image.FromFile("rose.jpg"), Bitmap)
ApplyMeanRemoval(b, 9)