Kmeans::Kmeans(const Mat& points, int k, string fileName) { this->k = k; n = points.rows; m = points.cols; k_means(points); collect(); updateMeasure(); save(fileName.c_str()); }
/** @function ******************************************************************************** <PRE> 函数名: InitGMM() 功能: 获得GMM初值 用法: 参数: [IN] X: 特征向量组 返回: 调用: k_means() 主调函数: GMMs() </PRE> *******************************************************************************/ static GMM InitGMM(double X[GOOD_FRAME_NUM][D]) { int i; int j; int clusterIndex[GOOD_FRAME_NUM] = {0}; //向量所属质心索引 int clusterSize[M] = {0}; //聚类所含向量数 GMM gmm = {{0}, {{0}}, {{0}}}; double sum[M][D] = {{0}}; //初始化均值u gmm = k_means(X, clusterIndex, clusterSize); //初始化加权系数p for (i = 0; i < M; ++i) { gmm.p[i] = 1.0 / M; } //初始化协方差矩阵cMatrix for (i = 0; i < GOOD_FRAME_NUM; ++i) { for (j = 0; j < D; ++j) { sum[clusterIndex[i]][j] += pow(X[i][j], 2); } } for (i = 0; i < M; ++i) { if (clusterSize[i] > 0) //防止分母为0 { for (j = 0; j < D; ++j) { //此处有负值和0值 gmm.cMatrix[i][j] = sum[i][j] / clusterSize[i] - pow(gmm.u[i][j], 2); if (gmm.cMatrix[i][j] < 0) { #ifdef _DEBUG printf("InitGMM: initial value of GMM`cMatrix < 0\n"); #endif // _DEBUG exit(0); } else if(gmm.cMatrix[i][j] < 1e-10) //消除相同double值相减的误差 { gmm.cMatrix[i][j] = 0; } } } //end if (clusterSize[i] > 0) } return gmm; }
void do_kmeans_sort(struct cluster_bed_matrix *cbm, double t, boolean sort) /* clusters but also sorts the labels by cluster size */ { int i = 0; int *labels = k_means(cbm, t); /* if (sort) */ /* exchange_labels(cbm->cluster_sizes, cbm->k, labels, cbm->num_na, cbm->pbm->nrow); */ for (i = cbm->num_na; i < cbm->pbm->nrow; i++) cbm->pbm->array[i]->label = labels[i]; qsort(cbm->pbm->array, cbm->pbm->nrow, sizeof(cbm->pbm->array[0]), perBaseWigLabelCmp); for (i = 0; i < cbm->pbm->nrow; i++) cbm->pbm->matrix[i] = cbm->pbm->array[i]->data; freeMem(labels); }
int main(int argc, char** args) { if(argc!=3) { std::cerr << "Usage cq image.jpg centroids.txt" << std::endl; return -1; } unsigned int max_loops = 5; std::string img_filename = args[1]; std::cout << "Image file = " << img_filename << std::endl; test(img_filename); // read image img_struct<unsigned char> rgb = read_image(img_filename); // read centroids std::string centroids_filename = args[2]; img_struct<unsigned char> rgb_centroids = read_centroids_txt(centroids_filename); // convert image and centroids to YUV float rgb_2_yuv[] = { 0.299, 0.587, 0.114, -0.14713, -0.28886, 0.436, 0.615, -0.51499, -0.10001 }; img_struct<float> yuv = convert_img<unsigned char, float, 3>(rgb, rgb_2_yuv); img_struct<float> centroids_yuv = convert_img<unsigned char, float, 3>(rgb_centroids, rgb_2_yuv); std::cout << "Done converting to yuv " << std::endl; // cluster the YUV image std::cout << "Start k_means " << std::endl; img_struct<float> clustered_yuv = k_means(yuv, centroids_yuv, max_loops); std::cout << "End k_means " << std::endl; // YUV 2 RGB (cluster image) float yuv_2_rgb[] = { 1, 0, 1.13983, 1, -0.39465, -0.58060, 1, 2.03211, 0 }; img_struct<unsigned char> clustered_rgb = convert_img<float, unsigned char, 3>(clustered_yuv, yuv_2_rgb); std::string img_clustered_filename = "clustered_image.jpg"; save_file<unsigned char>(clustered_rgb, img_clustered_filename); return 0; };
static float64 furthest_neighbor_kmeans(uint32 n_obs, uint32 veclen, vector_t *mean, uint32 n_mean, float32 min_ratio, uint32 max_iter) { uint32 **obs_of; uint32 *occ_cnt; codew_t *lbl; uint32 k_max=0, occ_max; uint32 n_mean_cur; vector_t *extr_mean; uint32 k, l; float64 sqerr; lbl = ckd_calloc(n_obs, sizeof(codew_t)); occ_cnt = ckd_calloc(n_mean, sizeof(uint32)); n_mean_cur = 1; extr_mean = (float32 **)ckd_calloc_2d(2, veclen, sizeof(float32)); do { E_INFO("n_mean == %u\n", n_mean_cur); obs_of = cw_obs(lbl, n_mean_cur, n_obs, occ_cnt); occ_max = 0; for (k = 0; k < n_mean_cur; k++) { if (occ_cnt[k] > occ_max) { occ_max = occ_cnt[k]; k_max = k; } } /* set the initial values of the new means by extreme means */ E_INFO("d_max == %e\n", find_farthest_neigh(obs_of[k_max], occ_cnt[k_max], veclen, extr_mean[0], extr_mean[1])); sqerr = k_means_subset(extr_mean, 2, obs_of[k_max], occ_cnt[k_max], veclen, min_ratio, max_iter, NULL); for (l = 0; l < veclen; l++) { mean[k_max][l] = extr_mean[0][l]; mean[n_mean_cur][l] = extr_mean[1][l]; } ++n_mean_cur; ckd_free(lbl); sqerr = k_means(mean, n_mean_cur, n_obs, veclen, min_ratio, max_iter, &lbl); E_INFO("\tsquerr == %e\n", sqerr); } while (n_mean_cur < n_mean); return sqerr; }
static float32 random_kmeans(uint32 n_trial, uint32 n_obs, uint32 veclen, vector_t *bst_mean, uint32 n_mean, float32 min_ratio, uint32 max_iter, codew_t **out_label) { uint32 t, k, kk; float32 rr; uint32 cc; codew_t *label = NULL, *b_label = NULL; vector_t *tmp_mean; float64 sqerr, b_sqerr = MAX_POS_FLOAT64; vector_t c; uint32 n_aborts; tmp_mean = (vector_t *)ckd_calloc_2d(n_mean, veclen, sizeof(float32)); E_INFO("Initializing means using random k-means\n"); for (t = 0; t < n_trial; t++) { E_INFO("Trial %u: %u means\n", t, n_mean); n_aborts = 100; /* # of aborts to allow */ do { /* pick a (pseudo-)random set of initial means from the corpus */ for (k = 0; k < n_mean; k++) { rr = drand48(); /* random numbers in the interval [0, 1) */ cc = rr * n_obs; assert((cc >= 0) && (cc < n_obs)); c = get_obs(cc); for (kk = 0; kk < veclen; kk++) { tmp_mean[k][kk] = c[kk]; } } if (n_mean > 1) { sqerr = k_means_trineq(tmp_mean, n_mean, n_obs, veclen, min_ratio, max_iter, &label); } else { sqerr = k_means(tmp_mean, n_mean, n_obs, veclen, min_ratio, max_iter, &label); } if (sqerr < 0) { E_INFO("\t-> Aborting k-means, bad initialization\n"); --n_aborts; } } while ((sqerr < 0) && (n_aborts > 0)); if (sqerr < b_sqerr) { b_sqerr = sqerr; E_INFO("\tbest-so-far sqerr = %e\n", b_sqerr); if (b_label) ckd_free(b_label); b_label = label; for (k = 0; k < n_mean; k++) { for (kk = 0; kk < veclen; kk++) { bst_mean[k][kk] = tmp_mean[k][kk]; } } } else { if (label) { ckd_free(label); label = NULL; } } } *out_label = b_label; ckd_free_2d((void **)tmp_mean); return b_sqerr; }
// main function in class BrightnessGroup // analyze and classify images void BrightnessGroup::run(){ int i; // get the number of clusters from user to set the number of group cout << "How many clusters? "; cin >> numcluster; cout << endl; // make the folder to save the result makebrightnessfolder( numcluster ); // set the size of brightness array to the number of images brightness = (float*)malloc(sizeof(float)*num); // for each image, for( i=0; i<num; i++){ Mat image, hsv_image; image = images[i]; // extract color element of the image // if the images doesn't have 3 channels, it's classified to '-1' if (image.channels() == 3){ // change the mode of image from RGB to HSV cvtColor(image, hsv_image, CV_BGR2HSV); // Separate the image in 3 places ( H, S, V ) vector<Mat> hsv_planes; split( hsv_image, hsv_planes ); // make histogram with brightness element ('v' in hsv means 'value') int vHistSize = 100; float vRange[] = {0, 100}; const float* vHistRange = { vRange }; Mat v_hist; calcHist( &hsv_planes[0], 1, 0, Mat(), v_hist, 1, &vHistSize, &vHistRange, true, false); int vHist_w = 300; int vHist_h = 400; int vbin_w = cvRound( (double) vHist_w/vHistSize); Mat vHistImage( vHist_h, vHist_w, CV_8UC3, Scalar( 0, 0, 0) ); normalize(v_hist, v_hist, 0, vHistImage.rows, NORM_MINMAX, -1, Mat() ); // with histogram of brightness, get the average of the brightness brightness[i] = avgBrightness(v_hist, vHistSize); cout << "The average of brightness is " << brightness[i] << endl; }else{ brightness[i] = -1; } cout << "next, go to other picture..." << endl; } // with the average of brightness data, // let the image get its own group by k means clustering k_means(); // with the clusters array result, classify and save images in appropriate folder if( flag == IS_FROM_FILES ){ int i=0; string filename; // open "filenames.txt" and get the name of file ifstream file; file.open("filenames.txt"); // save the images in appropriate folder which is the clusters array result while(!file.eof() && i<num ){ getline(file, filename); char newfile[FILE_NAME_MAX+20] = "./brightness_result/"; strcat(newfile, intToString(clusters[i]).c_str()); strcat(newfile, "/"); strcat(newfile, filename.c_str()); cout << "new file adress : " << newfile << endl; imwrite(newfile, images[i]); i++; } }else if( flag == IS_FROM_URLS ){ int i; // make the file name to save. It counts from 0 in increasing order // and save the images in appropriate folder which is the color array const char file[10] = "photo_"; for( i=0; i<num; i++){ char newfile[FILE_NAME_MAX+20] = "./brightness_result/"; strcat(newfile, intToString(clusters[i]).c_str()); strcat(newfile, "/"); strcat(newfile, file); if( i < 10 ){ strcat(newfile, "00"); strcat(newfile, intToString(i).c_str()); }else if ( i >= 10 && i < 100 ){ strcat(newfile, "0"); strcat(newfile, intToString(i).c_str()); }else if ( i >= 100 && i < 1000 ){ strcat(newfile, intToString(i).c_str()); } cout << newfile << endl; strcat(newfile, ".jpg"); imwrite(newfile, images[i]); } } cout << "brightness grouping finished" << endl; }
int main(int argc, const char *argv[]) { // build k_means() compatible memory layout points = calloc(npoints, sizeof(double*)); for (int i = 0; i < npoints; ++i) { points[i] = &_points[i * DIM]; } // determine the number of points - this is a fragile heuristic! nclusters = sqrt(npoints / 2); // centroids = calloc(nclusters, sizeof(double*)); for (int i = 0; i < nclusters; ++i) { centroids[i] = calloc(2, sizeof(double)); } // print our data //printf("npoints: %ld\n", npoints); //for (int i = 0; i < npoints; ++i) { // printf(" %f %f\n", points[i][0], points[i][1]); //} // run k_means() clusters = k_means(points, npoints, DIM, nclusters, 0.0001, centroids); // print clusters printf("npoints: %ld\n", npoints); printf("nclusters: %ld\n", nclusters); // x, y, cluster, centroid x, centroid y printf(" %8s %8s %2s %8s %8s\n", "x", "y", "c", "cx", "cy"); for (int i = 0; i < npoints; ++i) { int cluster = clusters[i]; printf(" %8f %8f %2d %f %f\n", points[i][0], points[i][1], cluster, centroids[cluster][0], centroids[cluster][1]); } // print just the centroids printf("\ncentroids:\n"); for (int i = 0; i < nclusters; ++i) { int cluster = clusters[i]; printf(" %2d %f\n", i, centroids[i][0]); } printf("\n"); for (int i = 0; i < nclusters; ++i) { printf(" %2d %f\n", i, centroids[i][1]); } // clean up if (points) free(points); if (centroids) { for (int i = 0; i < nclusters; ++i) { if (centroids[i]) free(centroids[i]); } free(centroids); } return 0; }
object *baseline(unsigned char *image, unsigned char *mask, int width, int height, int *n_object) { int i = 0, j = 0, k = 0; int n; /* number of objects */ int *area; /* area */ double *len; /* perimeter length */ double *circ; /* circularity index */ double *input_val; /*Color features*/ double *clr_mn_value, *clr_std_dev, *clr_skew, *clr_kurtosis, **clr_hist; /*Texture features*/ double ***glcmat, *ang_sec_mom, *contr, *corr, *var; double *inv_diff_mom, *sum_av, *sum_entrp, *sum_varnc; double *entrp, *diff_var, *diff_entrp; object *obj; /* for storing results */ int **obj_id = (int **)malloc(height*sizeof(int *)); if (obj_id == NULL){ printf("Could not allocate %d bytes.\n", height*sizeof(int *)); exit(0); } else{ for (i = 0; i < height; i++){ obj_id[i] = (int *)malloc(width*sizeof(int)); if (obj_id[i] == NULL){ printf("Could not allocate %d bytes for i=%d index.\n", width*sizeof(int), i); exit(0); } } } /* assign ID to each object and returns the number of objects */ n = assign_id(mask, width, height, obj_id); /* allocate memories */ area = (int *)malloc(n * sizeof(int)); if (area == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(int))); exit(-1); } len = (double *)malloc(n * sizeof(double)); if (len == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double))); exit(-1); } circ = (double *)malloc(n * sizeof(double)); if (circ == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double))); exit(-1); } obj = (object *)malloc(n * sizeof(object)); if (obj == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(object))); exit(-1); } /*Colors*/ clr_mn_value = (double *)malloc(n * sizeof(double)); if (clr_mn_value == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double))); exit(-1); } input_val = (double *)malloc(n * sizeof(double)); if (input_val == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double))); exit(-1); } clr_std_dev = (double *)malloc(n * sizeof(double)); if (clr_std_dev == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double))); exit(-1); } clr_skew = (double *)malloc(n * sizeof(double)); if (clr_skew == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double))); exit(-1); } clr_kurtosis = (double *)malloc(n * sizeof(double)); if (clr_kurtosis == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double))); exit(-1); } clr_hist = (double **)malloc(n*sizeof(double *)); if (clr_hist == NULL){ printf("Could not allocate %d bytes.\n", n*sizeof(double *)); exit(0); } else{ for (i = 0; i < n; i++){ clr_hist[i] = (double *)malloc(256*sizeof(double)); if (clr_hist[i] == NULL){ printf("Could not allocate %d bytes for i=%d index.\n", 256*sizeof(double), i); exit(0); } else{ for (j = 0; j<256; j++){ clr_hist[i][j] = 0.0; } } } } /*Texture*/ glcmat = (double ***)malloc(n * sizeof(double**)); if (glcmat == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double**))); exit(-1); } else{ for (i = 0;i < n; i++){ glcmat[i] = (double **)malloc(256 * sizeof(double *)); if (glcmat[i] == NULL){ printf("Cannot allocate %d bytes for memory.\n", (256 * sizeof(double *))); exit(-1); } else{ for (j = 0;j < 256; j++){ glcmat[i][j] = (double *)malloc(256 * sizeof(double)); if (glcmat[i][j] == NULL){ printf("Cannot allocate %d bytes for memory.\n", (256 * sizeof(double))); exit(-1); } else{ for (k = 0;k < 256;k++){ glcmat[i][j][k] = 0.0; } } }/*for j*/ } }/*for i*/ } ang_sec_mom = (double *)malloc(n * sizeof(double)); if (ang_sec_mom == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double))); exit(-1); } memset(ang_sec_mom, 0, (n * sizeof(double))); contr = (double *)malloc(n * sizeof(double)); if (contr == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double))); exit(-1); } memset(contr, 0, (n * sizeof(double))); corr = (double *)malloc(n * sizeof(double)); if (corr == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double))); exit(-1); } memset(corr, 0, (n * sizeof(double))); var = (double *)malloc(n * sizeof(double)); if (var == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double))); exit(-1); } memset(var, 0, (n * sizeof(double))); inv_diff_mom = (double *)malloc(n * sizeof(double)); if (inv_diff_mom == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double))); exit(-1); } memset(inv_diff_mom, 0, (n * sizeof(double))); sum_av = (double *)malloc(n * sizeof(double)); if (sum_av == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double))); exit(-1); } memset(sum_av, 0, (n * sizeof(double))); sum_entrp = (double *)malloc(n * sizeof(double)); if (sum_entrp == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double))); exit(-1); } memset(sum_entrp, 0, (n * sizeof(double))); sum_varnc = (double *)malloc(n * sizeof(double)); if (sum_varnc == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double))); exit(-1); } memset(sum_varnc, 0, (n * sizeof(double))); entrp = (double *)malloc(n * sizeof(double)); if (entrp == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double))); exit(-1); } memset(entrp, 0, (n * sizeof(double))); diff_var = (double *)malloc(n * sizeof(double)); if (diff_var == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double))); exit(-1); } memset(diff_var, 0, (n * sizeof(double))); diff_entrp = (double *)malloc(n * sizeof(double)); if (diff_entrp == NULL){ printf("Cannot allocate %d bytes for memory.\n", (n * sizeof(double))); exit(-1); } memset(diff_entrp, 0, (n * sizeof(double))); /* calcuate areas */ calculate_area(obj_id, width, height, n, area); /* calcuate perimeter length */ calculate_length(obj_id, width, height, n, len, image); /* calcuate cirularity index */ /* morphological_feature_circularity_index(area, len, n, circ); morphological_feature_object_moment(1.0, 1.0, obj_id, width, height, n, image, circ); morphological_feature_central_moments(0.0, 0.0, obj_id, width, height, n, image, circ); morphological_feature_object_orientation(obj_id, width, height, n, image, circ); */ morphological_feature_object_eccentricity(obj_id, width, height, n, image, circ); /* morphological_feature_central_invariant_moments(1.0, 1.0, obj_id, width, height, n, image, circ); */ /*color features*/ /* color_feature_mean(obj_id, width, height, n, area, image, clr_mn_value); color_feature_standard_deviation(obj_id, width, height, n, area, image, clr_mn_value, clr_std_dev); color_feature_skewness(obj_id, width, height, n, area, image, clr_mn_value, clr_skew); color_feature_kurtosis(obj_id, width, height, n, area, image, clr_mn_value, clr_kurtosis); color_feature_histogram(0, obj_id, width, height, n, area, image, clr_hist); */ /*texture features*/ /* glcm(0, obj_id, width, height, n, image, glcmat); texture_feature_angular_second_moment(glcmat, n, ang_sec_mom); texture_feature_contrast(glcmat, n, contr); texture_feature_correlation(glcmat, n, corr); texture_feature_variance(glcmat, n, var); texture_feature_inverse_diff_moment(glcmat, n, inv_diff_mom); texture_feature_sum_average(glcmat, n, sum_av); texture_feature_sum_entropy(glcmat, n, sum_entrp); texture_feature_sum_variance(glcmat, n, sum_entrp, sum_varnc); texture_feature_entropy(glcmat, n, entrp); texture_feature_difference_variance(glcmat, n, diff_var); texture_feature_difference_entropy(glcmat, n, diff_entrp); */ double weight = 0.0; for (i = 0; i < n; i++) { /*Morphological feature*/ input_val[i] = circ[i]; /*Color features*/ /*input_val[i] = weight*circ[i] + (1.0 - weight)*clr_mn_value[i];*/ /*input_val[i] = weight*circ[i] + (1.0 - weight)*clr_std_dev[i];*/ /*input_val[i] = weight*circ[i] + (1.0 - weight)*clr_skew[i];*/ /*input_val[i] = weight*circ[i] + (1.0 - weight)*clr_kurtosis[i];*/ /*input_val[i] = weight*circ[i] + weight*clr_mn_value[i] + weight*clr_std_dev[i] + weight*clr_skew[i] + weight*clr_kurtosis[i];*/ /*input_val[i] = weight*clr_mn_value[i] + weight*clr_std_dev[i] + weight*clr_skew[i] + weight*clr_kurtosis[i];*/ /*Texture features*/ /*input_val[i] = weight*circ[i] + (1.0 - weight)*ang_sec_mom[i];*/ /*input_val[i] = weight*circ[i] + (1.0 - weight)*contr[i];*/ /*input_val[i] = weight*circ[i] + (1.0 - weight)*corr[i];*/ /*input_val[i] = weight*circ[i] + (1.0 - weight)*var[i];*/ /*input_val[i] = weight*circ[i] + (1.0 - weight)*inv_diff_mom[i];*/ /*input_val[i] = weight*circ[i] + (1.0 - weight)*sum_av[i];*/ /*input_val[i] = weight*circ[i] + (1.0 - weight)*sum_entrp[i];*/ /*input_val[i] = weight*circ[i] + (1.0 - weight)*sum_varnc[i];*/ /*input_val[i] = weight*circ[i] + (1.0 - weight)*entrp[i];*/ /*input_val[i] = weight*circ[i] + (1.0 - weight)*diff_var[i];*/ /*input_val[i] = weight*circ[i] + (1.0 - weight)*diff_entrp[i];*/ } /* k-means clustering */ /*k_means(circ, obj, n);*/ k_means(input_val, obj, n); /* choose representatives (smallest number for each cluster) */ for (i = 0; i < n; i++) obj[i].rep = 0; for (j = 0; j < NUM_CLASS; j++) { for (i = 0; i < n; i++) { if (obj[i].label == j) { obj[i].rep = 1; break; } } } /* find bounding box */ find_rect(obj_id, width, height, n, obj); for (i = 0; i < height; i++) free(obj_id[i]); free(obj_id); free(area); free(len); free(circ); free(input_val); /*color features*/ free(clr_mn_value); free(clr_std_dev); free(clr_skew); free(clr_kurtosis); for (i = 0; i < n; i++) free(clr_hist[i]); free(clr_hist); /*texture features*/ for (i=0;i<n;i++){ for (j=0;j<256;j++){ free(glcmat[i][j]); }/*for j*/ free(glcmat[i]); }/*for i*/ free(glcmat); free(ang_sec_mom); free(contr); free(corr); free(var); free(inv_diff_mom); free(sum_av); free(sum_entrp); free(sum_varnc); free(entrp); free(diff_var); free(diff_entrp); *n_object = n; return obj; }
/* It executes the Brain Storm Optimization for function minimization according to Algorithm 1 (El-Abd, 2017) Parameters: s: search space Evaluate: pointer to the function used to evaluate particles arg: list of additional arguments */ void runBSO(SearchSpace *s, prtFun Evaluate, ...) { va_list arg, argtmp; int i, j, z, k, t, *best = NULL, c1, c2, **ideas_per_cluster = NULL; double p, r; Agent *nidea = NULL; va_start(arg, Evaluate); va_copy(argtmp, arg); if (!s) { fprintf(stderr, "\nSearch space not allocated @runBSO.\n"); exit(-1); } ideas_per_cluster = (int **)malloc(s->k * sizeof(int *)); best = (int *)malloc(s->k * sizeof(int)); nidea = CreateAgent(s->n, _BSO_, _NOTENSOR_); EvaluateSearchSpace(s, _BSO_, Evaluate, arg); /* Initial evaluation */ for (t = 1; t <= s->iterations; t++) { fprintf(stderr, "\nRunning iteration %d/%d ... ", t, s->iterations); /* clustering ideas */ k_means(s, best, &ideas_per_cluster); /* for each idea */ for (i = 0; i < s->m; i++) { va_copy(arg, argtmp); p = GenerateUniformRandomNumber(0, 1); if (s->p_one_cluster > p) { c1 = (int)GenerateUniformRandomNumber(0, s->k); /* selecting a cluster probabilistically */ p = GenerateUniformRandomNumber(0, 1); /* creating a new idea based on the cluster selected previously. We also consider if cluster c1 has a single idea, i.e., ideas_per_cluster[c1][0] == 0. Notice we do not consider the cluster's center into that computation @kmeans function, which means a unitary cluster has ideas_per_cluster[c1][0] == 0. */ if ((s->p_one_center > p) || (ideas_per_cluster[c1][0] == 0)) { for (k = 0; k < s->n; k++) nidea->x[k] = s->a[best[c1]]->x[k]; } else { /* creating a new idea based on another idea j selected randomly from cluster c1 */ j = (int)GenerateUniformRandomNumber(1, ideas_per_cluster[c1][0]); j = ideas_per_cluster[c1][j]; for (k = 0; k < s->n; k++) nidea->x[k] = s->a[j]->x[k]; } } else { /* selecting two clusters' centers probabilistically */ c1 = (int)GenerateUniformRandomNumber(0, s->k); c2 = (int)GenerateUniformRandomNumber(0, s->k); /* selecting two ideas randomly */ if (ideas_per_cluster[c1][0] == 0) j = best[c1]; else { j = (int)GenerateUniformRandomNumber(1, ideas_per_cluster[c1][0]); j = ideas_per_cluster[c1][j]; } if (ideas_per_cluster[c2][0] == 0) z = best[c2]; else { z = (int)GenerateUniformRandomNumber(1, ideas_per_cluster[c2][0]); z = ideas_per_cluster[c2][z]; } p = GenerateUniformRandomNumber(0, 1); r = GenerateUniformRandomNumber(0, 1); /* it creates a new idea based on a random combination of two selected clusters' centers */ if (s->p_two_centers > p) { for (k = 0; k < s->n; k++) nidea->x[k] = r * s->a[best[c1]]->x[k] + (1 - r) * s->a[best[c2]]->x[k]; } else { /* it creates a new idea based on the ideas selected at random from the clusters previously chosen */ for (k = 0; k < s->n; k++) nidea->x[k] = r * s->a[j]->x[k] + (1 - r) * s->a[z]->x[k]; } } /* adding local noise to the new created idea */ p = (0.5 * s->iterations - t) / k; r = GenerateUniformRandomNumber(0, 1) * Logistic_Sigmoid(p); for (k = 0; k < s->n; k++) nidea->x[k] += r * randGaussian(0, 1); /* It evaluates the new created idea */ CheckAgentLimits(s, nidea); p = Evaluate(nidea, arg); if (p < s->a[i]->fit) { /* if the new idea is better than the current one */ for (k = 0; k < s->n; k++) s->a[i]->x[k] = nidea->x[k]; s->a[i]->fit = p; } if (s->a[i]->fit < s->gfit) s->gfit = s->a[i]->fit; } fprintf(stderr, "OK (minimum fitness value %lf)", s->gfit); for (i = 0; i < s->k; i++) free(ideas_per_cluster[i]); } free(ideas_per_cluster); free(best); DestroyAgent(&nidea, _BSO_); va_end(arg); }
int quantize(Pixel *pixelData, uint32_t nPixels, uint32_t nQuantPixels, Pixel **palette, uint32_t *paletteLength, uint32_t **quantizedPixels, int kmeans) { PixelList *hl[3]; HashTable *h; BoxNode *root; uint32_t i; uint32_t *qp; uint32_t nPaletteEntries; uint32_t *avgDist; uint32_t **avgDistSortKey; Pixel *p; #ifndef NO_OUTPUT uint32_t timer,timer2; #endif #ifndef NO_OUTPUT timer2=clock(); printf ("create hash table..."); fflush(stdout); timer=clock(); #endif h=create_pixel_hash(pixelData,nPixels); #ifndef NO_OUTPUT printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC); #endif if (!h) { goto error_0; } #ifndef NO_OUTPUT printf ("create lists from hash table..."); fflush(stdout); timer=clock(); #endif hl[0]=hl[1]=hl[2]=NULL; hashtable_foreach(h,hash_to_list,hl); #ifndef NO_OUTPUT printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC); #endif if (!hl[0]) { goto error_1; } #ifndef NO_OUTPUT printf ("mergesort lists..."); fflush(stdout); timer=clock(); #endif for(i=0;i<3;i++) { hl[i]=mergesort_pixels(hl[i],i); } #ifdef TEST_MERGESORT if (!test_sorted(hl)) { printf ("bug in mergesort\n"); goto error_1; } #endif #ifndef NO_OUTPUT printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC); #endif #ifndef NO_OUTPUT printf ("median cut..."); fflush(stdout); timer=clock(); #endif root=median_cut(hl,nPixels,nQuantPixels); #ifndef NO_OUTPUT printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC); #endif if (!root) { goto error_1; } nPaletteEntries=0; #ifndef NO_OUTPUT printf ("median cut tree to hash table..."); fflush(stdout); timer=clock(); #endif annotate_hash_table(root,h,&nPaletteEntries); #ifndef NO_OUTPUT printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC); #endif #ifndef NO_OUTPUT printf ("compute palette...\n"); fflush(stdout); timer=clock(); #endif if (!compute_palette_from_median_cut(pixelData,nPixels,h,&p,nPaletteEntries)) { goto error_3; } #ifndef NO_OUTPUT printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC); #endif free_box_tree(root); root=NULL; /* malloc check ok, using calloc for overflow */ qp=calloc(nPixels, sizeof(uint32_t)); if (!qp) { goto error_4; } if (nPaletteEntries > UINT32_MAX / nPaletteEntries ) { goto error_5; } /* malloc check ok, using calloc for overflow, check of n*n above */ avgDist=calloc(nPaletteEntries*nPaletteEntries, sizeof(uint32_t)); if (!avgDist) { goto error_5; } /* malloc check ok, using calloc for overflow, check of n*n above */ avgDistSortKey=calloc(nPaletteEntries*nPaletteEntries, sizeof(uint32_t *)); if (!avgDistSortKey) { goto error_6; } if (!build_distance_tables(avgDist,avgDistSortKey,p,nPaletteEntries)) { goto error_7; } if (!map_image_pixels_from_median_box(pixelData,nPixels,p,nPaletteEntries,h,avgDist,avgDistSortKey,qp)) { goto error_7; } #ifdef TEST_NEAREST_NEIGHBOUR #include <math.h> { uint32_t bestmatch,bestdist,dist; HashTable *h2; printf ("nearest neighbour search (full search)..."); fflush(stdout); timer=clock(); h2=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp); for (i=0;i<nPixels;i++) { if (hashtable_lookup(h2,pixelData[i],&paletteEntry)) { bestmatch=paletteEntry; } else { bestmatch=0; bestdist= _SQR(pixelData[i].c.r-p[0].c.r)+ _SQR(pixelData[i].c.g-p[0].c.g)+ _SQR(pixelData[i].c.b-p[0].c.b); for (j=1;j<nPaletteEntries;j++) { dist= _SQR(pixelData[i].c.r-p[j].c.r)+ _SQR(pixelData[i].c.g-p[j].c.g)+ _SQR(pixelData[i].c.b-p[j].c.b); if (dist==bestdist && j==qp[i]) { bestmatch=j; } if (dist<bestdist) { bestdist=dist; bestmatch=j; } } hashtable_insert(h2,pixelData[i],bestmatch); } if (qp[i]!=bestmatch ) { printf ("discrepancy in matching algorithms pixel %d [%d %d] %f %f\n", i,qp[i],bestmatch, sqrt((double)(_SQR(pixelData[i].c.r-p[qp[i]].c.r)+ _SQR(pixelData[i].c.g-p[qp[i]].c.g)+ _SQR(pixelData[i].c.b-p[qp[i]].c.b))), sqrt((double)(_SQR(pixelData[i].c.r-p[bestmatch].c.r)+ _SQR(pixelData[i].c.g-p[bestmatch].c.g)+ _SQR(pixelData[i].c.b-p[bestmatch].c.b))) ); } } hashtable_free(h2); } #endif #ifndef NO_OUTPUT printf ("k means...\n"); fflush(stdout); timer=clock(); #endif if (kmeans) k_means(pixelData,nPixels,p,nPaletteEntries,qp,kmeans-1); #ifndef NO_OUTPUT printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC); #endif *quantizedPixels=qp; *palette=p; *paletteLength=nPaletteEntries; #ifndef NO_OUTPUT printf ("cleanup..."); fflush(stdout); timer=clock(); #endif if (avgDist) free(avgDist); if (avgDistSortKey) free(avgDistSortKey); destroy_pixel_hash(h); #ifndef NO_OUTPUT printf ("done (%f)\n",(clock()-timer)/(double)CLOCKS_PER_SEC); printf ("-----\ntotal time %f\n",(clock()-timer2)/(double)CLOCKS_PER_SEC); #endif return 1; error_7: if (avgDistSortKey) free(avgDistSortKey); error_6: if (avgDist) free(avgDist); error_5: if (qp) free(qp); error_4: if (p) free(p); error_3: if (root) free_box_tree(root); error_1: destroy_pixel_hash(h); error_0: *quantizedPixels=NULL; *paletteLength=0; *palette=NULL; return 0; }