Sie sind auf Seite 1von 10

Dim i As Integer

Dim j As Integer

Private Data() ' Row 0 = cluster, 1 =X, 2= Y; data in columns

Private Centroid() As Single ' centroid (X and Y) of clusters; cluster number = column number

Private totalData As Integer ' total number of data (total columns)

Private numCluster As Integer ' total number of cluster

Dim x1 As Long

Dim y1 As Long

Private Sub Command1_Click()

Dim hWnd As IntPtr

Dim hDC As IntPtr

Dim i, j As Integer

Dim tcol As Long

Dim curx, cury As Long

Dim r, g, b As Integer

Dim Y, cb, cr As Integer

hWnd = Picture1.Handle.ToInt32()

hDC = GetWindowDC(hWnd)

curx = Picture1.Width

cury = Picture1.Height

For i = 0 To curx - 1
For j = 0 To cury - 1

tcol = GetPixel(hDC, i, j)

r = tcol Mod 256

g = (tcol \ 256) Mod 256

b = tcol \ 256 \ 256

Y = 16 + (1 / 256) * (65.738 * r + 129.057 * g + 25.04 * b)

cb = 128 + (1 / 256) * (-37.945 * r - 74.494 * g + 112.439 * b)

cr = 128 + 1 / 256 * (112.439 * r - 94.154 * g - 18.285 * b)

SetPixel hDC, i, j, RGB(Y, cb, cr)

Next j

Next i

End Sub

Private Sub Command2_Click()

End

End Sub

' ###################################################################

' CONTROLS

' + Form_Load

' + cmdReset_Click

' + txtNumCluster_Change

' + Picture1_MouseDown

' + Picture1_MouseMove

' ###################################################################
Private Sub Form_Load()

Dim i As Integer

Picture1.BackColor = &HFFFFFF ' white

Picture1.DrawWidth = 10 ' big dot

Picture1.ScaleMode = 3 ' pixels

lblExplanation.Caption = "Click data in the picture box below. The program will automatically cluster
the data by color code"

'take number of cluster

numCluster = Int(txtNumCluster)

ReDim Centroid(1 To 2, 1 To numCluster)

' lblCentroid(0).Visible = False

' lblCentroid(0).Caption = 1

For i = 0 To numCluster - 1

'create label

If i > 0 Then Load lblCentroid(i)

lblCentroid(i).Caption = i + 1

lblCentroid(i).Visible = False

Next i

End Sub

Private Sub cmdReset_Click()

' reset data

Dim i As Integer

Picture1.Cls ' clean picture


Erase Data ' remove data

totalData = 0

For i = 0 To numCluster - 1

lblCentroid(i).Visible = False ' don't show label

Next i

'enable to change the number of cluster

txtNumCluster.Enabled = True

End Sub

Private Sub of_Click()

cd1.ShowOpen

Picture1.Picture = LoadPicture(cd1.FileName)

End Sub

Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)

'collecting data and showing result

Dim colorCluster As Integer

Dim i As Integer

'disable to change the number of cluster

txtNumCluster.Enabled = False

' take feature data

totalData = totalData + 1

ReDim Preserve Data(0 To 2, 1 To totalData) ' notice: start with 0 for row

Data(1, totalData) = X

Data(2, totalData) = Y
'do k-mean clustering

Call kMeanCluster(Data, numCluster)

'show the result

Picture1.Cls

For i = 1 To totalData

colorCluster = Data(0, i) - 1

If colorCluster = 7 Then colorCluster = 12 ' if white (similar to background change to other


color)

X = Data(1, i)

Y = Data(2, i)

Picture1.PSet (X, Y), QBColor(colorCluster)

Next i

'show centroid

For i = 1 To min2(numCluster, totalData)

lblCentroid(i - 1).Left = Centroid(1, i)

lblCentroid(i - 1).Top = Centroid(2, i)

lblCentroid(i - 1).Visible = True

Next i

End Sub

Private Sub txtNumCluster_Change()

'change number of cluster and reset data

Dim i As Integer

For i = 1 To numCluster - 1

Unload lblCentroid(i)
Next i

numCluster = Int(txtNumCluster)

ReDim Centroid(1 To 2, 1 To numCluster)

'Call cmdReset_Click

For i = 0 To numCluster - 1

If i > 0 Then Load lblCentroid(i)

lblCentroid(i).Caption = i + 1

lblCentroid(i).Visible = False

Next i

End Sub

Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)

lblXYValue.Caption = X & "," & Y

End Sub

' ###################################################################

' FUNCTIONS

' + kMeanCluster:

' + dist: calculate distance

' + min2: return minimum value between two numbers

' ###################################################################

Sub kMeanCluster(Data() As Variant, numCluster As Integer)


' main function to cluster data into k number of Clusters

' input: + Data matrix (0 to 2, 1 to TotalData); Row 0 = cluster, 1 =X, 2= Y; data in columns

' + numCluster: number of cluster user want the data to be clustered

' + private variables: Centroid, TotalData

' ouput: o) update centroid

' o) assign cluster number to the Data (= row 0 of Data)

Dim i As Integer

Dim j As Integer

Dim X As Single

Dim Y As Single

Dim min As Single

Dim cluster As Integer

Dim d As Single

Dim sumXY()

Dim isStillMoving As Boolean

isStillMoving = True

If totalData <= numCluster Then

Data(0, totalData) = totalData ' cluster No = total data

Centroid(1, totalData) = Data(1, totalData) ' X

Centroid(2, totalData) = Data(2, totalData) ' Y

Else

'calculate minimum distance to assign the new data

min = 10 ^ 10 'big number


X = Data(1, totalData)

Y = Data(2, totalData)

For i = 1 To numCluster

d = dist(X, Y, Centroid(1, i), Centroid(2, i))

If d < min Then

min = d

cluster = i

End If

Next i

Data(0, totalData) = cluster

Do While isStillMoving

' this loop will surely convergent

'calculate new centroids

ReDim sumXY(1 To 3, 1 To numCluster) ' 1 =X, 2=Y, 3=count number of data

For i = 1 To totalData

sumXY(1, Data(0, i)) = Data(1, i) + sumXY(1, Data(0, i))

sumXY(2, Data(0, i)) = Data(2, i) + sumXY(2, Data(0, i))

sumXY(3, Data(0, i)) = 1 + sumXY(3, Data(0, i))

Next i

For i = 1 To numCluster

Centroid(1, i) = sumXY(1, i) / sumXY(3, i)

Centroid(2, i) = sumXY(2, i) / sumXY(3, i)

Next i
'assign all data to the new centroids

isStillMoving = False

For i = 1 To totalData

min = 10 ^ 10 'big number

X = Data(1, i)

Y = Data(2, i)

For j = 1 To numCluster

d = dist(X, Y, Centroid(1, j), Centroid(2, j))

If d < min Then

min = d

cluster = j

End If

Next j

If Data(0, i) <> cluster Then

Data(0, i) = cluster

isStillMoving = True

End If

Next i

Loop

End If

End Sub
Function dist(x1 As Single, y1 As Single, X2 As Single, Y2 As Single) As Single

' calculate Euclidean distance

dist = Sqr((Y2 - y1) ^ 2 + (X2 - x1) ^ 2)

End Function

Private Function min2(num1, num2)

' return minimum value between two numbers

If num1 < num2 Then

min2 = num1

Else

min2 = num2

End If

End Function

Das könnte Ihnen auch gefallen