K-means 代碼。
將圖檔轉成黑白之後,分群。
K_GROUP = 設置的群組數量
#include<opencv2/opencv.hpp>
#include<iostream>
#include <cstdlib> /* 亂數相關函數 */
#include <ctime> /* 時間相關函數 */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
#define K_GROUP 10
Mat srcImage, grayImage;
long long k_cnt = 0;
int max_x, min_x;
void K_Manes(Point *kp, int k_group);
int main()
{
long timeStart, timeEnd;
timeStart = clock();
char k_first_Flag = 0;
Point K_center[K_GROUP];
//unsigned long long k_min_data, k_max_data;
//unsigned long long k_center[K_GROUP] = {0,0,0};
srcImage = imread("D:\\download\\2.Result.bmp");
//grayImage = imread("C:\\Users\\User\\Downloads\\Image2\\3.Left.bmp");
cvtColor(srcImage, grayImage, CV_RGB2GRAY);
//for (int x = 0; x < grayImage.rows; x++)
//{
// for (int y = 0; y < grayImage.cols; y++)
// {
// if (grayImage.ptr<uchar>(x)[y] >= 180)
// grayImage.ptr<uchar>(x)[y] = 0;
// else if (grayImage.ptr<uchar>(x)[y] <= 20)
// grayImage.ptr<uchar>(x)[y] = 0;
// }
//}
//get point range
for (int x = 0; x < grayImage.rows; x++)
{
for (int y = 0; y < grayImage.cols; y++)
{
if (grayImage.ptr<uchar>(x)[y] != 0)
{
if (k_first_Flag == 0)
{
k_first_Flag = 1;
min_x = x;
}
max_x = x;
k_cnt++;//get total point
}
//else if (grayImage.at<Vec3b>(x, y)[0] == 0 && grayImage.at<Vec3b>(x, y)[1] == 0 && grayImage.at<Vec3b>(x, y)[2] == 0)
//{
//grayImage.ptr<uchar>(x)[y] = 255;
// grayImage.at<Vec3b>(x, y)[0] = 255;//b
// grayImage.at<Vec3b>(x, y)[1] = 255;//g
// grayImage.at<Vec3b>(x, y)[2] = 255;//r
//}
}
}
//printf("min_x=%d\n", min_x);
//printf("max_x=%d\n", max_x);
//printf("k_min_data=%ld\n", k_min_data);
//printf("k_max_data=%ld\n", k_max_data);
//get rand point
int lx, ly;
srand(time(NULL));
for (int i = 0; i < K_GROUP; i++)
{
lx = rand() % (max_x - min_x + 1) + min_x;
//printf("lx=%d\n", lx);
ly = (rand() % grayImage.cols) + 1;
K_center[i].x = lx;
K_center[i].y = ly;
//printf("ly=%d\n", ly);
//k_center[i] = lx*grayImage.rows + ly;
//printf("k_center[%d]=%ld\n", i, k_center[i]);
}
//k_manes calculate
K_Manes(K_center, K_GROUP);
imshow("show",grayImage);
timeEnd = clock();
double times;
times = (double)(timeEnd - timeStart) / 1000;
printf("times=%f\n", times);
waitKey();
return 0;
}
void K_Manes(Point *kp, int k_group)
{
Point p2;
int d[K_GROUP];
Point **data;
unsigned long **dataD;
unsigned long *loc_cnt;
long loc_g = 0;
//char rand_flag[K_GROUP];
int lx, ly;
int t = 100, stop_cnt = 0;
Point last_p[K_GROUP];
data = new Point*[K_GROUP];
dataD = new unsigned long*[K_GROUP];
loc_cnt = new unsigned long[K_GROUP];
srand(time(NULL));
for (int i = 0; i < K_GROUP; i++){
data[i] = new Point[k_cnt];
dataD[i] = new unsigned long[k_cnt];
//rand_flag[i] = 0;
last_p[i].x = 0;
last_p[i].y = 0;
}
for (int i = 0; i < K_GROUP; i++)
{
for (int j = 0; j < k_cnt; j++){
data[i][j].x = 0;
data[i][j].y = 0;
dataD[i][j] = 0;
}
}
//show point
Mat show = Mat::zeros(grayImage.rows, grayImage.cols, grayImage.type());
for (int x = 0; x < grayImage.rows; x++)
{
for (int y = 0; y < grayImage.cols; y++)
{
for (int i = 0; i < K_GROUP; i++)
if (x == kp[i].x && y == kp[i].y){
show.ptr<uchar>(x)[y] = 255;
for (int j = 0; j < 10; j++){
if (x - j > 0 && x + j < grayImage.rows && y + j < grayImage.cols && y - j>0){
show.ptr<uchar>(x - j)[y] = 255;
show.ptr<uchar>(x + j)[y] = 255;
show.ptr<uchar>(x)[y - j] = 255;
show.ptr<uchar>(x)[y + j] = 255;
}
}
}
}
}
//imshow("show point", show);
while (t--)
{
//no any point and rand kp again
//for (int i = 0; i < K_GROUP; i++)
//{
// if (rand_flag[i])
// {
// lx = rand() % (max_x - min_x + 1) + min_x;
// //printf("lx=%d\n", lx);
// ly = (rand() % grayImage.cols) + 1;
// //printf("ly=%d\n", ly);
// kp[i].x = lx;
// kp[i].y = ly;
// rand_flag[i] = 0;
// }
//}
//clear loc_cnt
for (int i = 0; i < K_GROUP; i++)
{
loc_cnt[i] = 0;
for (int j = 0; j < k_cnt; j++)
{
data[i][j].x = 0;
data[i][j].y = 0;
dataD[i][j] = 0;
}
}
int samll_d= 0;
//find group
for (int x = 0; x < grayImage.rows; x++)
{
for (int y = 0; y < grayImage.cols; y++)
{
if (grayImage.ptr<uchar>(x)[y] != 0)
{
p2.x = x;
p2.y = y;
//find distance
loc_g = 0;
samll_d = d[0];
for (int i = 0; i < K_GROUP; i++)
{
d[i] = sqrt(pow(p2.x - kp[i].x, 2) + pow(p2.y - kp[i].y, 2));
if (samll_d > d[i]){
loc_g = i;
samll_d = d[i];
}
//printf("d[%d]=%d min value =%d loc_g=%d \n", i, d[i], d[loc_g], loc_g);
}
//save data
data[loc_g][loc_cnt[loc_g]].x = p2.x;
data[loc_g][loc_cnt[loc_g]].y = p2.y;
dataD[loc_g][loc_cnt[loc_g]] = samll_d;
//printf("dataD[%d][%d] = %ld ", loc_g, loc_cnt[loc_g], dataD[loc_g][loc_cnt[loc_g]]);
loc_cnt[loc_g]++;
data[loc_g][loc_cnt[loc_g]].x = 0;
data[loc_g][loc_cnt[loc_g]].y = 0;
dataD[loc_g][loc_cnt[loc_g]] = 0;
//printf("loc_cnt[%d]=%d\n",loc_g ,loc_cnt[loc_g]);
}
}
}
//count max point
int s = loc_cnt[0];
int sl = 0;
for (int i = 0; i < K_GROUP; i++){
if (s < loc_cnt[i]){
s = loc_cnt[i];
sl = i;
//printf("sl=%d\n", sl);
}
}
//draw center point
char p = 5;
Mat show2 = Mat::zeros(show.rows, show.cols, show.type());
for (int x = 0; x < show.rows; x++)
{
for (int y = 0; y < show.cols; y++)
{
for (int i = 0; i < K_GROUP; i++)
{
if (x == kp[i].x && y == kp[i].y){
if (loc_cnt[i] > 1500){//0
show2.ptr<uchar>(x)[y] = 255;
i == sl ? p = 10 : p = 5;
for (int j = 0; j < p; j++){
if (x - j > 0 && x + j < grayImage.rows && y + j < grayImage.cols && y - j>0){
show2.ptr<uchar>(x - j)[y] = 255;
show2.ptr<uchar>(x + j)[y] = 255;
show2.ptr<uchar>(x)[y - j] = 255;
show2.ptr<uchar>(x)[y + j] = 255;
}
}
}
//printf("i=%d\n",i);
}
}
}
}
//return loop
Mat show3 = Mat::zeros(show2.rows, show2.cols, show2.type());
for (int i = 0; i < K_GROUP; i++)
{
if (stop_cnt > 3 || t == 0)
{
printf("t=%d\n", 100 - t);
//for (int x = 0; x < K_GROUP; x++)
//{
// for (int j = 0; j < loc_cnt[x]; j++)
// {
// //if (dataD[x][j] != 0)
// if (data[x][j].x != 0 && data[x][j].y != 0)
// {
// line(show3, Point(kp[x].y, kp[x].x), Point(data[x][j].y, data[x][j].x), Scalar(255, 255, 255));
// }
// }
//}
//for (int x = 0; x < grayImage.rows; x++)
//{
// for (int y = 0; y < grayImage.cols; y++)
// {
// if (grayImage.ptr<uchar>(x)[y] != 0)
// {
// show2.ptr<uchar>(x)[y] = 255;
// }
// }
//}
for (int x = 0; x < K_GROUP; x++){
//printf("loc_cnt[%d]=%ld\n", x, loc_cnt[x]);
//printf("kp[%d].x=%d kp[%d].y=%d \n", x, kp[x].x, x, kp[x].y);
}
imshow("show2 point", show2);
//imshow("show3 point", show3);
return;
}
if (last_p[i].x == kp[i].x && last_p[i].y == kp[i].y && loc_cnt[i]>0)
stop_cnt++;
else if (sqrt(pow(last_p[i].x - kp[i].x, 2) + pow(last_p[i].y - kp[i].y, 2))<5)
stop_cnt++;
}
//calcuate K-group center again
Point max_loc[K_GROUP], min_loc[K_GROUP];
unsigned long long max_p, min_p;
unsigned long long new_point_X[K_GROUP];
unsigned long long new_point_Y[K_GROUP];
for (int i = 0; i < K_GROUP; i++)
{
new_point_X[i] = 0;
new_point_Y[i] = 0;
max_p = dataD[i][0];
min_p = dataD[i][0];
max_loc[i].x = data[i][0].x;
min_loc[i].y = data[i][0].y;
for (int j = 0; j < loc_cnt[i]; j++)
{
if (data[i][j].x != 0 && data[i][j].y != 0)
{
if (loc_cnt[i] > 0){
//get max & min point
//if (min_p>dataD[i][j])
//{
// min_p = dataD[i][j];
// min_loc[i].x = data[i][j].x;
// min_loc[i].y = data[i][j].y;
//}
//if (max_p < dataD[i][j])
//{
// max_p = dataD[i][j];
// max_loc[i].x = data[i][j].x;
// max_loc[i].y = data[i][j].y;
//}
///average point
new_point_X[i] += data[i][j].x;
new_point_Y[i] += data[i][j].y;
}
}
}
//printf("new_point_X[%d]=%ld\n", i, new_point_X[i]);
//printf("new_point_Y[%d]=%ld\n", i, new_point_Y[i]);
}
//update group center
for (int i = 0; i < K_GROUP; i++)
{
if (loc_cnt[i] > 0){
//max point & min point average
//new_point_X[i] = (min_loc[i].x + max_loc[i].x) / 2;
//new_point_Y[i] = (min_loc[i].y + max_loc[i].y) / 2;
//average point
new_point_X[i] /= loc_cnt[i];
new_point_Y[i] /= loc_cnt[i];
last_p[i].x = kp[i].x;
last_p[i].y = kp[i].y;
kp[i].x = new_point_X[i];
kp[i].y = new_point_Y[i];
//printf("kp[%d].x=%d kp[%d].y=%d \n", i, kp[i].x, i, kp[i].y);
}
//else{
// rand_flag[i] = 1;
// //printf("2 kp[%d].x=%d kp[%d].y=%d \n", i, kp[i].x, i, kp[i].y);
//}
//printf("loc_cnt[%d]=%ld\n", i, loc_cnt[i]);
//printf("new_point_X[%d]=%ld\n", i, new_point_X[i]);
//printf("new_point_Y[%d]=%ld\n", i, new_point_Y[i]);
}
}
}