基于内容的图像检索-聚类分析

来源:互联网 发布:新手如何经营淘宝 编辑:程序博客网 时间:2024/04/30 13:19

 

//导入必要的包

 

import java.awt.image.BufferedImage;

import javax.imageio.ImageIO;

import java.io.*;

import java.util.Scanner;

import java.util.Arrays;

import javax.swing.*;

import java.awt.*;

 

/**

 *基于k-means的简单图像检索

 * @author xuweibin

 * */

 

 

class CBIR

{

     private File srcFile;    //图像路径

     private boolean bFile;

     private File[] file;    //读入图片文件

       private BufferedImage[] bi;

       private int imNum;     //图像个数

       private int width;     //图像宽度

       private int height;    //图像高度

       private int minx;      //图像最小横坐标

       private int miny;      //图像最小纵坐标

       public int[][] rgb;    //图像rgb颜色值

       private double[][] rate;    //图像频率数组

       private static final int N=65536;    //图像像素个数,256*256,可以智能化

       private static final int M=8;    //颜色级数,可以智能化

       private static final int IN=6;   //图像个数,可以改变

       private static boolean[] flag;   //标记数组

       private int It1;    //初始化簇1

       private int It2;    //初始化簇2

       private double center1[];    //1中心

       private double center2[];    //2中心

     private double dis1;     //到簇1中心的距离

     private double dis2;     //到簇2中心的距离

 

 

   /**

    *在构造函数中初始化

    * */

       public CBIR()

       {

           srcFile=null;

           bFile=false;

           file=null;

           imNum=0;

           width=0;

           height=0;

           minx=0;

           miny=0;

           rgb=null;

           rate=null;

           flag=null;

           It1=It2=-1;

           center1=center2=null;

           dis1=dis2=0;

       }

 

 

   /**

    *读入图像文件流

    * */

    public void readImage()

    {

        srcFile=new File("image/");

        bFile=srcFile.exists();

        if(!bFile||!srcFile.isDirectory()||!srcFile.canRead())

          {

             try{

                   srcFile.createNewFile();

             }catch(IOException e){e.printStackTrace();}

          }

        else

          {

             file=srcFile.listFiles();

             imNum=file.length;

          }

     }

 

 

   /**

    *获得图像的rgb,并转化为亮度值

    * */

    public void getRGB()

    {

           readImage();

           bi=new BufferedImage[imNum];

           for(int i=0;i<imNum;i++)

           {

                 try{

                 bi[i]=ImageIO.read(file[i]);

               }catch(IOException e){System.out.println(e);}

           }

        rgb=new int[imNum][];

        for(int k=0;k<imNum;k++)

        {

                 width=bi[k].getWidth();

                 height=bi[k].getHeight();

                 minx=bi[k].getMinX();

                 miny=bi[k].getMinY();

            rgb[k]=new int[width*height];

            int count=0;

            for(int i=minx;i<width;i++)

              for(int j=miny;j<height;j++)

              {

                        int pixel=bi[k].getRGB(i,j);

                        int r=(pixel&0xff0000)>>16;

                        int g=(pixel&0xff00)>>8;

                        int b=(pixel&0xff);

                        rgb[k][count++]=(int)(r*0.299+g*0.586+b*0.114);    //转化为亮度值

                   }

           }

 

//         for(int i=0;i<imNum;i++)

//           for(int j=0;j<N;j++)

//           {

//             System.out.println(rgb[i][j]);

//           }

 

      }

 

 

   /**

    *获得图像的频率数组

    * */

      public void getRATE()

      {

           getRGB();

           rate=new double[imNum][M];

           for(int j=0;j<imNum;j++)

           {

                 int[] temp=new int[M];

                 for(int i=0;i<M;i++)

                   temp[i]=0;

                 int sum=0;

                 for(int i=0;i<N;i++)

                 {

                if(0<=rgb[j][i]&&rgb[j][i]<32)

                temp[0]++;

                else  if(32<=rgb[j][i]&&rgb[j][i]<64)

                      temp[1]++;

                      else if(64<=rgb[j][i]&&rgb[j][i]<96)

                           temp[2]++;

                           else if(96<=rgb[j][i]&&rgb[j][i]<128)

                                temp[3]++;

                              else if(128<=rgb[j][i]&&rgb[j][i]<160)

                                            temp[4]++;

                                            else if(160<=rgb[j][i]&&rgb[j][i]<192)

                                                 temp[5]++;

                                                 else if(192<=rgb[j][i]&&rgb[j][i]<234)

                                               temp[6]++;

                                               else

                                               temp[7]++;

                sum++;

                 }

                 for(int i=0;i<M;i++)

                 {

                      rate[j][i]=temp[i]/(sum*1.0);

                 }

           }

 

//         for(int i=0;i<imNum;i++)

//         {

//           for(int j=0;j<M;j++)

//             System.out.println(rate[i][j]);

//           System.out.println();

//         }

 

      }

 

 

