信息发布软件,b2b软件,广告发布软件

标题: VB.NET让图片黑白色原来是如此简单呀 [打印本页]

作者: 群发软件    时间: 2017-5-23 23:49
标题: VB.NET让图片黑白色原来是如此简单呀
本帖最后由 群发软件 于 2017-5-23 23:51 编辑

 原始图片

VB.NET让图片黑白色原来是如此简单呀 b2b软件

  黑白处理后图片

VB.NET让图片黑白色原来是如此简单呀 b2b软件

  原始图片:

VB.NET让图片黑白色原来是如此简单呀 b2b软件

  黑白处理后图片:

VB.NET让图片黑白色原来是如此简单呀 b2b软件

  部分处理代码:

  VB.NET code

  ……

  Dim ts2 As IThresholder = New GlobalMeanThreshold(inbmp)

  Dim tsBMP As New Bitmap(PictureBox1.Width, PictureBox1.Height)

  ts2.RenderToBitmap(tsBMP)

  PictureBox6.Image = tsBMP

  PictureBox6.Height = PictureBox1.Height

  PictureBox6.Width = PictureBox1.Width

  PictureBox6.Left = 0

  PictureBox6.Top = 0

  ……

  理论知识:

  灰度图像的二值化处理就是讲图像上的点的灰度置为0或255,也就是讲整个图像呈现出明显的黑白效果。即将256个亮度等级的灰度图像通过适当的阀值选取而获得仍然可以反映图像整体和局部特征的二值化图像。在数字图像处理中,二值图像占有非常重要的地位,特别是在实用的图像处理中,以二值图像处理实现而构成的系统是很多的,要进行二值图像的处理与分析,首先要把灰度图像二值化,得到二值化图像,这样子有利于再对图像做进一步处理时,图像的集合性质只与像素值为0或255的点的位置有关,不再涉及像素的多级值,使处理变得简单,而且数据的处理和压缩量小。为了得到理想的二值图像,一般采用封闭、连通的边界定义不交叠的区域。所有灰度大于或等于阀值的像素被判定为属于特定物体,其灰度值为255表示,否则这些像素点被排除在物体区域以外,灰度值为0,表示背景或者例外的物体区域。如果某特定物体在内部有均匀一致的灰度值,并且其处在一个具有其他等级灰度值的均匀背景下,使用阀值法就可以得到比较的分割效果。如果物体同背景的差别表现不在灰度值上(比如纹理不同),可以将这个差别特征转换为灰度的差别,然后利用阀值选取技术来分割该图像。动态调节阀值实现图像的二值化可动态观察其分割图像的具体结果。

  灰度图像的二值化没有固定的算法,根据图像区域中目标物体的不同而有不同的二值化算法.目前最主要的方法有:最大值法,平均值法,加权平均值法

  如下边代码:

  Private Function SetBitMapToBlackAndWhite(bmp As Bitmap) As Bitmap

  Try

  Dim height As Integer = bmp.Height

  Dim Width As Integer = bmp.Width

  Dim newBitMap As New Bitmap(Width, height)

  Dim pixel As Color

  For x As Integer = 0 To Width - 1

  For y As Integer = 0 To height - 1

  pixel = bmp.GetPixel(x, y)

  Dim r As Integer

  Dim g As Integer

  Dim b As Integer

  Dim Result As Integer

  Result = 0

  r = pixel.R

  g = pixel.G

  b = pixel.B

  Dim iType As Integer = 2

  Select Case iType

  Case 0

  '平均值法

  Result = (r + g + b) / 3

  Exit Select

  Case 1

  '最大值法

  If (r > g) Then

  Result = r

  Else

  Result = g

  End If

  If (Result > b) Then

  Result = Result

  Else

  Result = b

  End If

  Exit Select

  Case 2

  '加权平均值


  Result = CInt(0.7) * r + CInt(0.2) * g + CInt(0.1) * b

  Exit Select

  End Select

  newBitMap.SetPixel(x, y, Color.FromArgb(Result, Result, Result))

  Next

  Next

  Return newBitMap

  Catch ex As Exception

  Return Nothing

  End Try

  End Function

  该函数实现的简单的图像2值化。

  实际使用中最简单的二值化算法就是根据每个像素的灰度值做舍入处理,比如二值化阀值可以设置为0-255的中值127,但是这种的二值化没有根基图像的整体灰度值所在范围做考虑,所以效果很差.

  网上流传较广的是根据图像的直方图求取阀值:可以到网上搜索,我就不重复了

  介绍我的方法:

  图像数据处理函数:由于需要对图像进行指针操作,故使用C#编写源码

  public override unsafe void DoThresholding()

  {

  System.Drawing.Imaging.BitmapData indata = InBMP.LockBits(new Rectangle(0, 0, InBMP.Width, InBMP.Height),

  System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

  byte* ptr = (byte*)indata.Scan0.ToPointer();

  Histogram his = new Histogram(indata, ptr, 0, 0, InBMP.Width, InBMP.Height);

  int mean = Math.Max((int)his.Mean, 0) * 3;

  //图像阀值

  int stride = indata.Stride;

  for (int x = this.Width - 1; x >= 0; x--)

  {

  for (int y = this.Height - 1; y >= 0; y--)

  {

  int average = (ptr[(y * stride) + (x * 3)] +

  ptr[(y * stride) + (x * 3) + 1] +

  ptr[(y * stride) + (x * 3) + 2]);

  //byte average = (byte)((ptr[(y * indata.Stride) + (x * 3) + 2]));

  if (average > mean)

  Data[x, y] = 255;

  else

  Data[x, y] = 0;

  }

  }

  InBMP.UnlockBits(indata);

  }

  }

  图像阀值的求取:

  byte[] HistogramData;

  unsafe public Histogram(System.Drawing.Imaging.BitmapData indata, byte* ptr,

  int left, int top, int width, int height)

  {

  HistogramData = new byte[256];

  for (int i = 0; i < 256; i++)

  HistogramData = 0;

  int right = Math.Min(left + width, indata.Width);

  int bottom = Math.Min(top + height, indata.Height);

  int stride = indata.Stride;

  for (int x = left; x < right; x++)

  {

  for (int y = top; y < bottom; y++)

  {

  HistogramData[ptr[(y * stride) + (x * 3)]] += 1;

  HistogramData[ptr[(y * stride) + (x * 3) + 1]] += 1;

  HistogramData[ptr[(y * stride) + (x * 3) + 2]] += 1;

  }

  }

  CalculateMean();

  CalculateMinMax();

  }

  unsafe public Histogram(byte* ptr, int stride, int imgWidth, int imgHeight,

  int left, int top, int width, int height)

  {

  HistogramData = new byte[256];

  int right = Math.Min(left + width, imgWidth);

  int bottom = Math.Min(top + height, imgHeight);

  for (int x = left; x < right; x++)

  {

  for (int y = top; y < bottom; y++)

  {

  byte average = (byte)((ptr[(y * stride) + (x * 3)] +

  ptr[(y * stride) + (x * 3) + 1] +

  ptr[(y * stride) + (x * 3) + 2]) / 3);

  HistogramData[average] += 1;

  }

  }

  CalculateMean();

  CalculateVariance();

  }

  public byte Mean;

  private int Sum;

  private int WeightedSum;

  private void CalculateMean()

  {

  int sum = 0;

  int weightedSum = 0;

  for (int i = 0; i < 256; i++)

  {

  sum += HistogramData;

  weightedSum += HistogramData * i;

  }

  Sum = sum;

  WeightedSum = weightedSum;

  if (sum > 0)

  Mean = (byte)(weightedSum / sum);

  else

  Mean = 0;

  }

  生成黑白图像

  public unsafe void RenderToBitmap(Bitmap bmp)

  {

  if (Data == null)

  DoThresholding();

  System.Drawing.Imaging.BitmapData outdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),

  System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

  byte* ptr = (byte*)outdata.Scan0.ToPointer();

  for (int x = bmp.Width - 1; x >= 0; x--)

  {

  for (int y = bmp.Height - 1; y >= 0; y--)

  {

  if (this.Data[x, y] > 0)

  {

  ptr[(y * outdata.Stride) + (x * 3)] = this.Data[x, y];

  ptr[(y * outdata.Stride) + (x * 3) + 1] = this.Data[x, y];

  ptr[(y * outdata.Stride) + (x * 3) + 2] = this.Data[x, y];

  }

  else

  {

  ptr[(y * outdata.Stride) + (x * 3)] = 0;

  ptr[(y * outdata.Stride) + (x * 3) + 1] = 0;

  ptr[(y * outdata.Stride) + (x * 3) + 2] = 0;

  }

  }

  }

  bmp.UnlockBits(outdata);

  }

  考虑到图像处理速度问题,所有图像都锁定在内存中进行操作。这样比直接操作速度快了几倍。

