//----------------------------------------------------------------- // clustering.cpp: // クラスタリング用関数 // Last Update: <2004/12/22 22:08:50 A.Murakami> //----------------------------------------------------------------- #include "clustering.h" //----------------------------------------------------------------- // 画像中の白画素のデータ取得 //----------------------------------------------------------------- int obtain_points_data(LPBYTE inb,ClutData& cltd) { int x,y; cltd.num_pnts=0; // 取得ポイント数 for(y=0;y=MAX_PNTS){ MessageBox(NULL,"点列が多すぎます. 画像を作り直して下さい",0,0); return FALSE; } return TRUE; } //----------------------------------------------------------------- // 取得した点データをランダムに入れ替える. //----------------------------------------------------------------- void shuffle_points_data(ClutData& cltd) { int i,num1,num2; int sw_max; // 乱数の初期化 init_random(); // 点の総数の2倍の回数の入れ替え sw_max = cltd.num_pnts * 2; for(i=0;imin_num2) cltd.p_clstr[i]--; else if(cltd.p_clstr[i]==min_num2) cltd.p_clstr[i]=min_num1; } // 新規クラスタ重心の設定 sum_number = 0; sum_x = sum_y = 0; for(i=0;i=min_num2)?1:0; dy = (i>=min_num2)?1:0; dist_clstr[j+i*(cltd.num_clstr-1)] = dist_clstr[(j+dx)+(i+dy)*cltd.num_clstr]; } } // クラスタ数を減らす cltd.num_clstr--; // 距離の再計算 for(i=0;i<=min_num1;i++) for(j=i+1;j end_loop) finish = 1; } //-------------------------------------------------- // 各クラスタの意味上の半径を求める //-------------------------------------------------- for(i=0;i radius_clstr[i]) radius_clstr[i]=rint(distance); } } //-------------------------------------------------- // クラスタ位置の表示 //-------------------------------------------------- // 入力点と各点データまでの線分を描く if(dopt){ for(i=0;iMAX_CLSTR) return; //-------------------------------------------------- // 画像中の点を取得 //-------------------------------------------------- if(!obtain_points_data(inb,cltd)) return; //-------------------------------------------------- // 初期のクラスタ中心の設定 //-------------------------------------------------- cltd.num_clstr=K_number; shuffle_points_data(cltd); // ランダムに入れ替え for(i=0;i radius_clstr[i]) radius_clstr[i]=rint(distance); } } } // クラスタ中心が移動したかどうかのチェック finish=1; for(i=0;i KC_MINERR) finish=0; // 許容誤差 } } //-------------------------------------------------- // クラスタ位置の表示 //-------------------------------------------------- // 入力点と各点データまでの線分を描く if(dopt){ for(i=0;iMAX_CLSTR) return 0; //----------------------------------------------------------------- // ブロック数 //----------------------------------------------------------------- vqd.x_block = iWidth / VQ_BLKSZ; vqd.y_block = iHeight / VQ_BLKSZ; if(iWidth % VQ_BLKSZ != 0) vqd.x_block ++; if(iHeight % VQ_BLKSZ != 0) vqd.y_block ++; //----------------------------------------------------------------- // ベクトルデータの取得 //----------------------------------------------------------------- obtain_vector_data(inb,vqd); //----------------------------------------------------------------- // 仮代表ベクトルの設定 //----------------------------------------------------------------- init_random(); // 乱数の初期化 for(i=0;iVQ_MINERR) finish=0; } if(finish == 1){ // 処理終了 // 各ブロックを代表ベクトルに置換 for(y=0;y>=1; j++; } while(i > 0); // 圧縮後のサイズ coded_data_size = VQ_BLKSZ * VQ_BLKSZ * K_number * 8 + j * vqd.x_block * vqd.y_block; // 代表ベクトル数 // 圧縮率 compression_rate=(double)coded_data_size / (double)original_data_size * 100.0; return compression_rate; } //----------------------------------------------------------------- // ベクトル量子化[K平均法によるクラスタリング]: カラー画像 //----------------------------------------------------------------- double c_vector_quantize(LPBYTE inb,int K_number) // int K_number: K値(生成するクラスタの総数),default=100 // 返り値: 圧縮率[圧縮後のサイズ/元サイズ] { #if 0 // 各RGB成分ごと double comp_rate; LPBYTE iR=GetGray(COLOR_R); LPBYTE iG=GetGray(COLOR_G); LPBYTE iB=GetGray(COLOR_B); comp_rate = 0; comp_rate += vector_quantize(iR,K_number); comp_rate += vector_quantize(iG,K_number); comp_rate += vector_quantize(iB,K_number); comp_rate /= 3.0; RGBToColor(inb,iR,iG,iB); // 後片付け GlobalFree(iR); GlobalFree(iG); GlobalFree(iB); return comp_rate; #else // RGB成分をベクトルとして扱う int i,j,x,y,xs,ys; int counter,min_num,finish; int original_data_size,coded_data_size; double min_distance,distance,compression_rate; double sum[CVQ_DIM],sum_number,difference; BYTE init_main_vector[MAX_CLSTR][CVQ_DIM]; // 代表ベクトル CVQData vqd; //----------------------------------------------------------------- if(K_number>MAX_CLSTR) return 0; //----------------------------------------------------------------- // ブロック数 //----------------------------------------------------------------- vqd.x_block = iWidth / VQ_BLKSZ; vqd.y_block = iHeight / VQ_BLKSZ; if(iWidth % VQ_BLKSZ != 0) vqd.x_block ++; if(iHeight % VQ_BLKSZ != 0) vqd.y_block ++; //----------------------------------------------------------------- // ベクトルデータの取得 //----------------------------------------------------------------- vqd.cv = (C_vector*)GlobalAlloc(GPTR,sizeof(C_vector)*VQ_MAXBLK*VQ_MAXBLK); obtain_c_vector_data(inb,vqd); //----------------------------------------------------------------- // 仮代表ベクトルの設定 //----------------------------------------------------------------- init_random(); // 乱数の初期化 for(i=0;iVQ_MINERR) finish=0; } if(finish == 1){ // 処理終了 // 各ブロックを代表ベクトルに置換 for(y=0;y>=1; j++; } while(i > 0); // 圧縮後のサイズ coded_data_size = VQ_BLKSZ * VQ_BLKSZ * K_number * 8 * 3+ j * vqd.x_block * vqd.y_block; // 代表ベクトル数 // 圧縮率 compression_rate=(double)coded_data_size / (double)original_data_size * 100.0; // 後片付け GlobalFree(vqd.cv); return compression_rate; #endif }