java - Android位图到缓冲图像

标签 java android bitmap image-manipulation

有没有一种简单的方法可以将 Bitmap 图像数据类型转换为 BufferedImage?

我需要将一个缩放到 224*224 的位图图像转换成一个 BufferedImage,以便在两个 BufferedImage 之间进行像素比较。

我一直在尝试开发一个简单的面部识别类,该类将获取 2 个位图图像(从 android 相机拍摄)并使用本地二进制模式识别算法对它们进行比较。图片对比源码:

import java.awt.image.*;
import java.awt.color.ColorSpace;

public class ImageEncode {

 public static boolean facialRecognition(BufferedImage i, BufferedImage i2) {

  int currentPixelValue, newPixelValue;
  int[][] imageArray = new int[224][224], imageArray2 = new int[224][224], lbpArray = new int[224][224], lbpArray2 = new int[224][224], histogram = new int[9][256], histogram2 = new int[9][256];



  //input pictures, resize to 224x224
  BufferedImage image = i;
  BufferedImage image2 = i2;

  //convert to gray scale
  ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
  ColorConvertOp op = new ColorConvertOp(cs, null);
  image = op.filter(image, null);
  image2=op.filter(image2, null);

  //gaussian filter
  Kernel kernel = new Kernel(3,3,
    new float[] {
     1f/9f, 1f/9f, 1f/9f,
     1f/9f, 1f/9f, 1f/9f,
     1f/9f, 1f/9f, 1f/9f});
  BufferedImageOp op2 = new ConvolveOp(kernel);
  image = op2.filter(image, null);
  image2= op2.filter(image2, null);

  //convert images to pixel value array
  for(int row=0; row<=223; row++){
   for(int col=0; col<=223; col++){
    imageArray[row][col]=image.getRGB(row, col);
    imageArray2[row][col]=image2.getRGB(row, col);
   }
  }  

  //perform lbp calculations  
  for(int row=1; row<223; row++){
   for(int col=1; col<223; col++){
    currentPixelValue=imageArray[row][col];
    newPixelValue=0;
    if(imageArray[row-1][col-1]>currentPixelValue) newPixelValue=newPixelValue+1;
    if(imageArray[row-1][col]>currentPixelValue) newPixelValue=newPixelValue+2;
    if(imageArray[row-1][col+1]>currentPixelValue) newPixelValue=newPixelValue+4;
    if(imageArray[row][col+1]>currentPixelValue) newPixelValue=newPixelValue+8;
    if(imageArray[row+1][col+1]>currentPixelValue) newPixelValue=newPixelValue+16;
    if(imageArray[row+1][col]>currentPixelValue) newPixelValue=newPixelValue+32;
    if(imageArray[row+1][col-1]>currentPixelValue) newPixelValue=newPixelValue+64;
    if(imageArray[row][col-1]>currentPixelValue) newPixelValue=newPixelValue+128;
    lbpArray[row][col]=newPixelValue;
   }
  }

  for(int row=1; row<223; row++){
   for(int col=1; col<223; col++){
    currentPixelValue=imageArray2[row][col];
    newPixelValue=0;
    if(imageArray2[row-1][col-1]>currentPixelValue) newPixelValue=newPixelValue+1;
    if(imageArray2[row-1][col]>currentPixelValue) newPixelValue=newPixelValue+2;
    if(imageArray2[row-1][col+1]>currentPixelValue) newPixelValue=newPixelValue+4;
    if(imageArray2[row][col+1]>currentPixelValue) newPixelValue=newPixelValue+8;
    if(imageArray2[row+1][col+1]>currentPixelValue) newPixelValue=newPixelValue+16;
    if(imageArray2[row+1][col]>currentPixelValue) newPixelValue=newPixelValue+32;
    if(imageArray2[row+1][col-1]>currentPixelValue) newPixelValue=newPixelValue+64;
    if(imageArray2[row][col-1]>currentPixelValue) newPixelValue=newPixelValue+128;
    lbpArray2[row][col]=newPixelValue;
   }
  }

  //create histograms
  for(int row=1; row<=222; row++){
   for(int col=1; col<=222; col++){
    if(row<75 && col<75) histogram[0][imageArray[row][col]]++;
    if(row<75 && col>74 && col<149) histogram[1][imageArray[row][col]]++;
    if(row<75 && col>148 && col<223) histogram[2][imageArray[row][col]]++;
    if(row>74 && row<149 && col<75) histogram[3][imageArray[row][col]]++;
    if(row>74 && row<149 && col>75 && col<149) histogram[4][imageArray[row][col]]++;
    if(row>74 && row<149 && col>148 && col<223) histogram[5][imageArray[row][col]]++;
    if(row>148 && row<223 && col<75) histogram[6][imageArray[row][col]]++;
    if(row>148 && row<223 && col>74 && col<149) histogram[7][imageArray[row][col]]++;
    if(row>148 && row<223 && col>148 && col<223) histogram[8][imageArray[row][col]]++;
   }
  }  

  for(int row=1; row<=222; row++){
   for(int col=1; col<=222; col++){
    if(row<75 && col<75) histogram2[0][imageArray2[row][col]]++;
    if(row<75 && col>74 && col<149) histogram2[1][imageArray2[row][col]]++;
    if(row<75 && col>148 && col<223) histogram2[2][imageArray2[row][col]]++;
    if(row>74 && row<149 && col<75) histogram2[3][imageArray2[row][col]]++;
    if(row>74 && row<149 && col>75 && col<149) histogram2[4][imageArray2[row][col]]++;
    if(row>74 && row<149 && col>148 && col<223) histogram2[5][imageArray2[row][col]]++;
    if(row>148 && row<223 && col<75) histogram2[6][imageArray2[row][col]]++;
    if(row>148 && row<223 && col>74 && col<149) histogram2[7][imageArray2[row][col]]++;
    if(row>148 && row<223 && col>148 && col<223) histogram2[8][imageArray2[row][col]]++;
   }
  }  

  //Compare histograms
  for(int k=0; k<=8; k++){
   for(int j=0; j<=255; j++){
    if((((histogram[k][j])*0.1)+histogram[k][j]) < histogram2[k][j] || (histogram[k][j]-((histogram[k][j])*0.1)) > histogram2[k][j]){
     return false;
    }
   }
  }

  return true;

 }

}