VB彩色BMP图片转换为黑白图片

将RGB想成3D之X,Y,Z轴,则BMP的RGB为(r,g,b)与座标(Y,Y,Y)距离最小时的Y即为灰度值
Y = 0.29900 * R 0.58700 * G 0.11400 * B
整数化
Y = ( 9798*R 19235*G 3735*B) / 32768
RGB(Y, Y, Y)就可以了
需一个内有彩色图的PictureBox, CommandBox
Option Explicit
Private Declare Function GetPixel Lib "gdi32" _
(ByVal hdc As Long, ByVal x As Long, ByVal Y As Long) As Long
Private Declare Function SetPixelV Lib "gdi32" _
(ByVal hdc As Long, ByVal x As Long, _
ByVal Y As Long, ByVal crColor As Long) As Long
Private tmpPic As Picture
Private Sub Form_Load()
Picture1.ScaleMode = 3 ’设为Pixel
Picture1.AutoRedraw = True ’设定所有Pixel的改变不立即在pictureBox上显示
Set tmpPic = Picture1.Picture
End Sub
Private Sub Command1_click()
Dim width5 As Long, heigh5 As Long, rgb5 As Long
Dim hdc5 As Long, i As Long, j As Long
Dim bBlue As Long, bRed As Long, bGreen As Long
Dim Y As Long
width5 = Picture1.ScaleWidth
heigh5 = Picture1.ScaleHeight
hdc5 = Picture1.hdc
For i = 1 To width5
For j = 1 To heigh5
rgb5 = GetPixel(hdc5, i, j)
bBlue = Blue(rgb5)
bRed = Red(rgb5)
bGreen = Green(rgb5)
Y = (9798 * bRed 19235 * bGreen 3735 * bBlue) / 32768
rgb5 = RGB(Y, Y, Y)
SetPixelV hdc5, i, j, rgb5
Next j
Next i
Set Picture1.Picture = Picture1.Image ’此时才真正显示Picture

