当前位置: 首页 > 面试题库 >

Java-从图像获取像素数组

夏朝
2023-03-14
问题内容

我正在寻找从中获取像素数据(以表格形式int[][])的最快方法BufferedImage。我的目标是能够解决像素(x, y)从使用图像int[x][y]。我发现的所有方法均不执行此操作(大多数方法都返回int[]s)。


问题答案:

我只是在玩同一个主题,这是访问像素的最快方法。我目前知道执行此操作的两种方法:

使用getRGB()@tskuzzy的答案中所述的BufferedImage 方法。
通过直接使用以下方式访问像素数组:

byte[] pixels = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData();

如果你要处理大图像并且性能是一个问题,则第一种方法绝对不是可行的方法。该getRGB()方法将alpha,红色,绿色和蓝色的值合并为一个int,然后返回结果,在大多数情况下,你将进行相反操作以将这些值取回。

第二种方法将直接为每个像素返回红色,绿色和蓝色值,如果有alpha通道,它将添加alpha值。使用此方法在计算指标方面比较困难,但是比第一种方法要快得多。

在我的应用程序中,通过从第一种方法切换到第二种方法,我能够将像素处理时间减少90%以上!

这是我为比较两种方法而设置的比较:

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

public class PerformanceTest {

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

      BufferedImage hugeImage = ImageIO.read(PerformanceTest.class.getResource("12000X12000.jpg"));

      System.out.println("Testing convertTo2DUsingGetRGB:");
      for (int i = 0; i < 10; i++) {
         long startTime = System.nanoTime();
         int[][] result = convertTo2DUsingGetRGB(hugeImage);
         long endTime = System.nanoTime();
         System.out.println(String.format("%-2d: %s", (i + 1), toString(endTime - startTime)));
      }

      System.out.println("");

      System.out.println("Testing convertTo2DWithoutUsingGetRGB:");
      for (int i = 0; i < 10; i++) {
         long startTime = System.nanoTime();
         int[][] result = convertTo2DWithoutUsingGetRGB(hugeImage);
         long endTime = System.nanoTime();
         System.out.println(String.format("%-2d: %s", (i + 1), toString(endTime - startTime)));
      }
   }

   private static int[][] convertTo2DUsingGetRGB(BufferedImage image) {
      int width = image.getWidth();
      int height = image.getHeight();
      int[][] result = new int[height][width];

      for (int row = 0; row < height; row++) {
         for (int col = 0; col < width; col++) {
            result[row][col] = image.getRGB(col, row);
         }
      }

      return result;
   }

   private static int[][] convertTo2DWithoutUsingGetRGB(BufferedImage image) {

      final byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
      final int width = image.getWidth();
      final int height = image.getHeight();
      final boolean hasAlphaChannel = image.getAlphaRaster() != null;

      int[][] result = new int[height][width];
      if (hasAlphaChannel) {
         final int pixelLength = 4;
         for (int pixel = 0, row = 0, col = 0; pixel + 3 < pixels.length; pixel += pixelLength) {
            int argb = 0;
            argb += (((int) pixels[pixel] & 0xff) << 24); // alpha
            argb += ((int) pixels[pixel + 1] & 0xff); // blue
            argb += (((int) pixels[pixel + 2] & 0xff) << 8); // green
            argb += (((int) pixels[pixel + 3] & 0xff) << 16); // red
            result[row][col] = argb;
            col++;
            if (col == width) {
               col = 0;
               row++;
            }
         }
      } else {
         final int pixelLength = 3;
         for (int pixel = 0, row = 0, col = 0; pixel + 2 < pixels.length; pixel += pixelLength) {
            int argb = 0;
            argb += -16777216; // 255 alpha
            argb += ((int) pixels[pixel] & 0xff); // blue
            argb += (((int) pixels[pixel + 1] & 0xff) << 8); // green
            argb += (((int) pixels[pixel + 2] & 0xff) << 16); // red
            result[row][col] = argb;
            col++;
            if (col == width) {
               col = 0;
               row++;
            }
         }
      }

      return result;
   }

   private static String toString(long nanoSecs) {
      int minutes    = (int) (nanoSecs / 60000000000.0);
      int seconds    = (int) (nanoSecs / 1000000000.0)  - (minutes * 60);
      int millisecs  = (int) ( ((nanoSecs / 1000000000.0) - (seconds + minutes * 60)) * 1000);


      if (minutes == 0 && seconds == 0)
         return millisecs + "ms";
      else if (minutes == 0 && millisecs == 0)
         return seconds + "s";
      else if (seconds == 0 && millisecs == 0)
         return minutes + "min";
      else if (minutes == 0)
         return seconds + "s " + millisecs + "ms";
      else if (seconds == 0)
         return minutes + "min " + millisecs + "ms";
      else if (millisecs == 0)
         return minutes + "min " + seconds + "s";

      return minutes + "min " + seconds + "s " + millisecs + "ms";
   }
}

