使用BufferedImage和Java在7000个图像中查找纯色的最有效方法是什么?

qmelpv7a  于 2023-05-27  发布在  Java
关注(0)|答案(3)|浏览(134)

我有一个方法可以计算并返回图像中最常见颜色的像素百分比-我有超过7000张图像,我需要迭代以获得每个jpg的百分比。
下面的方法迭代超过6000个jpg,以返回每个jpg中最常见颜色的百分比。这需要6-7分钟来迭代所有的jpg。

public static double calculatePercentage(BufferedImage image) {
        int width = image.getWidth();
        int height = image.getHeight();
        int totalPixels = width * height;
        Map<Integer, Integer> colorCounts = new HashMap<>();

        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int color = image.getRGB(x, y);
                colorCounts.put(color, colorCounts.getOrDefault(color, 0) + 1);
            }
        }

        int mostCommonColorCount = colorCounts.values().stream().max(Integer::compareTo).orElse(0);
        double percentage = (double) mostCommonColorCount / totalPixels;

        return percentage;
    }

有没有一种有效的方法来检查纯色和迭代这个程序更快超过7000图像。基本上,我试图确定那些JPG有平原纯色(如黑色,蓝色或白色)。

yhived7q

yhived7q1#

图像加载的速度很可能是性能问题的一个重要原因,但是对于计算步骤,您可以使用计数器AtomicInteger来测试自动装箱Integer,并使用并行Instream来同时处理多行。类似于:

public static double calculatePercentage(BufferedImage image) {
    int width = image.getWidth();
    int height = image.getHeight();
    int totalPixels = width * height;
    ConcurrentHashMap<Integer, AtomicInteger> colorCounts = new ConcurrentHashMap<>();
    IntStream.range(0, height).parallel().forEach(y -> {
        for (int x = 0; x < width; x++) {
            colorCounts.computeIfAbsent(image.getRGB(x, y), c -> new AtomicInteger()).incrementAndGet();
        }
    });
    int mostCommonColorCount = colorCounts.values().stream().mapToInt(AtomicInteger::get).max().orElse(0);
    double percentage = (double) mostCommonColorCount / totalPixels;

    return percentage;
}

您也应该尝试加载图像-您可能会发现读取File->BufferedImageFile->byte[]->BufferedImage的速度在不同类型的存储之间存在差异(我注意到后者对于NAS驱动器上的照片更快)。

tjvv9vkg

tjvv9vkg2#

可以做的一件事是将局部变量提升为字段,以减少持续时间。
这将创建可重用性。

Map<Integer, Integer> colorCounts;
int width, height;
int totalPixels;

int mostCommonColorCount;
double percentage;

public void calculatePercentage(BufferedImage image) {
    width = image.getWidth();
    height = image.getHeight();
    totalPixels = width * height;

    colorCounts = new HashMap<>();

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            int color = image.getRGB(x, y);
            colorCounts.put(color, colorCounts.getOrDefault(color, 0) + 1);
        }
    }

    mostCommonColorCount = 0;
    for (int count : colorCounts.values())
        if (count > mostCommonColorCount) mostCommonColorCount = count;

    percentage = (double) mostCommonColorCount / totalPixels;
}

一个图像的示例,1,920 x 1,280 JPEG (24-bit color) 170.97 kB
输出量

726 ms
0.044464518229166666

或者,您可以创建两个线程,其中一个用于在当前计算运行时将下一个图像加载到内存中。
这通常会显著提高速度。

ql3eal8s

ql3eal8s3#

方法image.getRGB非常慢,不建议用于访问像素值。
如果您想更快地遍历所有像素值,请使用getRaster(),但最快的方法是访问DataBuffer(它只是一个数组)。请参阅本讨论或本讨论,了解如何使用Raster或DataBuffer(强烈推荐后者)访问像素值。

相关问题