LIRe图像检索:Tamura纹理特征算法源码分析
来源:互联网 发布:iphone美图软件 编辑:程序博客网 时间:2024/05/18 21:43
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
0 0
- LIRe图像检索:Tamura纹理特征算法源码分析
- LIRe图像检索:CEDD算法原理与源码分析
- LIRe图像检索:FCTH算法原理与源码分析
- Tamura纹理特征
- [图像] Tamura纹理
- FIRE图像检索库之tamura特征计算
- 图像tamura特征提取<一>
- 图像检索:几种基于纹理特征的图像检索算法
- 图像检索:几种基于纹理特征的图像检索算法
- 图像检索:几种基于纹理特征的图像检索算法
- 图像检索:几种基于纹理特征的图像检索算法
- 图像检索:几种基于纹理特征的图像检索算法
- 图像检索:几种基于纹理特征的图像检索算法
- Tamura纹理特征的matlab实现
- Tamura纹理特征的matlab实现
- LIRe提供的图像检索算法的速度
- 基于Gabor纹理特征的图像检索
- LIRE图像检索引擎Lire - Lucene Image REtrieval
- 阿里2018届实习生内推经历
- Java 代码性能优化
- 代理模式(Proxy Pattern)之远程代理服务
- Hexo + GitHub配置个人博客
- fa
- LIRe图像检索:Tamura纹理特征算法源码分析
- 欢迎使用CSDN-markdown编辑器
- Javaweb学习笔记——Server Tomcat v9.0 Server at localhost failed to start.
- 文章标题
- 【公网远程】网页控制nodemcu的LED
- 49.性能调优之调节并行度
- 计算几何摸黑(1)
- VS2017下Boost编译
- mysql 查询当日的