Asked by:
How to combine no of bin in histogram using vb.net?
Question

Hi,
I'm Bella. Do I want to ask how to combine pixel value from 0255bin into 010 bin using vb.net? can someone correct my coding? Is it correct?
Dim HDr As Long() = New Long(255) {} Dim HDg As Long() = New Long(255) {} Dim HDb As Long() = New Long(255) {} GetHistogram(New Bitmap(PictureBox1.Image), HDr, HDg, HDb) 'setup the chart With Chart1.ChartAreas(0) .AxisX.Title = "Pixel" .AxisX.MajorGrid.LineColor = Color.LightBlue .AxisX.Minimum = 0 .AxisX.Interval = 1 .AxisY.Title = "Frequency" .AxisY.MajorGrid.LineColor = Color.LightGray .AxisY.Minimum = 0 .AxisY.Interval = 0.1 .BackColor = Color.FloralWhite .BackSecondaryColor = Color.White .BackGradientStyle = GradientStyle.HorizontalCenter .BorderColor = Color.Blue .BorderDashStyle = ChartDashStyle.Solid .BorderWidth = 1 .ShadowOffset = 2 'draw the chart Chart1.Series.Clear() Chart1.Series.Add("Red") Chart1.Series("Red").ChartType = DataVisualization.Charting.SeriesChartType.Column Chart1.Series("Red").Color = Color.Red Chart1.Series("Red").IsVisibleInLegend = False For i As Integer = 0 To 9 Chart1.Series("Red").Points.AddY(HDr(i) / 70000) > Im not sure for this part. Next End With End Sub
Thanks.
Regards,
Bella
All replies

I want to ask how to combine pixel value from 0255bin into 010 bin using vb.net? can someone correct my coding? Is it correct?
What is HDr? If it is the 256 bins and you want to create 10 bins then the code would be something like:
Dim Bins10 As Integer(9)
For I As Integer = 0 to 255
Bins10(CInt(I / 25.5)) += HDr(I)
Next IThen use Bins10 to populate the Y data points.

I want to ask how to combine pixel value from 0255bin into 010 bin using vb.net? can someone correct my coding? Is it correct?
What is HDr? If it is the 256 bins and you want to create 10 bins then the code would be something like:
Dim Bins10 As Integer(9)
For I As Integer = 0 to 255
Bins10(CInt(I / 25.5)) += HDr(I)
Next IThen use Bins10 to populate the Y data points.

HDr is represent red, HDg = green and HDb = blue. From the image, I want to plot RGB histogram from bin 010. But, this coding will display for red color.
The code you provided handles the Red series. For the Green and Blue series, duplicate that code for the other arrays. If you want to show a RGB series then you need to combine that data in some way  you should indicate how it is to be combined for a RGB value.

HDr is represent red, HDg = green and HDb = blue. From the image, I want to plot RGB histogram from bin 010. But, this coding will display for red color.
The code you provided handles the Red series. For the Green and Blue series, duplicate that code for the other arrays. If you want to show a RGB series then you need to combine that data in some way  you should indicate how it is to be combined for a RGB value.
Yes. I will combine RGB color. So, each color will represent 10 bins in one graph. But, when I compare with Matlab, I don't get the same value. Below is my RGB combination graph. The graph is not the same as Matlab graph.

The graph is not the same as Matlab graph.
If that is the matlab graph then you should explain what it means. It seems there are 30 bins, not 10, and the RGB values seem to be separate, not combined, so it's not clear what the xaxis values mean. And the Yaxis values appear to be a proportion, not a count. How you would calculate proportion depends on what the bin values are: if they are counts then you need to divide by the total number of test points to get a proportion. You should show the code you are now using and describe exactly what is wrong with the result you are getting.

