pHash的Java实现
时间:2022-05-04
本文章向大家介绍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;
}
}
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Nginx安装lua-nginx-module模块
- IPinfo 多接口IP查询工具源码
- 教你CentOS7下如何更换内核安装BBR加速
- we-extract解析和采集微信公众号文章的账号及内容必备工具
- android九宫格可分页加载控件使用详解
- WordPress用插件实现MarkDown语法支持
- Android中实现长按照片弹出右键菜单功能的实例代码
- Android Studio无法执行Java类的main方法问题及解决方法
- PlayTube优秀的视频CMS系统/支持本地和youtube导入
- Android Studio 中运行 groovy 程序的方法图文详解
- android studio按钮监听的5种方法实例详解
- AndroidStudio3.6.1打包jar及AndroidStudio4.0打包jar的一系列问题及用法
- 教你如何在js中split函数分割字符串为数组
- [折腾]小型HTTP web服务Caddy及配置PHP
- graftcp一种把指定程序的 TCP 流量重定向到代理的方法