K-means法と画像の階調分類
K-means法とは類似したデータをいくつかのグループに分類するアルゴリズムの一つです。このアルゴリズムを利用して、画像の減色処理を行うプログラムを作りました。
この画像処理のコードについて、昔作ったjavaのコードですが引っ張り出してきました。
public static BufferedImage ClasterUse(BufferedImage read,int CLASTNUM,boolean t) { long start = System.currentTimeMillis(); BufferedImage out = new BufferedImage(read.getWidth(),read.getHeight(),BufferedImage.TYPE_INT_RGB); int width=read.getWidth(),height=read.getHeight(),obj[]=new int[3],i,x,y,j,k,index=0,avg[][]=new int[CLASTNUM][3],temp=0,c=0; int[][] claster = new int[width][height]; boolean flag=true; double min,tmp=0; int num[] = new int[CLASTNUM]; short clascolor[][] = new short[CLASTNUM][3]; short[][][] image= CreateImagearray(read); for(i= 0;i<CLASTNUM;i++) for(j=0;j<3;j++) clascolor[i][j] = (short) (255*Math.random()); do{ Arrays.fill(num,0); flag = true; for(i=0;i<CLASTNUM;i++) for(j=0;j<3;j++) avg[i][j] = 0; for(x=0;x<width;x++){ for(y=0;y<height;y++){ min=-1; for(i=0;i<CLASTNUM;i++) if(min > (tmp = Math.pow((double)(clascolor[i][0]-image[x][y][0]),2)+Math.pow((double)(clascolor[i][1]-image[x][y][1]),2)+Math.pow((double)(clascolor[i][2]-image[x][y][2]),2)) || min==-1 ){ min = tmp; index = i; } claster[x][y] = index; } } for(x=0;x<width;x++) for(y=0;y<height;y++){ for(k=0;k<3;k++) avg[claster[x][y]][k] += image[x][y][k]; num[claster[x][y]]++; } for(i=0;i<CLASTNUM;i++) for(k=0;k<3;k++){ if(num[i] == 0) continue; if(clascolor[i][k] != (temp = avg[i][k]/num[i])) flag = false; clascolor[i][k] = (short)temp; } }while( !flag); for(x=0;x<width;x++){ for(y=0;y<height;y++){ for(j=0;j<3;j++) obj[j] = clascolor[claster[x][y]][j]; out.setRGB(x,y,RGBtoint(obj)); } } long end = System.currentTimeMillis(); System.out.println((end - start) + "ms"); return out; }
実行結果
元画像
8色
4色
各ピクセルのRGBでのユークリッド距離をいくつかのクラスタと比較して最近傍法です。画像処理のプログラムとしても、なかなか時間がかかるものとなっています。