LIRe图像检索:Tamura纹理特征算法源码分析

2023-10-23 19:51

本文主要是介绍LIRe图像检索:Tamura纹理特征算法源码分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 Tamura概述

Tamura纹理特征包括了粗糙度(coarseness)、对比度(contrast)、方向度(directionality)、线性度(linelikeness)、规则度(regularity)、粗略度(roughness)。最原始的Tamura论文有《Textural Features Correspondingto Visual Perception》。Tamura纹理特征要比灰度共生矩阵得到的纹理特征更直观,在视觉效果上更有优势。LIRe实现了Tamura纹理特征,包括粗糙度、对比度和方向。

2 源码分析

在lire.jar中Tamura源码的位置如下:


以下为我对源码的分析和解读。

public class Tamura implements GlobalFeature {private static final int MAX_IMG_HEIGHT = 64;private int[][] grayScales;private int imgWidth;private int imgHeight;private double[] histogram;private static final double[][] filterH = new double[][]{{-1.0D, 0.0D, 1.0D}, {-1.0D, 0.0D, 1.0D}, {-1.0D, 0.0D, 1.0D}};private static final double[][] filterV = new double[][]{{-1.0D, -1.0D, -1.0D}, {0.0D, 0.0D, 0.0D}, {1.0D, 1.0D, 1.0D}};private static final String TAMURA_NAME = "tamura";public Tamura() {}//第一个指标coarseness 粗糙度public double coarseness(int n0, int n1) {double result = 0.0D;for(int i = 1; i < n0 - 1; ++i) {for(int j = 1; j < n1 - 1; ++j) {result += Math.pow(2.0D, (double)this.sizeLeadDiffValue(i, j));}}result = 1.0D / (double)(n0 * n1) * result;return result;}public double averageOverNeighborhoods(int x, int y, int k) {double result = 0.0D;double border = Math.pow(2.0D, (double)(2 * k));boolean x0 = false;boolean y0 = false;for(int i = 0; (double)i < border; ++i) {for(int j = 0; (double)j < border; ++j) {int var12 = x - (int)Math.pow(2.0D, (double)(k - 1)) + i;int var13 = y - (int)Math.pow(2.0D, (double)(k - 1)) + j;if(var12 < 0) {var12 = 0;}if(var13 < 0) {var13 = 0;}if(var12 >= this.imgWidth) {var12 = this.imgWidth - 1;}if(var13 >= this.imgHeight) {var13 = this.imgHeight - 1;}result += (double)this.grayScales[var12][var13];}}result = 1.0D / Math.pow(2.0D, (double)(2 * k)) * result;return result;}public double differencesBetweenNeighborhoodsHorizontal(int x, int y, int k) {double result = 0.0D;result = Math.abs(this.averageOverNeighborhoods(x + (int)Math.pow(2.0D, (double)(k - 1)), y, k) - this.averageOverNeighborhoods(x - (int)Math.pow(2.0D, (double)(k - 1)), y, k));return result;}public double differencesBetweenNeighborhoodsVertical(int x, int y, int k) {double result = 0.0D;result = Math.abs(this.averageOverNeighborhoods(x, y + (int)Math.pow(2.0D, (double)(k - 1)), k) - this.averageOverNeighborhoods(x, y - (int)Math.pow(2.0D, (double)(k - 1)), k));return result;}public int sizeLeadDiffValue(int x, int y) {double result = 0.0D;int maxK = 1;for(int k = 0; k < 3; ++k) {double tmp = Math.max(this.differencesBetweenNeighborhoodsHorizontal(x, y, k), this.differencesBetweenNeighborhoodsVertical(x, y, k));if(result < tmp) {maxK = k;result = tmp;}}return maxK;}//第二个指标Contrast,对比度public double contrast() {double result = 0.0D;double my4 = 0.0D;double alpha4 = 0.0D;double my = this.calculateMy();double sigma = this.calculateSigma(my);if(sigma <= 0.0D) {return 0.0D;} else {for(int x = 0; x < this.imgWidth; ++x) {for(int y = 0; y < this.imgHeight; ++y) {my4 += Math.pow((double)this.grayScales[x][y] - my, 4.0D);}}alpha4 = my4 / Math.pow(sigma, 4.0D);result = sigma / Math.pow(alpha4, 0.25D);return result;}}public double calculateMy() {double mean = 0.0D;for(int x = 0; x < this.imgWidth; ++x) {for(int y = 0; y < this.imgHeight; ++y) {mean += (double)this.grayScales[x][y];}}mean /= (double)(this.imgWidth * this.imgHeight);return mean;}public double calculateSigma(double mean) {double result = 0.0D;for(int x = 0; x < this.imgWidth; ++x) {for(int y = 0; y < this.imgHeight; ++y) {result += Math.pow((double)this.grayScales[x][y] - mean, 2.0D);}}result /= (double)(this.imgWidth * this.imgHeight);return Math.sqrt(result);}//第三个指标 Directionality,方向度public double[] directionality() {double[] histogram = new double[16];double maxResult = 3.0D;double binWindow = maxResult / (double)(histogram.length - 1);boolean bin = true;for(int x = 1; x < this.imgWidth - 1; ++x) {for(int y = 1; y < this.imgHeight - 1; ++y) {int var9 = (int)((1.5707963267948966D + Math.atan(this.calculateDeltaV(x, y) / this.calculateDeltaH(x, y))) / binWindow);++histogram[var9];}}return histogram;}public double calculateDeltaH(int x, int y) {double result = 0.0D;for(int i = 0; i < 3; ++i) {for(int j = 0; j < 3; ++j) {result += (double)this.grayScales[x - 1 + i][y - 1 + j] * filterH[i][j];}}return result;}public double calculateDeltaV(int x, int y) {double result = 0.0D;for(int i = 0; i < 3; ++i) {for(int j = 0; j < 3; ++j) {result += (double)this.grayScales[x - 1 + i][y - 1 + j] * filterV[i][j];}}return result;}public double getDistance(double[] targetFeature, double[] queryFeature) {double result = 0.0D;for(int i = 2; i < targetFeature.length; ++i) {result += Math.pow(targetFeature[i] - queryFeature[i], 2.0D);}return result;}public void extract(BufferedImage image) {this.histogram = new double[18];ColorConvertOp op = new ColorConvertOp(image.getColorModel().getColorSpace(), ColorSpace.getInstance(1003), new RenderingHints(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY));BufferedImage bimg = op.filter(image, (BufferedImage)null);bimg = ImageUtils.scaleImage(bimg, 64);WritableRaster raster = bimg.getRaster();int[] tmp = new int[3];this.grayScales = new int[raster.getWidth()][raster.getHeight()];int i;for(i = 0; i < raster.getWidth(); ++i) {for(int j = 0; j < raster.getHeight(); ++j) {raster.getPixel(i, j, tmp);this.grayScales[i][j] = tmp[0];}}this.imgWidth = bimg.getWidth();this.imgHeight = bimg.getHeight();//第一个指标 Coarseness,粗糙度this.histogram[0] = this.coarseness(bimg.getWidth(), bimg.getHeight());//第二个指标 Contrast,对比度this.histogram[1] = this.contrast();//第三个指标 Directionality,方向度double[] directionality = this.directionality();for(i = 2; i < this.histogram.length; ++i) {this.histogram[i] = directionality[i - 2];}}public byte[] getByteArrayRepresentation() {return SerializationUtils.toByteArray(this.histogram);}public void setByteArrayRepresentation(byte[] in) {this.histogram = SerializationUtils.toDoubleArray(in);}public void setByteArrayRepresentation(byte[] in, int offset, int length) {this.histogram = SerializationUtils.toDoubleArray(in, offset, length);}public double[] getFeatureVector() {return this.histogram;}public double getDistance(LireFeature feature) {if(!(feature instanceof Tamura)) {throw new UnsupportedOperationException("Wrong descriptor.");} else {Tamura tamura = (Tamura)feature;return this.getDistance(tamura.histogram, this.histogram);}}public String getFeatureName() {return "Tamura Features";}public String getFieldName() {return "TAMURA";}
}
Reference:

