专栏首页Venyo 的专栏颜色聚合向量

颜色聚合向量

package com.imageretrieval.features;

/**
 * 颜色聚合向量<br>
 * 参考链接:http://www.docin.com/p-396527256.html
 * 
 * @author VenyoWang
 *
 */
public class ColorCoherenceVector {
	private static int BIN_WIDTH = 4;

	public static void main(String[] args) {
		int[][] matrix = getFeatureMatrix("");
		int[][] matrix1 = getFeatureMatrix("");
		System.out.println(calculateSimilarity(matrix2vector(matrix), Util.matrix2vector(matrix1)));
	}

	public static int[][] getFeatureMatrix(String imagePath) {
		// 均匀量化
		int[][] grayMatrix = getGrayPixel(imagePath, 200, 200);
		int width = grayMatrix[0].length;
		int height = grayMatrix.length;
		for(int i = 0; i < height; i++){
			for(int j = 0; j < width; j++){
				grayMatrix[i][j] /= ColorCoherenceVector.BIN_WIDTH;
			}
		}

		// 划分连通区域
		int[][] groupNums = new int[grayMatrix.length][grayMatrix[0].length];
		int groupNum = groupMatrix(grayMatrix, groupNums);

		// 判断聚合性
		// 统计每个分组下的像素数
		int[] groupCount = new int[groupNum];
		for(int i = 0; i < height; i++){
			for(int j = 0; j < width; j++){
				groupCount[groupNums[i][j]]++;
			}
		}
		
		// 阈值
		int threshold = width * height / 100;
		for(int i = 0; i < groupNum; i++){
			if(groupCount[i] < threshold){
				// 0表示非聚合
				groupCount[i] = 0;
			}
			else{
				// 1表示聚合
				groupCount[i] = 1;
			}
		}
		
		for(int i = 0; i < height; i++){
			for(int j = 0; j < width; j++){
				groupNums[i][j] = groupCount[groupNums[i][j]];
			}
		}

		// 计算图像特征
		int[][] feature = new int[256 / ColorCoherenceVector.BIN_WIDTH][2];
		for(int i = 0; i < height; i++){
			for(int j = 0; j < width; j++){
				if(groupNums[i][j] == 0){
					feature[grayMatrix[i][j] / ColorCoherenceVector.BIN_WIDTH][0]++;
				}
				else {
					feature[grayMatrix[i][j] / ColorCoherenceVector.BIN_WIDTH][1]++;
				}
			}
		}

		return feature;
	}
	
	private static int groupMatrix(int[][] matrix, int[][] groupNums) {
		for(int i = 0; i < groupNums.length; i++){
			for(int j = 0; j < groupNums[0].length; j++){
				groupNums[i][j] = -1;
			}
		}
		
		int groupNum = 0;
		for(int i = 0; i < groupNums.length; i++){
			for(int j = 0; j < groupNums[0].length; j++){
				if(groupNums[i][j] < 0){
					// 该像素点未进行分组,对其进行分组
					groupNums[i][j] = groupNum;
					recursive(matrix, i, j, groupNum, groupNums);
					groupNum++;
				}
			}
		}
		return groupNum + 1;
	}
	
