gpt4 book ai didi

android - 使用 jfeaturelib 计算 Haralick 特征

转载 作者:太空宇宙 更新时间:2023-11-03 23:10:49 24 4
gpt4 key购买 nike

我想使用 jfeaturelib(基本上是用于 java)计算 android 中的 haralick 功能,但我发现没有ImageIOBufferedImage 在 android 中的实现,因为这些用于计算波纹管代码中的 haralick 特征。这些仅在纯 JAVA 中可用。

public void haralickFeatures(){
InputStream stream = HaralickDemo.class.getClassLoader().getResourceAsStream("test.jpg");
ColorProcessor image = new ColorProcessor(ImageIO.read(stream));

// initialize the descriptor
Haralick descriptor = new Haralick();

// run the descriptor and extract the features
descriptor.run(image);

// obtain the features
List<double[]> features = descriptor.getFeatures();

// print the features to system out
for (double[] feature : features) {
System.out.println(Arrays2.join(feature, ", ", "%.5f"));
}
}

有没有办法计算 android 中的 haralick 特征。任何代码示例都会有很大帮助。提前致谢。

最佳答案

正如您提到的,您不能使用 jfeaturelib 来计算haralick 功能,因为该库使用某些类,这些类仅在纯 java 而不是 android 中实现。您可以使用我从 jfeaturelib 中获取的代码,并对其进行修改以适合 android。

  • 首先,您必须在您的 android 项目中创建一个 java 类,并将其命名为您想要的名称(在我的例子中,我将其命名为 GLCM)

    public class GLCM {
    static int totalPixels=0;
    /**
    * The number of gray values for the textures
    */
    private final int NUM_GRAY_VALUES = 32;
    /**
    * p_(x+y) statistics
    */
    private final double[] p_x_plus_y = new double[2 * NUM_GRAY_VALUES - 1];
    /**
    * p_(x-y) statistics
    */
    private final double[] p_x_minus_y = new double[NUM_GRAY_VALUES];
    /**
    * row mean value
    */
    private double mu_x = 0;
    /**
    * column mean value
    */
    private double mu_y = 0;
    /**
    * row variance
    */
    private double var_x = 0;
    /**
    * column variance
    */
    private double var_y = 0;
    /**
    * HXY1 statistics
    */
    private double hx = 0;
    /**
    * HXY2 statistics
    */
    private double hy = 0;
    /**
    * HXY1 statistics
    */
    private double hxy1 = 0;
    /**
    * HXY2 statistics
    */
    private double hxy2 = 0;
    /**
    * p_x statistics
    */
    private final double[] p_x = new double[NUM_GRAY_VALUES];
    /**
    * p_y statistics
    */
    private final double[] p_y = new double[NUM_GRAY_VALUES];
    // -
    public List<double[]> data;
    public int haralickDist;
    double[] features = null;
    static byte[] imageArray;
    public void addData(double[] data) {

    this.data.add(data);
    }
    public List<double[]> getFeatures() {
    return data;
    }
    public void process(Bitmap b) {

    features = new double[14];

    Coocurrence coocurrence = new Coocurrence(b, NUM_GRAY_VALUES, this.haralickDist);
    coocurrence.calculate();
    double[][] cooccurrenceMatrix = coocurrence.getCooccurrenceMatrix();
    double meanGrayValue = coocurrence.getMeanGrayValue();


    normalize(cooccurrenceMatrix, coocurrence.getCooccurenceSums());

    calculateStatistics(cooccurrenceMatrix);
    double[][] p = cooccurrenceMatrix;
    double[][] Q = new double[NUM_GRAY_VALUES][NUM_GRAY_VALUES];
    for (int i = 0; i < NUM_GRAY_VALUES; i++) {
    double sum_j_p_x_minus_y = 0;
    for (int j = 0; j < NUM_GRAY_VALUES; j++) {
    double p_ij = p[i][j];

    sum_j_p_x_minus_y += j * p_x_minus_y[j];

    features[0] += p_ij * p_ij;
    features[2] += i * j * p_ij - mu_x * mu_y;
    features[3] += (i - meanGrayValue) * (i - meanGrayValue) * p_ij;
    features[4] += p_ij / (1 + (i - j) * (i - j));
    features[8] += p_ij * log(p_ij);

    // feature 13
    if (p_ij != 0 && p_x[i] != 0) { // would result in 0
    for (int k = 0; k < NUM_GRAY_VALUES; k++) {
    if (p_y[k] != 0 && p[j][k] != 0) { // would result in NaN
    Q[i][j] += (p_ij * p[j][k]) / (p_x[i] * p_y[k]);
    }
    }
    }
    }

    features[1] += i * i * p_x_minus_y[i];
    features[9] += (i - sum_j_p_x_minus_y) * (i - sum_j_p_x_minus_y) * p_x_minus_y[i];
    features[10] += p_x_minus_y[i] * log(p_x_minus_y[i]);
    }

    // feature 13: Max Correlation Coefficient
    double[] realEigenvaluesOfQ = new Matrix(Q).eig().getRealEigenvalues();
    Arrays2.abs(realEigenvaluesOfQ);
    Arrays.sort(realEigenvaluesOfQ);
    features[13] = Math.sqrt(realEigenvaluesOfQ[realEigenvaluesOfQ.length - 2]);

    features[2] /= Math.sqrt(var_x * var_y);
    features[8] *= -1;
    features[10] *= -1;
    double maxhxhy = Math.max(hx, hy);
    if (Math.signum(maxhxhy) == 0) {
    features[11] = 0;
    } else {
    features[11] = (features[8] - hxy1) / maxhxhy;
    }
    features[12] = Math.sqrt(1 - Math.exp(-2 * (hxy2 - features[8])));

    for (int i = 0; i < 2 * NUM_GRAY_VALUES - 1; i++) {
    features[5] += i * p_x_plus_y[i];
    features[7] += p_x_plus_y[i] * log(p_x_plus_y[i]);

    double sum_j_p_x_plus_y = 0;
    for (int j = 0; j < 2 * NUM_GRAY_VALUES - 1; j++) {
    sum_j_p_x_plus_y += j * p_x_plus_y[j];
    }
    features[6] += (i - sum_j_p_x_plus_y) * (i - sum_j_p_x_plus_y) * p_x_plus_y[i];
    }

    features[7] *= -1;
    }

    /**
    * Calculates the statistical properties.
    */
    private void calculateStatistics(double[][] cooccurrenceMatrix) {
    // p_x, p_y, p_x+y, p_x-y
    for (int i = 0; i < NUM_GRAY_VALUES; i++) {
    for (int j = 0; j < NUM_GRAY_VALUES; j++) {
    double p_ij = cooccurrenceMatrix[i][j];

    p_x[i] += p_ij;
    p_y[j] += p_ij;

    p_x_plus_y[i + j] += p_ij;
    p_x_minus_y[Math.abs(i - j)] += p_ij;
    }
    }

    // mean and variance values
    double[] meanVar;
    meanVar = meanVar(p_x);
    mu_x = meanVar[0];
    var_x = meanVar[1];
    meanVar = meanVar(p_y);
    mu_y = meanVar[0];
    var_y = meanVar[1];

    for (int i = 0; i < NUM_GRAY_VALUES; i++) {
    // hx and hy
    hx += p_x[i] * log(p_x[i]);
    hy += p_y[i] * log(p_y[i]);

    // hxy1 and hxy2
    for (int j = 0; j < NUM_GRAY_VALUES; j++) {
    double p_ij = cooccurrenceMatrix[i][j];
    hxy1 += p_ij * log(p_x[i] * p_y[j]);
    hxy2 += p_x[i] * p_y[j] * log(p_x[i] * p_y[j]);
    }
    }
    hx *= -1;
    hy *= -1;
    hxy1 *= -1;
    hxy2 *= -1;
    }

    /**
    * Compute mean and variance of the given array
    *
    * @param a inut values
    * @return array{mean, variance}
    */
    private double[] meanVar(double[] a) {
    // VAR(X) = E(X^2) - E(X)^2
    // two-pass is numerically stable.
    double ex = 0;
    for (int i = 0; i < NUM_GRAY_VALUES; i++) {
    ex += a[i];
    }
    ex /= a.length;
    double var = 0;
    for (int i = 0; i < NUM_GRAY_VALUES; i++) {
    var += (a[i] - ex) * (a[i] - ex);
    }
    var /= (a.length - 1);

    return new double[]{ex, var};
    }

    /**
    * Returns the bound logarithm of the specified value.
    *
    * If Math.log would be Double.NEGATIVE_INFINITY, 0 is returned
    *
    * @param value the value for which the logarithm should be returned
    * @return the logarithm of the specified value
    */
    private double log(double value) {
    double log = Math.log(value);
    if (log == Double.NEGATIVE_INFINITY) {
    log = 0;
    }
    return log;
    }

    /**
    * Normalizes the array by the given sum. by dividing each 2nd dimension
    * array componentwise by the sum.
    *
    * @param A
    * @param sum
    */
    private void normalize(double[][] A, double sum) {
    for (double[] A1 : A) {
    Arrays2.div(A1, sum);
    }
    }

    //<editor-fold defaultstate="collapsed" desc="getter/Setter">
    /**
    * Getter for haralick distributions
    *
    * @return haralick distributions
    */
    public int getHaralickDist() {
    return haralickDist;
    }

    /**
    * Setter for haralick distributions
    *
    * @param haralickDist int for haralick distributions (must be >= 1)
    */
    public void setHaralickDist(int haralickDist) {
    if (haralickDist <= 0) {
    throw new IllegalArgumentException("the distance for haralick must be >= 1 but was " + haralickDist);
    }
    this.haralickDist = haralickDist;
    }
    //</editor-fold>

    static class Coocurrence {

    /**
    * The number of gray values for the textures
    */
    private final int NUM_GRAY_VALUES;
    /**
    * The number of gray levels in an image
    */
    int GRAY_RANGES = 256;
    /**
    * The scale for the gray values for conversion rgb to gray values.
    */
    double GRAY_SCALE;
    /**
    * gray histogram of the image.
    */
    double[] grayHistogram;
    /**
    * Quantized gray values of each pixel of the image.
    *
    * Use int instead of byte as there is no unsigned byte in Java.
    * Otherwise you'll have a hard time using white = 255. Alternative:
    * replace with ImageJ ByteProcessor.
    */
    private final int[] grayValue;
    /**
    * mean gray value
    */
    private double meanGrayValue = 0;
    /**
    * The cooccurrence matrix
    */
    private final double[][] cooccurrenceMatrices;
    /**
    * The value for one increment in the gray/color histograms.
    */
    private final int HARALICK_DIST;
    private final Bitmap image;

    public Coocurrence(Bitmap b, int numGrayValues, int haralickDist) {
    this.NUM_GRAY_VALUES = numGrayValues;
    this.HARALICK_DIST = haralickDist;
    this.cooccurrenceMatrices = new double[NUM_GRAY_VALUES][NUM_GRAY_VALUES];
    this.image = b;
    totalPixels=b.getHeight()*b.getWidth();
    this.grayValue = new int[totalPixels];
    }

    void calculate() {
    this.GRAY_SCALE = (double) GRAY_RANGES / (double) NUM_GRAY_VALUES;
    this.grayHistogram = new double[GRAY_RANGES];

    calculateGreyValues();

    final int imageWidth = image.getWidth();
    final int imageHeight = image.getHeight();
    final int d = HARALICK_DIST;
    final int yOffset = d * imageWidth;
    int i, j, pos;

    // image is not empty per default
    for (int y = 0; y < imageHeight; y++) {
    for (int x = 0; x < imageWidth; x++) {
    pos = imageWidth * y + x;

    // horizontal neighbor: 0 degrees
    i = x - d;
    if (i >= 0) {
    increment(grayValue[pos], grayValue[pos - d]);
    }

    // vertical neighbor: 90 degree
    j = y - d;
    if (j >= 0) {
    increment(grayValue[pos], grayValue[pos - yOffset]);
    }

    // 45 degree diagonal neigbor
    i = x + d;
    j = y - d;
    if (i < imageWidth && j >= 0) {
    increment(grayValue[pos], grayValue[pos + d - yOffset]);
    }

    // 135 vertical neighbor
    i = x - d;
    j = y - d;
    if (i >= 0 && j >= 0) {
    increment(grayValue[pos], grayValue[pos - d - yOffset]);
    }
    }
    }
    }

    private void calculateGreyValues() {
    final int size = grayValue.length;
    double graySum = 0;
    for (int pos = 0; pos < size; pos++) {
    int gray = imageArray[pos]&0xff;
    graySum += gray;
    grayValue[pos] = (int) (gray / GRAY_SCALE); // quantized for texture analysis
    assert grayValue[pos] >= 0 : grayValue[pos] + " > 0 violated";
    grayHistogram[gray]++;
    }
    Arrays2.div(grayHistogram, size);
    meanGrayValue = Math.floor(graySum / size / GRAY_SCALE)*GRAY_SCALE;
    }

    /**
    * Incremets the coocurrence matrix at the specified positions (g1,g2)
    * and (g2,g1) if g1 and g2 are in range.
    *
    * @param g1 the gray value of the first pixel
    * @param g2 the gray value of the second pixel
    */
    private void increment(int g1, int g2) {
    cooccurrenceMatrices[g1][g2]++;
    cooccurrenceMatrices[g2][g1]++;
    }

    public double getMeanGrayValue() {
    return this.meanGrayValue;
    }

    public double[][] getCooccurrenceMatrix() {
    return this.cooccurrenceMatrices;
    }

    public double getCooccurenceSums() {
    // divide by R=8 neighbours
    // see p.613, §2 of Haralick paper
    return totalPixels * 8;
    }
    }
    }
  • 现在在您的主要 Activity 或您想要的 Activity 中创建该 GLCM 类的对象

     GLCM glcm=new GLCM();
  • 下一步是在您的主要 Activity 或您想要的 Activity 中复制过去的此功能。此函数提取特征,因为您必须将图像作为位图传递,并且此函数将在 float 组中返回 14 haralick 特征。这是那个函数

    public void haralickFeatures(Bitmap b) throws IOException {
    glcm.haralickDist=1;
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    b.compress(Bitmap.CompressFormat.PNG, 90, stream); // what 90 does ??
    GLCM.imageArray=new byte[]{};
    GLCM.imageArray = stream.toByteArray();
    glcm.process(b);
    glcm.data = new ArrayList<>(1);
    glcm.addData(glcm.features);
    List<double[]> featuresHar=glcm.getFeatures();

    for (double[] feature : featuresHar) {
    featureString=Arrays2.join(feature, ",", "%.5f");
    }
    String[] featureStr=featureString.split(Pattern.quote(","));
    float[] featureFlot = new float[featureStr.length];
    for (int i=0;i<featureStr.length;i++){
    featureFlot[i]=Float.parseFloat(featureStr[i]);
    }
    //featureFlot is array that contain all 14 haralick features

    }

关于android - 使用 jfeaturelib 计算 Haralick 特征,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50659080/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com