What's New
Q & A
Tip Jar
C# Helper...
Follow VBHelper on Twitter
MSDN Visual Basic Community
TitleFind the brightness centroid of an image
Keywordscentroid, brightness, image
The "brightness centroid" of an image is the centroid (center of gravity) of the image where each pixel is weighted by brightness.

The program uses GetDIBits to load pixel information into a DIB (device-independant bitmap). It then examines each pixel in the image.

The images used by this program include very large uninteresting areas that are dark but not perfectly black. They also include some graph lines that are not part of the laser image that we want to process. To remove the dark areas and these lines, the program ignores any pixel that is darker than a certain limit or that matches the graph line colors.

For the remaining pixels, the program calculates each pixel's X and Y moment. These are the pixel's brightness times its X and Y coordinate. The program adds all of the moments for all pixels.

After it has processed every pixel, the program divides the moments by the total brightnesses of all pixels. That gives the X and Y coordinates of the centroid.

Private m_NumIgnored As Integer
Private m_IgnoredR() As Byte
Private m_IgnoredG() As Byte
Private m_IgnoredB() As Byte

Private Sub cmdGo_Click()

Dim bitmap_info As BITMAPINFO
Dim pixels() As Byte
Dim bytes_per_scanLine As Integer
Dim pad_per_scanLine As Integer
Dim X As Integer
Dim Y As Integer
Dim i As Integer
Dim ignore_pixel As Boolean
Dim x_moment As Double
Dim y_moment As Double
Dim brightness As Double
Dim total_brightness As Double

    Screen.MousePointer = vbHourglass
    cmdGo.Enabled = False

    ' Prepare the bitmap description.
    With bitmap_info.bmiHeader
        .biSize = 40
        .biWidth = picLaser.ScaleWidth
        ' Use negative height to scan top-down.
        .biHeight = -picLaser.ScaleHeight
        .biPlanes = 1
        .biBitCount = 32
        .biCompression = BI_RGB
        bytes_per_scanLine = ((((.biWidth * .biBitCount) + _
            31) \ 32) * 4)
        pad_per_scanLine = bytes_per_scanLine - (((.biWidth _
            * .biBitCount) + 7) \ 8)
        .biSizeImage = bytes_per_scanLine * Abs(.biHeight)
    End With

    ' Load the bitmap's data.
    ReDim pixels(1 To 4, 1 To picLaser.ScaleWidth, 1 To _
    GetDIBits picLaser.hdc, picLaser.Image, _
        0, picLaser.ScaleHeight, pixels(1, 1, 1), _
        bitmap_info, DIB_RGB_COLORS

    ' Modify the pixels.
    For Y = 1 To picLaser.ScaleHeight
        For X = 1 To picLaser.ScaleWidth
            ' See if we should ignore this pixel.
            ignore_pixel = False
            For i = 1 To m_NumIgnored
                If m_IgnoredR(i) = pixels(pixR, X, Y) And _
                   m_IgnoredG(i) = pixels(pixG, X, Y) And _
                   m_IgnoredB(i) = pixels(pixB, X, Y) _
                    ignore_pixel = True
                    Exit For
                End If
            Next i

            brightness = CDbl(pixels(pixR, X, Y)) + _
                pixels(pixG, X, Y) + pixels(pixB, X, Y)
            If brightness < MIN_BRIGHTNESS Then _
                ignore_pixel = True

            ' Process the pixel.
            If ignore_pixel Then
                pixels(pixR, X, Y) = 64
                pixels(pixG, X, Y) = 64
                pixels(pixB, X, Y) = 64
                total_brightness = total_brightness + _
                x_moment = x_moment + X * brightness
                y_moment = y_moment + Y * brightness
            End If
        Next X
    Next Y

    ' Display the result.
    SetDIBits picLaser.hdc, picLaser.Image, _
        0, picLaser.ScaleHeight, pixels(1, 1, 1), _
        bitmap_info, DIB_RGB_COLORS
    picLaser.Picture = picLaser.Image

    ' Display the results.
    x_moment = x_moment / total_brightness
    y_moment = y_moment / total_brightness
    lblX.Caption = Format$(x_moment, "0.00")
    lblY.Caption = Format$(y_moment, "0.00")
    picLaser.PSet (x_moment, y_moment), vbBlue
    picLaser.Circle (x_moment, y_moment), 5, vbBlue
    picLaser.Line (x_moment + 5, y_moment + 5)-Step(5, 5), _
    picLaser.Line (x_moment - 5, y_moment + 5)-Step(-5, 5), _
    picLaser.Line (x_moment - 5, y_moment - 5)-Step(-5, _
        -5), vbBlue
    picLaser.Line (x_moment + 5, y_moment - 5)-Step(5, -5), _

    Screen.MousePointer = vbDefault
End Sub
Copyright © 1997-2010 Rocky Mountain Computer Consulting, Inc.   All rights reserved.