pHash的Java实现

此算法中的DCT变换是从 http://blog.csdn.net/luoweifu/article/details/8214959抄过来的,因为这种需要大量的复杂的数学运算,我看不来,完全不懂...都已经还给老师了...

package com.imageretrieval.features;

import com.imageretrieval.utils.ImageUtil;

/**
 * pHash<br>
 * 参考链接:http://blog.csdn.net/zouxy09/article/details/17471401<br>
 * http://blog.csdn.net/luoweifu/article/details/8220992
 * @author VenyoWang
 *
 */
public class PHash {

	public static void main(String[] args) {
		String hash = getFeatureValue("");
		String hash1 = getFeatureValue("");
		System.out.println(hash);
		System.out.println(hash1);
		System.out.println(calculateSimilarity(hash, hash1));
	}

	public static String getFeatureValue(String imagePath) {
		// 缩小尺寸,简化色彩
		int[][] grayMatrix = getGrayPixel(imagePath, 32, 32);
		// 计算DCT
		grayMatrix = DCT(grayMatrix, 32);
		// 缩小DCT,计算平均值
		int[][] newMatrix = new int[8][8];
		double average = 0;
		for(int i = 0; i < 8; i++){
			for(int j = 0; j < 8; j++){
				newMatrix[i][j] = grayMatrix[i][j];
				average += grayMatrix[i][j];
			}
		}
		average /= 64.0;
		// 计算hash值
		String hash = "";
		for(int i = 0; i < 8; i++){
			for(int j = 0; j < 8; j++){
				if(newMatrix[i][j] < average){
					hash += '0';
				}
				else{
					hash += '1';
				}
			}
		}
		return hash;
	}

    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;
	}
	
	/**
	 * 用于计算pHash的相似度<br>
	 * 相似度为1时,图片最相似
	 * @param str1
	 * @param str2
	 * @return
	 */
	public static double calculateSimilarity(String str1, String str2) {
		int num = 0;
		for(int i = 0; i < 64; i++){
			if(str1.charAt(i) == str2.charAt(i)){
				num++;
			}
		}
		return ((double)num) / 64.0;
	}

	/**
	 * 离散余弦变换
	 * @author luoweifu 
	 * 
	 * @param pix
	 *            原图像的数据矩阵
	 * @param n
	 *            原图像(n*n)的高或宽
	 * @return 变换后的矩阵数组
	 */
	public static int[][] DCT(int[][] pix, int n) {
		double[][] iMatrix = new double[n][n];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				iMatrix[i][j] = (double) (pix[i][j]);
			}
		}
		double[][] quotient = coefficient(n); // 求系数矩阵
		double[][] quotientT = transposingMatrix(quotient, n); // 转置系数矩阵

		double[][] temp = new double[n][n];
		temp = matrixMultiply(quotient, iMatrix, n);
		iMatrix = matrixMultiply(temp, quotientT, n);
		
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				pix[i][j] = (int) (iMatrix[i][j]);
			}
		}
		return pix;
	}

	/**
	 * 求离散余弦变换的系数矩阵
	 * @author luoweifu 
	 * 
	 * @param n
	 *            n*n矩阵的大小
	 * @return 系数矩阵
	 */
	private static double[][] coefficient(int n) {
		double[][] coeff = new double[n][n];
		double sqrt = 1.0 / Math.sqrt(n);
		for (int i = 0; i < n; i++) {
			coeff[0][i] = sqrt;
		}
		for (int i = 1; i < n; i++) {
			for (int j = 0; j < n; j++) {
				coeff[i][j] = Math.sqrt(2.0 / n) * Math.cos(i * Math.PI * (j + 0.5) / (double) n);
			}
		}
		return coeff;
	}

	/**
	 * 矩阵转置
	 * @author luoweifu 
	 * 
	 * @param matrix
	 *            原矩阵
	 * @param n
	 *            矩阵(n*n)的高或宽
	 * @return 转置后的矩阵
	 */
	private static double[][] transposingMatrix(double[][] matrix, int n) {
		double nMatrix[][] = new double[n][n];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				nMatrix[i][j] = matrix[j][i];
			}
		}
		return nMatrix;
	}

	/**
	 * 矩阵相乘
	 * @author luoweifu 
	 * 
	 * @param A
	 *            矩阵A
	 * @param B
	 *            矩阵B
	 * @param n
	 *            矩阵的大小n*n
	 * @return 结果矩阵
	 */
	private static double[][] matrixMultiply(double[][] A, double[][] B, int n) {
		double nMatrix[][] = new double[n][n];
		int t = 0;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				t = 0;
				for (int k = 0; k < n; k++) {
					t += A[i][k] * B[k][j];
				}
				nMatrix[i][j] = t;
			}
		}
		return nMatrix;
	}
}

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏数值分析与有限元编程

有限元 | 三次样条梁单元

样条梁单元是样条函数与有限元法相结合的产物。有限元法将结构分割成若干单元,位移场采用分段插值或者分区插值。常用的插值方法有Lagrange插值,Hermite插...

40560
来自专栏软件开发 -- 分享 互助 成长

最小生成树-Prim算法和Kruskal算法

Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里...

702100
来自专栏PPV课数据科学社区

【工具】SAS 常用函数汇总

? 一、数学函数 ABS(x) 求x的绝对值。 MAX(x1,x2,…,xn) 求所有自变量中的最大一个。 MIN(x1,x2,…,xn) 求所有自变量...

28430
来自专栏文武兼修ing——机器学习与IC设计

基于sklearn的决策树分类器理论基础代码实现

理论基础 决策树 决策树是一种树形结构的机器学习算法,所有的样本起始于根节点,每个具有子节点的父节点都有一个判断,根据判断结果将样本向子节点分流,测试样本从根节...

47280
来自专栏尾尾部落

小白的机器学习实战——向量,矩阵和数组 小白的机器学习实战——向量,矩阵和数组

16640
来自专栏书山有路勤为径

CNN层和特征可视化VGG-16

CNN由处理视觉信息的层组成。CNN首先接收输入图像,然后将其传递通过这些层。有几种不同类型的层:最常用的层:卷积,池化和完全连接的层。 首先,让我们来看看完...

1.9K20
来自专栏Deep learning进阶路

OpenCV 学习日记(三)--- 常见数据类型

OpenCV基本数据类型: CvPoint,这些结构中最简单的一个,包含两个整型变量x和y。 CvPoint还有两个兄弟:CvPoint2D32f 和 CvPo...

24700
来自专栏专知

【论文推荐】最新6篇机器翻译相关论文—词性和语义标注任务、变分递归神经机器翻译、文学语料、神经后缀预测、重构模型

【导读】专知内容组整理了最近六篇机器翻译(Machine Translation)相关文章,为大家进行介绍,欢迎查看! 1. Evaluating Layers...

49060
来自专栏机器学习算法与Python学习

机器学习(34)之BIRCH层次聚类详解

关键字全网搜索最新排名 【机器学习算法】:排名第一 【机器学习】:排名第一 【Python】:排名第三 【算法】:排名第四 前言 在K-Means算法(机器学习...

47650
来自专栏人工智能LeadAI

机器学习实战 | 第四章:模型验证和选择

模型选择和评估主要是在sklearn.model_selection这个模块里面.这里只会列出概述和常见函数的用法,更加详细的可以到sklearn.model_...

41650

扫码关注云+社区

领取腾讯云代金券