package com.imageretrieval.features;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.imageretrieval.utils.Coordinate;
import com.imageretrieval.utils.ImageUtil;
import com.imageretrieval.utils.Util;
/**
* 环形颜色分布直方图<br>
* 参考文献:<br>
* http://wenku.baidu.com/link?url=bWfVkM-oyUn7cJuCnhICReeByt2XR-MUx07J-
* 1pXvBz7UKzoe4iGmH4S-8j4MiuAXyzetBV7NEDwJC7BBjT8ecCpHvo7oSBNChO0gLJMhI7<br>
* http://wenku.baidu.com/link?url=s13-4JCwPWfHsnv1EKXcScLNs06-NEN2gBG-
* oFpKL4VvFOy1r5lznMJg9rQ2dWvbzXiSoEOO_Oge0THJZF6nEedJG5hJtAGZm-cyNqSoEZW<br>
*
* @author VenyoWang
*
*/
public class AnnularColorLayoutHistogram {
/** 同心圆个数 */
private static int N = 10;
public static void main(String[] args) {
int[][] nums = getFeatureMatrix("");
int[][] nums1 = getFeatureMatrix("");
System.out.println(calculateSimilarity(Util.matrix2vector(nums), Util.matrix2vector(nums1)));
}
public static int[][] getFeatureMatrix(String imagePath) {
// 获取灰度矩阵
int[][] matrix = getGrayPixel(imagePath, 200, 200);
// 根据灰度值对像素点进行分组
Map<Integer, List<Coordinate>> groupedPixels = new HashMap<Integer, List<Coordinate>>();
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
List<Coordinate> list = null;
if (groupedPixels.containsKey(matrix[i][j])) {
list = groupedPixels.get(matrix[i][j]);
} else {
list = new ArrayList<Coordinate>();
}
Coordinate coordinate = new Coordinate();
coordinate.x = i;
coordinate.y = j;
list.add(coordinate);
groupedPixels.put(matrix[i][j], list);
}
}
// 为不同的灰度值计算质心
Coordinate[] centroid = new Coordinate[256];
for (int i = 0; i <= 255; i++) {
if (groupedPixels.containsKey(i)) {
List<Coordinate> list = groupedPixels.get(i);
double x = 0, y = 0;
for (int j = 0; j < list.size(); j++) {
Coordinate coordinate = list.get(j);
x += coordinate.x;
y += coordinate.y;
}
x = x / list.size();
y = y / list.size();
Coordinate coordinate = new Coordinate();
coordinate.x = x;
coordinate.y = y;
centroid[i] = coordinate;
}
}
// 为每一个像素计算其到质心的距离
double[][] distances = new double[matrix.length][matrix[0].length];
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
Coordinate coordinate = centroid[matrix[i][j]];
distances[i][j] = Math.sqrt(Math.pow(i - coordinate.x, 2) + Math.pow(j - coordinate.y, 2));
}
}
// 比较出最大距离
double[] maxDistances = new double[256];
for (int i = 0; i <= 255; i++) {
if (groupedPixels.containsKey(i)) {
List<Coordinate> list = groupedPixels.get(i);
double max = 0;
for (int j = 0; j < list.size(); j++) {
Coordinate coordinate = list.get(j);
double distance = distances[(int) coordinate.x][(int) coordinate.y];
if (distance > max) {
max = distance;
}
}
maxDistances[i] = max;
}
}
// 统计以不同距离为半径的同心圆内包含的像素数量
int[][] nums = new int[256][AnnularColorLayoutHistogram.N];
for (int i = 0; i <= 255; i++) {
for (int j = 1; j <= AnnularColorLayoutHistogram.N; j++) {
double minDis = maxDistances[i] * (j - 1) / AnnularColorLayoutHistogram.N;
double maxDis = maxDistances[i] * j / AnnularColorLayoutHistogram.N;
// 第一个同心圆的取值范围必须为[0, maxDis * j / n]
// 必须包含0,因为有可能存在像素点和质心重叠的情况
if (j == 1) {
minDis = -1;
}
List<Coordinate> list = groupedPixels.get(i);
int num = 0;
if (list == null)
continue;
for (int k = 0; k < list.size(); k++) {
Coordinate coordinate = list.get(k);
double dis = distances[(int) coordinate.x][(int) coordinate.y];
if (dis > minDis && dis <= maxDis) {
num++;
}
}
nums[i][j - 1] = num;
}
}
return nums;
}
public static double calculateSimilarity(int[] vector, int[] vector1) {
double len = 0, len1 = 0, numerator = 0;
for (int i = 0; i < vector.length; i++) {
len += Math.pow(vector[i], 2);
len1 += Math.pow(vector1[i], 2);
numerator += vector[i] * vector1[i];
}
len = Math.sqrt(len);
len1 = Math.sqrt(len1);
return numerator / (len * len1);
}
public static Pixel[][] getImagePixel(String imagePath, int width, int height) {
BufferedImage bi = null;
try {
bi = resizeImage(imagePath, width, height, BufferedImage.TYPE_INT_RGB);
} catch (Exception e) {
e.printStackTrace();
return null;
}
int minx = bi.getMinX();
int miny = bi.getMinY();
Pixel[][] rgbMatrix = new Pixel[width - minx][height - miny];
for (int i = minx; i < width; i++) {
for (int j = miny; j < height; j++) {
int pixel = bi.getRGB(i, j);
int red = (pixel & 0xff0000) >> 16;
int green = (pixel & 0xff00) >> 8;
int blue = (pixel & 0xff);
Pixel p = new Pixel();
p.red = red;
p.green = green;
p.blue = blue;
rgbMatrix[i - minx][j - miny] = p;
}
}
return rgbMatrix;
}
public static BufferedImage resizeImage(String srcImgPath, int width, int height, int imageType)
throws IOException {
File srcFile = new File(srcImgPath);
BufferedImage srcImg = ImageIO.read(srcFile);
BufferedImage buffImg = null;
buffImg = new BufferedImage(width, height, imageType);
buffImg.getGraphics().drawImage(srcImg.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
return buffImg;
}
}
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有