CCVで画像同士の距離が取れたってことは、画像同士どれが近いかというマップができるよね。
ソースはこんな感じで
import java.awt.*; import java.awt.geom.Point2D; import java.awt.image.BufferedImage; import java.io.*; import java.util.*; import java.util.List; import javax.imageio.ImageIO; import javax.swing.*; public class ColorCoherenceVectorMap extends javax.swing.JFrame { /** Creates new form ColorCoherenceVectorMap */ public ColorCoherenceVectorMap() { setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); setBounds((screenSize.width-800)/2, (screenSize.height-600)/2, 800, 600); readFile(new File("C:\\search")); final int[][] dists = new int[images.size()][images.size()]; for(int i = 0; i < images.size(); ++i){ int[] ccv1 = images.get(i).getValue(); for(int j = i + 1; j < images.size(); ++j){ int[] ccv2 = images.get(j).getValue(); int total = 0; for(int k = 0; k < ccv1.length; ++k){ total += Math.abs(ccv1[k] - ccv2[k]); } dists[i][j] = total; dists[j][i] = total; } } final BufferedImage img = new BufferedImage(800, 600, BufferedImage.TYPE_INT_RGB); final JComponent comp = new JComponent() { @Override protected void paintComponent(Graphics g) { g.drawImage(img, 0, 0, this); } }; add(comp); final Point2D[] pos = new Point2D[images.size()]; Random r = new Random(); final Image[] thumbs = new Image[pos.length]; int limit = 40; for(int i = 0; i < pos.length; ++i){ pos[i] = new Point2D.Double(r.nextInt(800), r.nextInt(600)); try { BufferedImage im = ImageIO.read(new File(images.get(i).getKey())); int w = im.getWidth(); int h = im.getHeight(); if(w > h){ h = limit * h / w; w = limit; }else{ w = limit * w / h; h = limit; } BufferedImage imt = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics2D g = (Graphics2D) imt.getGraphics(); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.drawImage(im, 0, 0, w, h, this); g.dispose(); thumbs[i] = imt; } catch (IOException ex) { } } new Thread(){ @Override public void run() { long t = System.currentTimeMillis(); for(;;){ for(int i = 0; i < pos.length; ++i){ for(int j = 0; j < pos.length; ++j){ if(i == j) continue; double dx = pos[i].getX() - pos[j].getX(); double dy = pos[i].getY() - pos[j].getY(); if(dx == 0 && dy == 0){ pos[i].setLocation(pos[i].getX() + 1, pos[i].getY() + 1); dx = 1; dy = 1; } double d = Math.sqrt(dx * dx + dy * dy); int nd = dists[i][j] / 8 + 15; dx = (int)(dx * 2 / d); dy = (int)(dy * 2 / d); if(d > nd){ pos[i].setLocation(pos[i].getX() - dx, pos[i].getY() - dy); }else{ pos[i].setLocation(pos[i].getX() + dx, pos[i].getY() + dy); } } } double mdx = 0; double mdy = 0; for(int i = 0; i < pos.length; ++i){ mdx += pos[i].getX(); mdy += pos[i].getY(); } mdx = 400 - mdx / pos.length; mdy = 300 - mdy / pos.length; for(int i = 0; i < pos.length; ++i){ pos[i].setLocation(pos[i].getX() + mdx, pos[i].getY() + mdy); } long nt = System.currentTimeMillis(); if(nt - t > 200){ t = nt; Graphics2D g = (Graphics2D) img.getGraphics(); g.setColor(Color.WHITE); g.fillRect(0, 0, 800, 600); g.setColor(Color.BLACK); for(int i = 0; i < pos.length; ++i){ g.drawImage(thumbs[i], (int)pos[i].getX(), (int)pos[i].getY(), ColorCoherenceVectorMap.this); } g.dispose(); comp.repaint(); } } } }.start(); } //ファイルのCCVを求める private void readFile(File f){ if(f.isDirectory()){ File[] files = f.listFiles(); for(File file : files){ readFile(file); } }else{ try { BufferedImage img = ImageIO.read(f); if(img == null) return; int[] data = colorCoherenceVector(img); images.add(new AbstractMap.SimpleEntry(f.getCanonicalPath(), data)); } catch (IOException ex) { System.out.println(ex.getMessage()); } } } List<Map.Entry<String, int[]>> images = new ArrayList<Map.Entry<String, int[]>>(); /** CCVを求める */ public static int[] colorCoherenceVector(BufferedImage imgsrc){ int w = imgsrc.getWidth(); int h = imgsrc.getHeight(); //サイズ正規化 int limit = 200; if(w < h){ w = w * limit / h; h = limit; }else{ h = h * limit / w; w = limit; } BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics2D grp = (Graphics2D) img.getGraphics(); grp.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); grp.drawImage(imgsrc, 0, 0, w, h, null); grp.dispose(); //ガウシアンフィルタ int[] ctemp = img.getRGB(0, 0, w, h, null, 0, w); int[] ctbl = new int[ctemp.length]; int[][] filter = { {1, 2, 1}, {2, 4, 2}, {1, 2, 1}}; for(int y = 0; y < h; ++y){ for(int x = 0; x < w; ++x){ int tr = 0; int tg = 0; int tb = 0; int t = 0; for(int i = -1; i < 2; ++i){ for(int j = -1; j < 2; ++j){ if(y + i < 0) continue; if(x + j < 0) continue; if(y + i >= h) continue; if(x + j >= w) continue; t += filter[i + 1][j + 1]; int adr = (x + j) + (y + i) * w; tr += filter[i + 1][j + 1] * ((ctemp[adr] >> 16) & 255); tg += filter[i + 1][j + 1] * ((ctemp[adr] >> 8) & 255); tb += filter[i + 1][j + 1] * ( ctemp[adr] & 255); } } ctbl[x + y * w] = ((tr / t) << 16) + ((tg / t) << 8) + tb / t; } } //減色 for(int i = 0; i < ctbl.length; ++i){ int r = (ctemp[i] >> 16) & 192; int g = (ctemp[i] >> 8) & 192; int b = ctemp[i] & 192; ctbl[i] = (r << 16) + (g << 8) + b; } //タグ付け int[][] lbl = new int[w][h]; int id = 0; for(int y = 0; y < h; ++y){ for(int x = 0; x < w; ++x){ int col = ctbl[y * w + x]; if(y > 0){ if(x > 0){ if(ctbl[(y - 1) * w + x - 1] == col){ //左上と一緒 lbl[x][y] = lbl[x - 1][y - 1]; continue; } } if(ctbl[(y - 1) * w + x] == col){ //上と一緒 lbl[x][y] = lbl[x][y - 1]; continue; } if(x < w - 1){ if(ctbl[(y - 1) * w + x + 1] == col){ //右上と一緒 lbl[x][y] = lbl[x + 1][y - 1]; continue; } } } if(x > 0){ if(ctbl[y * w + x - 1] == col){ //左と一緒 lbl[x][y] = lbl[x - 1][y]; continue; } } lbl[x][y] = id; ++id; } } //集計 int[] count = new int[id]; int[] color = new int[id]; for(int x = 0; x < w; ++x){ for(int y = 0; y < h; ++y){ count[lbl[x][y]]++; color[lbl[x][y]] = ctbl[y * w + x]; } } int[] data = new int[129]; for(int i = 0; i < id; ++i){ int d = color[i]; color[i] = (((d >> 22) & 3) << 4) + (((d >> 14) & 3) << 2) + ((d >> 6) & 3); if(count[i] < 20){ data[color[i] * 2 + 1] ++; }else{ data[color[i] * 2] ++; } } return data; } /** * @param args the command line arguments */ public static void main(String args[]) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new ColorCoherenceVectorMap().setVisible(true); } }); } }