文档章节

环形颜色分布直方图

VenyoWang
 VenyoWang
发布于 2016/07/06 17:35
字数 696
阅读 86
收藏 0
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;
	}
}

 

© 著作权归作者所有

VenyoWang
粉丝 9
博文 36
码字总数 14111
作品 0
程序员
私信 提问
几种图像检索中的图像特征提取算法

本人由于某些原因,决定自己实现一个图像检索框架,目前处于最开始的阶段,现在正在实现一些图像特征提取算法,由于本人基础知识薄弱,看了别人的博客、论文等资料也无法很好地了解算法的精髓...

VenyoWang
2016/07/06
1K
1
opencv 直方图匹配 图片颜色迁移

两张原始图片,相互迁移颜色 结果 因为直方图可以表示颜色的分布情况,而通过直方图匹配算法可以将一幅图像的直方图分布复制给另一副图,从而让目标图像拥有原始图像信息 首先计算src与目标图...

阿豪boy
2018/08/25
15
0
9- OpenCV+TensorFlow 入门人工智能图像处理-8- OpenCV+TensorFlow 入门人工智能图像处理-图像修复

图像美化 案例1: 直方图 案例2: 直方图均衡化 案例3: 亮度增强 案例4: 磨皮美白 案例5: 图片滤波 案例6: 高斯滤波 颜色等级的直方图。 图片滤波 这一章节所有的知识点都比较复杂,也就是难度...

天涯明月笙
2018/05/08
0
0
Metal图像处理——直方图均衡化

前言 Metal入门教程总结 正文 核心思路 首先,我们用直方图来表示一张图像:横坐标代表的是颜色值,纵坐标代表的是该颜色值在图像中出现次数。 如图,对于某些图像,可能出现颜色值集中分布在...

落影loyinglin
2018/08/31
0
0
图像直方图与直方图均衡化

图像直方图(英语:Image Histogram)是用以表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素数。可以借助观察该直方图了解需要如何调整亮度分布。这种直方图中,横坐标的左侧...

Tony沈哲
2017/05/22
0
0

没有更多内容

加载失败,请刷新页面

加载更多

关于运维,该怎么决定它的方向,这个似工作又似兴趣的存在

我之前主要从事网络、桌面、机房管理等相关工作,这些工作使我迷惘,这应该是大多数运维人都经历过的过程; 18年国庆,我从国内前三的消费金融公司裸辞,下海创业,就是想要摆脱这样的困境。...

网络小虾米
18分钟前
4
0
Java Timer的用法

Timer timer = new Timer(); timer.schedule(new TimerTask() { public void run() { System.out.println("11232"); } }, 200000 , 1000); public void schedule(TimerTask task, long delay......

林词
22分钟前
4
0
使用js动态加载外部js文件以及动态创建script脚本

动态脚本指的是在页面加载时不存在,但将来的某一时刻通过修改该DOM动态添加的脚本。和操作HTML元素一样,创建动态脚本也有两种方式:插入外部文件和直接插入JavaScript代码。 动态加载外的外...

Bing309
30分钟前
3
0
从零开始入门 K8s | Kubernetes 网络概念及策略控制

作者 | 阿里巴巴高级技术专家 叶磊 一、Kubernetes 基本网络模型 本文来介绍一下 Kubernetes 对网络模型的一些想法。大家知道 Kubernetes 对于网络具体实现方案,没有什么限制,也没有给出特...

阿里巴巴云原生
34分钟前
3
0
天气获取

本文转载于:专业的前端网站➨天气获取 $.get("http://wthrcdn.etouch.cn/WeatherApi", { citykey: cityCode }, function (d) { //创建文档对象 var parser = new ......

前端老手
34分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部