你能猜出输出吗?;)

Testing convertTo2DUsingGetRGB:
1 : 16s 911ms
2 : 16s 730ms
3 : 16s 512ms
4 : 16s 476ms
5 : 16s 503ms
6 : 16s 683ms
7 : 16s 477ms
8 : 16s 373ms
9 : 16s 367ms
10: 16s 446ms

Testing convertTo2DWithoutUsingGetRGB:
1 : 1s 487ms
2 : 1s 940ms
3 : 1s 785ms
4 : 1s 848ms
5 : 1s 624ms
6 : 2s 13ms
7 : 1s 968ms
8 : 1s 864ms
9 : 1s 673ms
10: 2s 86ms

BUILD SUCCESSFUL (total time: 3 minutes 10 seconds)


 类似资料:
  • 问题内容: 我正在尝试从位图获取像素rgb值。我得到了一些价值,但远没有达到我期望的价值。我也得到: 我找不到界外错误… 这是代码: 问题答案: 这个: 与此不符: 你已经计数的行和列,即包含 ÿ 值和包含 X 的值。那是倒退。

  • 问题内容: 我正在尝试阅读以下图片 但是它显示了IIOException。 这是代码: 问题答案: 您收到(错误请求)错误,因为您的网址中有。如果在参数之前对其进行了修复,则会收到错误消息(未经授权)。也许您需要一些HTTP标头才能将您的下载标识为可识别的浏览器(使用“ User-Agent”标头)或其他身份验证参数。 对于User-Agent示例,然后通过连接inputstream 使用Imag

  • 最近,我一直试图在Java中缩放像素数组(INT[])。我使用。setrgb()将我所有的像素数据添加到BufferedImage中。然后,BufferedImage提供了一个名为.getScaledInstance()的函数。这对我来说应该很有效,但我遇到了一个问题。.getScaledInstance()返回图像,而不是BufferedImage。对于Image对象,我不能使用.getrgb(

  • 问题内容: Q1) 在我的reactjs应用程序中,我正在尝试从后端Nodejs服务器获取API。API会根据请求响应图像文件。 我可以在http://192.168.22.124:3000/source/592018124023PM-pexels- photo.jpg 上访问并查看图像文件 但是在我的reactjs客户端上,我在控制台日志上收到此错误。 未捕获(承诺)SyntaxError:意外

  • 问题内容: 有没有办法使用Java从https网址获取图像? 到目前为止,我正在尝试: 但是,我得到: 我该如何处理?我必须提取该URL上的6k张图像以上。 问题答案: 有两个问题。您可以使用浏览器访问该网站,并查看错误。 服务器证书是自签名的,不受Java信任。您可以将其添加到信任库。 服务器证书与主机名“ ns6.host.md”不匹配,因此您需要一个忽略它的证书。 另一个答案也是如此,它提供

  • 实际上我想对每个像素做一些计算,为此我需要显式地访问每个像素。 如有任何帮助或建议,我们将不胜感激。