本文主要是介绍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纹理特征算法源码分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!