http://blog.sina.com.cn/s/blog_5ae7a1de01012r03.html

http://blog.csdn.net/jzwong/article/details/51584535


这篇关于LIRe图像检索:Tamura纹理特征算法源码分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/270106

相关文章

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景

python中Hash使用场景分析

《python中Hash使用场景分析》Python的hash()函数用于获取对象哈希值,常用于字典和集合,不可变类型可哈希,可变类型不可,常见算法包括除法、乘法、平方取中和随机数哈希,各有优缺点,需根... 目录python中的 Hash除法哈希算法乘法哈希算法平方取中法随机数哈希算法小结在Python中,

Java Stream的distinct去重原理分析

《JavaStream的distinct去重原理分析》Javastream中的distinct方法用于去除流中的重复元素,它返回一个包含过滤后唯一元素的新流,该方法会根据元素的hashcode和eq... 目录一、distinct 的基础用法与核心特性二、distinct 的底层实现原理1. 顺序流中的去重

HTML5 中的<button>标签用法和特征

《HTML5中的<button>标签用法和特征》在HTML5中,button标签用于定义一个可点击的按钮,它是创建交互式网页的重要元素之一,本文将深入解析HTML5中的button标签,详细介绍其属... 目录引言<button> 标签的基本用法<button> 标签的属性typevaluedisabled

关于MyISAM和InnoDB对比分析

《关于MyISAM和InnoDB对比分析》:本文主要介绍关于MyISAM和InnoDB对比分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录开篇:从交通规则看存储引擎选择理解存储引擎的基本概念技术原理对比1. 事务支持:ACID的守护者2. 锁机制:并发控制的艺

MyBatis Plus 中 update_time 字段自动填充失效的原因分析及解决方案(最新整理)

《MyBatisPlus中update_time字段自动填充失效的原因分析及解决方案(最新整理)》在使用MyBatisPlus时,通常我们会在数据库表中设置create_time和update... 目录前言一、问题现象二、原因分析三、总结:常见原因与解决方法对照表四、推荐写法前言在使用 MyBATis

Python主动抛出异常的各种用法和场景分析

《Python主动抛出异常的各种用法和场景分析》在Python中,我们不仅可以捕获和处理异常,还可以主动抛出异常,也就是以类的方式自定义错误的类型和提示信息,这在编程中非常有用,下面我将详细解释主动抛... 目录一、为什么要主动抛出异常?二、基本语法:raise关键字基本示例三、raise的多种用法1. 抛

github打不开的问题分析及解决

《github打不开的问题分析及解决》:本文主要介绍github打不开的问题分析及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、找到github.com域名解析的ip地址二、找到github.global.ssl.fastly.net网址解析的ip地址三