none
How to combine no of bin in histogram using vb.net? RRS feed

  • Question

  • Hi,

    I'm Bella. Do I want to ask how to combine pixel value from 0-255bin into 0-10 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

    Tuesday, August 15, 2017 9:54 AM

All replies

  • I want to ask how to combine pixel value from 0-255bin into 0-10 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 I

    Then use Bins10 to populate the Y data points.

    Tuesday, August 15, 2017 10:06 AM
  • I want to ask how to combine pixel value from 0-255bin into 0-10 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 I

    Then 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 0-10. But, this coding will display for red color. 
    Tuesday, August 15, 2017 12:54 PM
  • HDr is represent red, HDg = green and HDb = blue. From the image, I want to plot RGB histogram from bin 0-10. 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.

    Tuesday, August 15, 2017 9:35 PM
  • HDr is represent red, HDg = green and HDb = blue. From the image, I want to plot RGB histogram from bin 0-10. 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.

    Wednesday, August 16, 2017 8:19 AM
  • 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 x-axis values mean.   And the Y-axis 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.

    Wednesday, August 16, 2017 10:54 AM
  • 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 y-axis (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
    Thursday, August 17, 2017 8:20 AM
  • I have succeeded to get the 10 bins. Now, I want to small the scale for the y-axis (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

    Thursday, August 17, 2017 1:07 PM
  • I have succeeded to get the 10 bins. Now, I want to small the scale for the y-axis (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.

    Thursday, August 17, 2017 10:06 PM