	private static void recursive(int[][] matrix, int i, int j, int groupNum, int[][] groupNums){
		int num = matrix[i][j];
		int x = i - 1, y = j - 1;
		int maxX = matrix.length, maxY = matrix[0].length;
		if(x >= 0 && y >= 0 && x < maxX && y < maxY && groupNums[x][y] < 0 && matrix[x][y] == num){
			groupNums[x][y] = groupNum;
			recursive(matrix, x, y, groupNum, groupNums);
		}
		y = j;
		if(x >= 0 && y >= 0 && x < maxX && y < maxY && groupNums[x][y] < 0 && matrix[x][y] == num){
			groupNums[x][y] = groupNum;
			recursive(matrix, x, y, groupNum, groupNums);
		}
		y = j + 1;
		if(x >= 0 && y >= 0 && x < maxX && y < maxY && groupNums[x][y] < 0 && matrix[x][y] == num){
			groupNums[x][y] = groupNum;
			recursive(matrix, x, y, groupNum, groupNums);
		}
		x = i;y = j - 1;
		if(x >= 0 && y >= 0 && x < maxX && y < maxY && groupNums[x][y] < 0 && matrix[x][y] == num){
			groupNums[x][y] = groupNum;
			recursive(matrix, x, y, groupNum, groupNums);
		}
		y = j + 1;
		if(x >= 0 && y >= 0 && x < maxX && y < maxY && groupNums[x][y] < 0 && matrix[x][y] == num){
			groupNums[x][y] = groupNum;
			recursive(matrix, x, y, groupNum, groupNums);
		}
		x = i + 1;y = j - 1;
		if(x >= 0 && y >= 0 && x < maxX && y < maxY && groupNums[x][y] < 0 && matrix[x][y] == num){
			groupNums[x][y] = groupNum;
			recursive(matrix, x, y, groupNum, groupNums);
		}
		y = j;
		if(x >= 0 && y >= 0 && x < maxX && y < maxY && groupNums[x][y] < 0 && matrix[x][y] == num){
			groupNums[x][y] = groupNum;
			recursive(matrix, x, y, groupNum, groupNums);
		}
		y = j + 1;
		if(x >= 0 && y >= 0 && x < maxX && y < maxY && groupNums[x][y] < 0 && matrix[x][y] == num){
			groupNums[x][y] = groupNum;
			recursive(matrix, x, y, groupNum, groupNums);
		}
	}

    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 int[][] getGrayPixel(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();
		int[][] matrix = new int[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);
				int gray = (int) (red * 0.3 + green * 0.59 + blue * 0.11);
				matrix[i][j] = gray;
			}
		}
		return matrix;
	}

    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;
	}

    public static int[] matrix2vector(int[][] matrix){
		if(matrix.length <= 0 || matrix[0].length <= 0){
			return null;
		}
		int[] vector = new int[matrix.length * matrix[0].length];
		int index = 0;
		for(int i = 0; i < matrix.length; i++){
			for(int j = 0; j < matrix[0].length; j++, index++){
				vector[index] = matrix[i][j];
			}
		}
		return vector;
	}
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • RBG颜色直方图

    package com.imageretrieval.features; import java.awt.Color; import com.imagere...

    Venyo
  • pHash的Java实现

    此算法中的DCT变换是从 http://blog.csdn.net/luoweifu/article/details/8214959抄过来的,因为这种需要大量的...

    Venyo
  • 旋转不变的感知哈希

    package com.imageretrieval.features; import com.imageretrieval.utils.ImageUtil;...

    Venyo
  • 【USACO 3.2】Magic Squares

    4*2个格子分别为 1234 8765 的魔板有3种操作,A:上下两排互换,B:最后一列放到第一列前面,C:中间四个顺时针旋转1格。 现在给出目标状态,...

    饶文津
  • 弱校联盟10.3

    n对括号最多需要1+2+..+n次交换,当它是)))..(((的形式时,)))(((需要6次,然后把中间两个交换一下,))()((就还需要5次,再交换一次靠近左...

    饶文津
  • 2018 团队设计天梯赛题解---华山论剑组

    2018 年度的团队设计天梯赛前几天结束了。但是成绩真的是惨不忍睹。。。毕竟是团队的比赛,如果团队平均水平不高的话,单凭一个人,分再高也很难拉起来(当然,一个人...

    指点
  • loj#6031. 「雅礼集训 2017 Day1」字符串(SAM 广义SAM 数据分治)

    考虑K比较小的情况,可以直接暴力建SAM, 枚举w的子串算出现次数。询问用个 的vector记录一下每次在vector里二分就好。

    attack
  • 洛谷P4723 【模板】线性递推(多项式取模 线性代数)

    attack
  • BZOJ2535: [Noi2010]Plane 航空管制2(拓扑排序 贪心)

    首先不难想到拓扑排序,但是直接对原图按\(k\)从小到大拓扑排序是错的。因为当前的\(k\)大并不意味着后面的点\(k\)也大

    attack
  • 牛客小白月赛11D(分治、RMQ)

    定义一个玄学节点叫做 R,每次操作读入 val ,执行 Insert(R,val)。

    ACM算法日常

扫码关注云+社区

领取腾讯云代金券