End Sub
Private Function Red(ByVal mlColor As Long) As Long
Red = mlColor And &HFF
End Function
Private Function Green(ByVal mlColor As Long) As Long
Green = (mlColor / &H100) And &HFF
End Function
Private Function Blue(ByVal mlColor As Long) As Long
Blue = (mlColor / &H10000) And &HFF
End Function


作者: lalajie    时间: 2017-5-29 08:51
快,页面设计很满意,而且也很,老板人不错,喜欢
作者: pwl2015    时间: 2017-6-2 04:15
卖家服务很好,客服和技术都很有耐心,慢慢摸熟悉了,感觉很不错,很让人放心的平台。
作者: mmgg    时间: 2017-6-5 16:32
很nice的人,人品杠杠滴!!!!
作者: linshihu    时间: 2017-6-9 00:30
看帖回帖是美德!
作者: yirenzhuang    时间: 2017-6-15 07:45
服务态度相当的好,后台好多不明白的地方都会解答,实在搞不明白的会帮我们搞定,很不错卖家。
作者: 紫逸风    时间: 2017-6-16 11:24
不错,功能强大,满意
作者: 西充    时间: 2017-6-22 17:19
太好了,第一次合作出来效果很满意!继续合作多介绍客户给你们哈




欢迎光临 信息发布软件,b2b软件,广告发布软件 (http://postbbs.com/) Powered by Discuz! X3.2