   /**

    *获得两个频率数组的距离

    * */

      public double getDistance(double[] r1,double[] r2)

      {

           double pe=0;

           for(int i=0;i<M;i++)

           {

                 pe+=Math.abs(r1[i]-r2[i]);   //使用的是曼哈顿距离,也即城市街区距离

           }

           return pe;

      }

 

 

 

   /**

    *获得初始化的簇中心

    * */

    public void getIntial()

    {

           getRATE();

        Scanner input=new Scanner(System.in);

        System.out.print("请输入初始化簇1");

        It1=input.nextInt();

        System.out.print("请输入初始化簇2");

        It2=input.nextInt();

      }

 

 

   /**

    *获得更新后的簇中心

    * */

    public void getCenter(double rt[][],boolean fl[],boolean fg,double center[])

    {

          int temp=0;

          double[] centerTemp=new double[M];

          for(int i=0;i<M;i++)

            centerTemp[i]=0;

        if(fg)

        {

          for(int i=0;i<IN;i++)

            if(fl[i])

            {

                   temp++;

              for(int j=0;j<M;j++)

                centerTemp[j]+=rt[i][j];

                 }

 

          }

          else

          {

          for(int i=0;i<IN;i++)

            if(!fl[i])

            {

                   temp++;

              for(int j=0;j<M;j++)

                centerTemp[j]+=rt[i][j];

                 }

          }

          for(int i=0;i<M;i++)

            center[i]=centerTemp[i]/temp;

      }

 

 

   /**

    *对图像进行k-means聚类

    * */

      public boolean[] cluster()

      {

           getIntial();

           flag=new boolean[IN];

           for(int i=0;i<IN;i++)

           {

                 flag[i]=false;

           }

           flag[It1-1]=false;

           flag[It2-1]=true;

           center1=new double[M];

           center1=(double[])rate[It1-1];

           center2=new double[M];

           center2=(double[])rate[It2-1];

 

//         for(int i=0;i<M;i++)

//         System.out.println(center1[i]);

 

           boolean[] tflag=new boolean[flag.length];

           tflag=(boolean[])flag.clone();

        while(true)

        {

                 for(int i=0;i<IN;i++)

                 {

                dis1=getDistance(center1,rate[i]);

                dis2=getDistance(center2,rate[i]);

                if(dis1>dis2)

                tflag[i]=true;

                else

                tflag[i]=false;

                 }

                 if(Arrays.equals(flag,tflag))

                   break;

                 else

                   {

                  flag=(boolean[])tflag.clone();

                  getCenter(rate,flag,false,center1);

                  getCenter(rate,flag,true,center2);

                   }

           }

           System.out.println();

           System.out.println("聚类结果簇1");

           for(int i=0;i<IN;i++)

           {

                 if(!flag[i])

                 System.out.println(i+1);

           }

           System.out.println("聚类结果簇2");

           for(int i=0;i<IN;i++)

           {

                 if(flag[i])

                 System.out.println(i+1);

           }

           return flag;

      }

 

}

 

 

 

   /**

    *一个简单的UI,使用Gridlayout布局、jLabel容器

    * */

class ImageShow

{

      private Frame f;

      private JLabel bt1;

      private ImageIcon icon1;

    public void show(boolean[] fg,boolean fa)

        {

           if(fa)

           {

             f = new Frame("2");

             f.setLayout (new GridLayout (5, 1));

             for(int i=0;i<fg.length;i++)

             if(fg[i])

          {

               bt1=new JLabel("",JLabel.CENTER);

               bt1.setBorder(BorderFactory.createLineBorder(Color.white,3));

               icon1=new ImageIcon("image/"+(i+1)+".gif");

               bt1.setIcon(icon1);

               f.add(bt1);

               f.setLocation(1000,10);

            }

          }

           else

           {

             f = new Frame("1");

             f.setLayout (new GridLayout (5, 1));

             for(int i=0;i<fg.length;i++)

             if(!fg[i])

          {

               bt1=new JLabel("",JLabel.CENTER);

               bt1.setBorder(BorderFactory.createLineBorder(Color.white,3));

               icon1=new ImageIcon("image/"+(i+1)+".gif");

               bt1.setIcon(icon1);

               f.add(bt1);

               f.setLocation(10,10);

            }

          }

           f.pack();

           f.setSize(400,1000);

        f.setVisible(true);

       }

}

 

 

 

 /**

  *主类调用

  * */

public class XunKang

{

 

      public static void main(String args[])

      {

       CBIR c=new CBIR();

       ImageShow is=new ImageShow();

       boolean[] flag=c.cluster();

       is.show(flag,false);

       is.show(flag,true);

    }

 

}

原创粉丝点击