最佳答案

我多次使用此类将不同的位图转换为缓冲图像

import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.io.IOException;
import java.io.InputStream;

/**
 * Utility class for loading windows bitmap files
 * <p>
 * Based on code from author Abdul Bezrati and Pepijn Van Eeckhoudt
 */
public class BitmapLoader {

    /**
     * Static method to load a bitmap file based on the filename passed in.
     * Based on the bit count, this method will either call the 8 or 24 bit
     * bitmap reader methods
     *
     * @param file The name of the bitmap file to read
     * @throws IOException
     * @return A BufferedImage of the bitmap
     */
    public static BufferedImage loadBitmap(String file) throws IOException {
        BufferedImage image;
        InputStream input = null;
        try {
            input = ResourceRetriever.getResourceAsStream(file);

            int bitmapFileHeaderLength = 14;
            int bitmapInfoHeaderLength = 40;

            byte bitmapFileHeader[] = new byte[bitmapFileHeaderLength];
            byte bitmapInfoHeader[] = new byte[bitmapInfoHeaderLength];

            input.read(bitmapFileHeader, 0, bitmapFileHeaderLength);
            input.read(bitmapInfoHeader, 0, bitmapInfoHeaderLength);

            int nSize = bytesToInt(bitmapFileHeader, 2);
            int nWidth = bytesToInt(bitmapInfoHeader, 4);
            int nHeight = bytesToInt(bitmapInfoHeader, 8);
            int nBiSize = bytesToInt(bitmapInfoHeader, 0);
            int nPlanes = bytesToShort(bitmapInfoHeader, 12);
            int nBitCount = bytesToShort(bitmapInfoHeader, 14);
            int nSizeImage = bytesToInt(bitmapInfoHeader, 20);
            int nCompression = bytesToInt(bitmapInfoHeader, 16);
            int nColoursUsed = bytesToInt(bitmapInfoHeader, 32);
            int nXPixelsMeter = bytesToInt(bitmapInfoHeader, 24);
            int nYPixelsMeter = bytesToInt(bitmapInfoHeader, 28);
            int nImportantColours = bytesToInt(bitmapInfoHeader, 36);

            if (nBitCount == 24) {
                image = read24BitBitmap(nSizeImage, nHeight, nWidth, input);
            } else if (nBitCount == 8) {
                image = read8BitBitmap(nColoursUsed, nBitCount, nSizeImage, nWidth, nHeight, input);
            } else {
                System.out.println("Not a 24-bit or 8-bit Windows Bitmap, aborting...");
                image = null;
            }
        } finally {
            try {
                if (input != null)
                    input.close();
            } catch (IOException e) {
            }
        }
        return image;
    }