Below is the code represent the red color channel for the image.
Option Strict On Imports System.Drawing.Imaging Imports System.Runtime.InteropServices Imports System.Windows.Forms.DataVisualization.Charting Public Class Form1 Private Sub initChart(ByVal c As Chart) 'setup the chart With c.ChartAreas(0) .AxisX.Title = "RGB" .AxisX.MajorGrid.LineColor = Color.LightBlue .AxisX.Minimum = 0 .AxisX.Interval = 10 .AxisY.Title = "Frequency" .AxisY.MajorGrid.LineColor = Color.LightGray .AxisY.Minimum = 0 .BackColor = Color.FloralWhite .BackSecondaryColor = Color.White .BackGradientStyle = GradientStyle.HorizontalCenter .BorderColor = Color.Blue .BorderDashStyle = ChartDashStyle.Solid .BorderWidth = 1 .ShadowOffset = 2 End With End Sub Private Sub DrawChart(ByVal c As Chart, ByVal h As Histogram) For I As Integer = 0 To 255 h.R(CInt(I / 25.5)) += h.R(I) h.G(CInt(I / 25.5)) += h.G(I) h.B(CInt(I / 25.5)) += h.B(I) Next I With c 'draw the chart .Series.Clear() .Series.Add("Red") .Series("Red").ChartType = DataVisualization.Charting.SeriesChartType.Column .Series("Red").Color = Color.Red .Series("Red").IsVisibleInLegend = False Dim SumR As Double SumR = 0 For k = 1 To 10 SumR = SumR + h.R(k) Next k 'TextBox1.Text = CStr(SumR) 'TextBox1.Text = CStr(h.R(7)) Dim SumG As Double SumG = 0 For k = 1 To 10 SumG = SumG + h.G(k) Next k TextBox2.Text = CStr(SumG) 'TextBox2.Text = CStr(h.G(125)) Dim SumB As Double SumB = 0 For k = 1 To 10 SumB = SumB + h.B(k) Next k 'TextBox3.Text = CStr(SumB) For i As Integer = 0 To 10 .Series("Red").Points.AddXY(i, h.R(i) / SumR) Next End With End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click If OpenFileDialog1.ShowDialog() = DialogResult.OK Then PictureBox1.Image = Image.FromFile(OpenFileDialog1.FileName) End If Dim img As New Bitmap(PictureBox1.Image) img = New Bitmap(img, 1024, 768) RGB(img) Me.PictureBox1.Image = img End Sub Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click Dim h1 As New Histogram(New Bitmap(PictureBox1.Image), False) initChart(Chart1) DrawChart(Chart1, h1) End Sub End Class Public Class Histogram Public R As Long() = New Long(255) {} Public B As Long() = New Long(255) {} Public G As Long() = New Long(255) {} Sub New(ByVal bmp As Bitmap, ByVal Normalize As Boolean) GetHistogram(bmp, Normalize) End Sub Public Sub GetHistogram(ByVal bm As Bitmap, ByVal Norm As Boolean) Dim bmData As BitmapData Dim numBytes As Integer = 0 Dim ptr As IntPtr Dim r, g, b As Integer bmData = bm.LockBits(New Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb) ptr = bmData.Scan0 numBytes = bmData.Stride * bm.Height Dim p(numBytes  1) As Byte Marshal.Copy(ptr, p, 0, numBytes) For y As Integer = 0 To bm.Height  1 For x As Integer = 0 To bm.Width  1 r = p(x * 3 + bmData.Stride * y + 2) g = p(x * 3 + bmData.Stride * y + 1) b = p(x * 3 + bmData.Stride * y) Me.R(r) += 1 Me.G(g) += 1 Me.B(b) += 1 Next Next bm.UnlockBits(bmData) End Sub Public Shared Sub RGB(ByRef bmp As Bitmap) 'convert image into black for the backgorund and remain color of the image. Dim x As Integer Dim y As Integer Dim red As Byte Dim green As Byte Dim blue As Byte For x = 0 To bmp.Width  1 For y = 0 To bmp.Height  1 red = bmp.GetPixel(x, y).R green = bmp.GetPixel(x, y).G blue = bmp.GetPixel(x, y).B If red > 30 And green > 30 And blue > 30 Then bmp.SetPixel(x, y, Color.Black) End If Next Next End Sub End Class
I have succeeded to get the 10 bins. Now, I want to small the scale for the yaxis (frequency) such as 0 to 1 only. I don't get it. When I display the value, it shows big value. for each bin.
Thanks.
Bella
 Edited by Bella67 Thursday, August 17, 2017 8:22 AM

I have succeeded to get the 10 bins. Now, I want to small the scale for the yaxis (frequency) such as 0 to 1 only. I don't get it. When I display the value, it shows big value. for each bin.
Thanks.
Bella
Bella,
Scaling is what normalizing is. Just scale the all values by the same amount. ie to scale by one half multiply by the scale factor 1/2 = 0.5. Its the same thing as normalizing.
Just for example lets start with four pixel values. So this would be a bitmap 1 pixel high x 4 pixels wide.
Say the red color values (which normally range 0 to 255) in the bitmap pixels are:
index value
0 42
1 255
2 177
3 92
So this list of values is our bitmaps color histogram.
Now we want to normalize from a maximum value of 255 to a maximum of 10.
So our scale factor is
256 / 10 = 25.6
we use 256 because we have 0 to 255
Now we just reduce the original values by dividing with the scale factor.
42 / 25.6 = 1.64
255 / 256 = 10.0
177 / 25.6 = 6.91
92 / 25.6 = 3.59
Imports System.Windows.Forms.DataVisualization.Charting Public Class Form3 Private MyData As New List(Of PointF) Private Sub Form3_Load(sender As Object, e As EventArgs) Handles Me.Load With Chart1.ChartAreas(0) .AxisX.MajorGrid.LineColor = Color.LightBlue .AxisY.MajorGrid.LineColor = Color.LightGray .AxisX.Minimum = 1 .AxisX.Maximum = 5 .AxisX.Interval = 1 .AxisY.Minimum = 0 .AxisY.Maximum = 300 .AxisY.Interval = 50 End With Chart1.Series.Clear() Chart1.Series.Add("Base 255") Chart1.Series.Add("Base 10") Dim yvals As New List(Of Integer)({42, 255, 177, 92}) With Chart1.Series("Base 255") .ChartType = DataVisualization.Charting.SeriesChartType.Column .Color = Color.Red .IsValueShownAsLabel = True For x As Integer = 0 To 3 .Points.AddXY(x, yvals(x)) Next End With With Chart1.Series("Base 10") .ChartType = DataVisualization.Charting.SeriesChartType.Column .Color = Color.Blue .IsValueShownAsLabel = True Dim factor As Double = 256 / 10 Dim y As Double For x As Integer = 0 To 3 'round to integer just to show label better y = Math.Round(yvals(x) / factor, 1) .Points.AddXY(x, y) Next End With End Sub End Class
 Proposed as answer by Cherry BuMicrosoft contingent staff, Moderator Friday, August 18, 2017 9:05 AM

I have succeeded to get the 10 bins. Now, I want to small the scale for the yaxis (frequency) such as 0 to 1 only. I don't get it. When I display the value, it shows big value. for each bin.
That's the adjustment I mentioned above  if you bins currently contain a count of points, then you need to divide each bin total by the total number of points to convert the bin value from a count to a proportion. For instance, if your image is 256x256, and you are counting every pixel, then you could count 65536 pixels. Therefore the maximum in any one bin could be 65536. If that result should display as 1.0, then the bin value needs to be divided by 65536.
You need to calculate your scaling factor at the same time as you examine the image to calculate the bin data.
 Proposed as answer by Cherry BuMicrosoft contingent staff, Moderator Friday, August 18, 2017 9:05 AM