2

我用 Java 编写了一个用于图像处理的应用程序。我已经处理了作为缓冲图像的图像,现在我想返回byte[]那个处理过的图像,我应该得到二值化图像的字节数组。

这是我的代码:

public static byte[][] binarizeImage(BufferedImage bfImage){

        int red;
        int newPixel;
        int h ;
        int w ;
        int threshold = otsuTreshold(bfImage);   
          // this function returns the threshold value 199

        BufferedImage binarized = new BufferedImage(bfImage.getWidth(), bfImage.getHeight(), bfImage.getType());

        for(int i=0; i<bfImage.getWidth(); i++) {
        for(int j=0; j<bfImage.getHeight(); j++) {

            // Get pixels
            red = new Color(bfImage.getRGB(i, j)).getRed();
            int alpha = new Color(bfImage.getRGB(i, j)).getAlpha();
            if(red > threshold) {
                newPixel = 255;
            }
            else {
                newPixel = 0;
            }
            newPixel = colorToRGB(alpha, newPixel, newPixel, newPixel);
            binarized.setRGB(i, j, newPixel); 
       }

     }
          Raster raster  = binarized.getData();

    h = raster.getHeight();
    w = raster.getWidth();

    byte[][] binarize_image = new byte[w][h];

    for(int i=0 ; i<w ; i++)
    {
        for(int j=0; j<h ; j++)
        {
            binarize_image[i][j]=raster.getSampleModel();  //error at this line 
        }
   }
   return binarize_image;
}

// Convert R, G, B, Alpha to standard 8 bit
    private static int colorToRGB(int alpha, int red, int green, int blue) {

        int newPixel = 0;
        newPixel += alpha;
        newPixel = newPixel << 8;
        newPixel += red; newPixel = newPixel << 8;
        newPixel += green; newPixel = newPixel << 8;
        newPixel += blue;

        return newPixel;

    }

但它不起作用。我应该怎么做才能将该缓冲图像转换为相同图像数据的字节数组?

4

4 回答 4

2

我不确定“二值化”一词在这种情况下是什么意思。您似乎只想过滤图像(即根据某个阈值截断红色通道)并将结果转换为byte[].

假设上面是正确的,然后检查下面的代码。它将图像转换byte[]为 32 位图像。请考虑以下几点:

  • 您不需要先过滤图像然后转换为byte[]. 您可以在转换期间执行此操作。
  • “将 RGB 转换为标准 8 位”:如果您的意思是每个颜色通道8 位,那么这没关系,但如果您的意思是每个像素8 位,那么您正在谈论压缩/转换(即您可能会丢失一些信息/质量)在这种情况下,您应该提供有关您想要实现的目标的更多信息。
  • 假设我们谈论的是 32 位图像的情况,您的结果byte[]将具有一定的大小。如果您需要处理其他情况,您应该考虑(或至少只有您感兴趣的)支持的可用图像类型。4 * width * heightwidth * heightBufferedImage

下面的代码将打印每个转换像素的信息,如下所示(注意红色通道是如何过滤的):

[0,0] Converting [ffaaccee] --> [0, cc, ee, ff]

package imageio.byteconversion;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;

public class BufferedImageToBytes {

    private static void log(String s) {
        System.out.println(s);
    }

    private static String toByteString(int color) {
        // Perform a bitwise AND for convenience while printing. 
        // Otherwise Integer.toHexString() interprets values as integers and a negative byte 0xFF will be printed as "ffffffff"
        return Integer.toHexString(color & 0xFF);
    }

    public static void main(String[] args) throws IOException {

        // Load the image. This expects the image to be in the same package with this class 
        InputStream stream = BufferedImageToBytes.class.getResourceAsStream("test.png");
        BufferedImage image = ImageIO.read(stream);
        int iw = image.getWidth();
        int ih = image.getHeight();
        log("Image loaded succesfully, width=" + iw + " height=" + ih);
        stream.close();

        log("Image color model: " + image.getColorModel());
        log("Image sample model: " + image.getSampleModel());
        log("Image raster: " + image.getRaster());

        int bands = image.getSampleModel().getNumBands();
        log("Color bands: " + bands);
        if (bands != 4) {
            throw new RuntimeException("The image does not have 4 color bands. Are you sure this is a 32-bit image?");
        }

        int threshold = 199; // <-- decide your threshold here

        byte bytes[] = new byte[4 * iw * ih];
        int index = 0;

        // note that image is processed row by row top to bottom
        for(int y = 0; y < ih; y++) {
            for(int x = 0; x < iw; x++) {

                // returns a packed pixel where each byte is a color channel
                // order is the default ARGB color model
                int pixel = image.getRGB(x, y);

                // Get pixels
                int alpha = (pixel >> 24) & 0xFF;
                int red = (pixel >> 16) & 0xFF;
                int green = (pixel >> 8) & 0xFF;
                int blue = pixel & 0xFF;

                // perform filtering here depending on threshold 
                if (red > threshold) {
                   red = 255;
                } else {
                    red = 0;
                }

                log("[" + x + "," + y + "]" + " Converting [" + Integer.toHexString(pixel)  + "] --> ["
                        + toByteString(red) + ", " + toByteString(green) + ", " 
                        + toByteString(blue) + ", " + toByteString(alpha)
                        + "]");

                bytes[index++] = (byte) red;
                bytes[index++] = (byte) green;
                bytes[index++] = (byte) blue;
                bytes[index++] = (byte) alpha;
           }
        }
    }
}
于 2013-08-29T10:44:36.827 回答
2

你为什么不尝试使用 libs 作为 Catalano 框架。http://code.google.com/p/catalano-framework/

FastBitmap fb = new FastBitmap("c:\\files\\image.jpg");
fb.toGrayscale();

OtsuThreshold otsu = new OtsuThreshold();
otsu.applyInPlace(fb);

int[][] image = new int[fb.getHeight()][fb.getWidth()];
fb.toArrayGray(image);
于 2013-08-29T19:21:56.610 回答
1
  try {
                  // get the BufferedImage, using the ImageIO class
                  Bitmap image = 
                    BitmapFactory.decodeStream(getAssets()
                            .open("aa.bmp"));
                  marchThroughImage(image);
                } catch (IOException e) {
                  System.err.println(e.getMessage());
                }
        }
    });


}
public void printPixelARGB(int pixel) {
    int alpha = (pixel >> 24) & 0xff;
    int red = (pixel >> 16) & 0xff;
    int green = (pixel >> 8) & 0xff;
    int blue = (pixel) & 0xff;
    System.out.println("argb: " + alpha + ", " + red + ", " + green + ", " + blue);
  }
private void marchThroughImage(Bitmap image) {
    int w = image.getWidth();
    int h = image.getHeight();
    System.out.println("width, height: " + w + ", " + h);

    for (int i = 0; i < h; i++) {
      for (int j = 0; j < w; j++) {
        System.out.println("x,y: " + j + ", " + i);
        int pixel = image.getPixel(j, i);
        printPixelARGB(pixel);
        System.out.println("");
      }
    }
  }
于 2013-11-07T11:44:35.677 回答
1

怎么样:

BufferedImage input;

BufferedImage binary = new BufferedImage(input.getWidth(), input.getHeight(), BufferedImage.TYPE_BYTE_BINARY);

Graphics2D g = binary.createGraphics();
try {
    g.drawImage(input, 0, 0, null);
}
finally {
   g.dispose();
}

它不会使用您的otsuTreshold,它会(可能)抖动图像,但它会使用最少的内存完成使其成为二进制(仅限黑色/白色)的工作。

于 2013-08-29T11:23:45.377 回答