旋转不变的感知哈希
2016-07-06 00:00
447 查看
摘要: 在感知哈希的基础上添加了类似LBP的旋转不变性(个人实现,旋转不变的灵感就是来自LBP)
[code=language-java]package com.imageretrieval.features; import com.imageretrieval.utils.ImageUtil; /** * 旋转不变的感知哈希<br> * @author VenyoWang * */ public class RHash { 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, 8, 8); // 缩小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; return getFeature(newMatrix, average); } /** * 旋转不变性<br> * @return */ private static String getFeature(int[][] matrix, double average) { // 半径 String featureValue = ""; int[] r = {2, 4, 6, 8}; for(int i = 0; i < 4; i++){ // 正方形左上角的点的下标 int start = (8 - r[i]) / 2; int feature = 0; for(int j = start; j < start + r[i]; j++){ feature = matrix[start][j] < average ? feature<<1 : (feature<<1)+1; } for(int j = start + 1; j < start + r[i]; j++){ feature = matrix[j][start + r[i] - 1] < average ? feature<<1 : (feature<<1)+1; } for(int j = start + r[i] - 2; j >= start; j--){ feature = matrix[start + r[i] - 1][j] < average ? feature<<1 : (feature<<1)+1; } for(int j = start + r[i] - 2; j > start; j--){ feature = matrix[j][start] < average ? feature<<1 : (feature<<1)+1; } featureValue += getMinFeature(feature, 4 * (r[i] - 1)); } return featureValue; } private static String getMinFeature(int feature, int bitNum) { // 位数为bitNum的情况下的最大值 int max = 1; for(int i = 1; i < bitNum; i++){ max = (max << 1) + 1; } int min = feature; for(int i = 0; i < bitNum - 1; i++){ feature = (feature>>1 | feature<<(bitNum - 1)) & max; if(feature < min) min = feature; } String result = ""; for(int i = 0; i < bitNum; i++){ if(min % 2 == 0){ result = "0" + result; } else { result = "1" + result; } min >>= 1; } return result; } 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; } }
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树