    /**
     * Static method to read a 8 bit bitmap
     *
     * @param nColoursUsed Number of colors used
     * @param nBitCount The bit count
     * @param nSizeImage The size of the image in bytes
     * @param nWidth The width of the image
     * @param input The input stream corresponding to the image
     * @throws IOException
     * @return A BufferedImage of the bitmap
     */
    private static BufferedImage read8BitBitmap(int nColoursUsed, int nBitCount, int nSizeImage, int nWidth, int nHeight, InputStream input) throws IOException {
        int nNumColors = (nColoursUsed > 0) ? nColoursUsed : (1 & 0xff) << nBitCount;

        if (nSizeImage == 0) {
            nSizeImage = ((((nWidth * nBitCount) + 31) & ~31) >> 3);
            nSizeImage *= nHeight;
        }

        int npalette[] = new int[nNumColors];
        byte bpalette[] = new byte[nNumColors * 4];
        readBuffer(input, bpalette);
        int nindex8 = 0;

        for (int n = 0; n < nNumColors; n++) {
            npalette[n] = (255 & 0xff) << 24 |
                    (bpalette[nindex8 + 2] & 0xff) << 16 |
                    (bpalette[nindex8 + 1] & 0xff) << 8 |
                    (bpalette[nindex8 + 0] & 0xff);

            nindex8 += 4;
        }

        int npad8 = (nSizeImage / nHeight) - nWidth;
        BufferedImage bufferedImage = new BufferedImage(nWidth, nHeight, BufferedImage.TYPE_INT_ARGB);
        DataBufferInt dataBufferByte = ((DataBufferInt) bufferedImage.getRaster().getDataBuffer());
        int[][] bankData = dataBufferByte.getBankData();
        byte bdata[] = new byte[(nWidth + npad8) * nHeight];

        readBuffer(input, bdata);
        nindex8 = 0;

        for (int j8 = nHeight - 1; j8 >= 0; j8--) {
            for (int i8 = 0; i8 < nWidth; i8++) {
                bankData[0][j8 * nWidth + i8] = npalette[((int) bdata[nindex8] & 0xff)];
                nindex8++;
            }
            nindex8 += npad8;
        }

        return bufferedImage;
    }

    /**
     * Static method to read a 24 bit bitmap
     *
     * @param nSizeImage size of the image  in bytes
     * @param nHeight The height of the image
     * @param nWidth The width of the image
     * @param input The input stream corresponding to the image
     * @throws IOException
     * @return A BufferedImage of the bitmap
     */
    private static BufferedImage read24BitBitmap(int nSizeImage, int nHeight, int nWidth, InputStream input) throws IOException {
        int npad = (nSizeImage / nHeight) - nWidth * 3;
        if (npad == 4 || npad < 0)
            npad = 0;
        int nindex = 0;
        BufferedImage bufferedImage = new BufferedImage(nWidth, nHeight, BufferedImage.TYPE_4BYTE_ABGR);
        DataBufferByte dataBufferByte = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer());
        byte[][] bankData = dataBufferByte.getBankData();
        byte brgb[] = new byte[(nWidth + npad) * 3 * nHeight];

        readBuffer(input, brgb);

        for (int j = nHeight - 1; j >= 0; j--) {
            for (int i = 0; i < nWidth; i++) {
                int base = (j * nWidth + i) * 4;
                bankData[0][base] = (byte) 255;
                bankData[0][base + 1] = brgb[nindex];
                bankData[0][base + 2] = brgb[nindex + 1];
                bankData[0][base + 3] = brgb[nindex + 2];
                nindex += 3;
            }
            nindex += npad;
        }

        return bufferedImage;
    }

    /**
     * Converts bytes to an int
     *
     * @param bytes An array of bytes
     * @param index
     * @returns A int representation of the bytes
     */
    private static int bytesToInt(byte[] bytes, int index) {
        return (bytes[index + 3] & 0xff) << 24 |
                (bytes[index + 2] & 0xff) << 16 |
                (bytes[index + 1] & 0xff) << 8 |
                bytes[index + 0] & 0xff;
    }

    /**
     * Converts bytes to a short
     *
     * @param bytes An array of bytes
     * @param index
     * @returns A short representation of the bytes
     */
    private static short bytesToShort(byte[] bytes, int index) {
        return (short) (((bytes[index + 1] & 0xff) << 8) |
                (bytes[index + 0] & 0xff));
    }

    /**
     * Reads the buffer
     *
     * @param in An InputStream
     * @param buffer An array of bytes
     * @throws IOException
     */
    private static void readBuffer(InputStream in, byte[] buffer) throws IOException {
        int bytesRead = 0;
        int bytesToRead = buffer.length;
        while (bytesToRead > 0) {
            int read = in.read(buffer, bytesRead, bytesToRead);
            bytesRead += read;
            bytesToRead -= read;
        }
    }
}

关于java - Android位图到缓冲图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8301543/

相关文章:

android - 如何压缩Camera.takepicture拍摄的照片

java - 有没有办法自定义JLabel?

android -\n 在 Java 中不换行

java - 分析心率监测器返回的数据

android - 什么会导致已发布的 Android 应用程序自发地停止为大量用户工作?

java - 如何将位图压缩为较小尺寸的图像(保持纵横比)

Java API/Jersey put 方法

java - Blogger API 示例代码

java - 为什么这个类被认为是可变的?

android - 用相机拍照并得到位图