Как сделать пикселирование BufferedImage, чтобы оно выглядело так? - PullRequest
2 голосов
/ 02 февраля 2020

Я занимаюсь обработкой изображений и хочу сделать пикселизацию изображения, которое раньше было размытым, но оно все равно должно выглядеть как оригинал. Здесь я покажу вам несколько примеров того, что я сейчас делаю, и как я хочу, чтобы это выглядело:

Michael Jackson - normal

Это изображение, которое я хочу изменить.

Michael Jackson - Dithered

Это изображение после того, как оно было размыто "размыванием Флойда Штейнберга".

Michael Jackson- What I want it to look like

Вот как он должен выглядеть в конце после пикселизации.

Michael Jackson- What my image looks like

И так выглядит мое изображение после пикселизации. Я действительно не знаю, что делать, так что это выглядит как на картинке выше.

Я искал целое число rnet и пробовал каждый алгоритм пикселизации. Вот класс, который я использую в данный момент:

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.*;
import java.util.List;

public final class ImageUtil {

public static BufferedImage pixelate(BufferedImage imageToPixelate, int pixelSize) {
    BufferedImage pixelateImage = new BufferedImage(
        imageToPixelate.getWidth(),
        imageToPixelate.getHeight(),
        imageToPixelate.getType());

    for (int y = 0; y < imageToPixelate.getHeight(); y += pixelSize) {
        for (int x = 0; x < imageToPixelate.getWidth(); x += pixelSize) {
            BufferedImage croppedImage = getCroppedImage(imageToPixelate, x, y, pixelSize, pixelSize);
            Color dominantColor = getDominantColor(croppedImage);
            for (int yd = y; (yd < y + pixelSize) && (yd < pixelateImage.getHeight()); yd++) {
                for (int xd = x; (xd < x + pixelSize) && (xd < pixelateImage.getWidth()); xd++) {
                    pixelateImage.setRGB(xd, yd, dominantColor.getRGB());
                }
            }
        }
    }

    return pixelateImage;
}

public static BufferedImage getCroppedImage(BufferedImage image, int startx, int starty, int width, int height) {
    if (startx < 0) startx = 0;
    if (starty < 0) starty = 0;
    if (startx > image.getWidth()) startx = image.getWidth();
    if (starty > image.getHeight()) starty = image.getHeight();
    if (startx + width > image.getWidth()) width = image.getWidth() - startx;
    if (starty + height > image.getHeight()) height = image.getHeight() - starty;
    return image.getSubimage(startx, starty, width, height);
}

public static Color getDominantColor(BufferedImage image) {
    Map<Integer, Integer> colorCounter = new HashMap<>(100);
    for (int x = 0; x < image.getWidth(); x++) {
        for (int y = 0; y < image.getHeight(); y++) {
            int currentRGB = image.getRGB(x, y);
            int count = colorCounter.getOrDefault(currentRGB, 0);
            colorCounter.put(currentRGB, count + 1);
        }
    }
    return getDominantColor(colorCounter);
}

private static Color getDominantColor(Map<Integer, Integer> colorCounter) {
    int dominantRGB = colorCounter.entrySet().stream()
        .max((entry1, entry2) -> entry1.getValue() > entry2.getValue() ? 1 : -1)
        .get()
        .getKey();
    return new Color(dominantRGB);
}
}

И вот как я его запускаю:

ImageUtil.pixelate(selectedImage, 3);

Я ценю вашу помощь и скажите мне, если что-то не понятно или мне нужно добавьте что-нибудь к моему вопросу.

1 Ответ

0 голосов
/ 02 февраля 2020

Ниже приведены алгоритмы c этапов, которые вы можете применить:

  • Уменьшить оригинальное изображение - уменьшите разрешение примерно до 200x200.
  • Применение палитры с 16 цветами с размыванием.
    Проверьте подробности в документации rgb2ind MATLAB.
    В приведенном ниже примере я нашел палитру, используя эталонное изображение из вашего поста.
  • Измените размер в 3 раза по каждой оси, используя метод ближайший сосед для создания эффекта pixelate.

Реализация MATLAB:

% Palette of 16 colors
P = [  0     0     0
     160    80    44
     210   122   170
      14    16    83
     254   254   254
     255   113     0
      99    48    13
       1    86   158
       4    93    13
     192   192   192
      75    75    75
     233   165     0
     167    85   115
      85    15   105
       1   178   255
     116    11     7];

%Read original image
I = imread('I.jpg');

%Resize original image to resolution 200x200
J = imresize(I, [200, 200]);

% Convert shrunk RGB image to indexed image using palette P.
[IND, map] = rgb2ind(J, double(P)/255, 'dither'); %figure;imagesc(IND);colormap(map);axis image

% Convert from indexed image to RGB
RGB = ind2rgb(IND, map); %figure;imshow(RGB);

% Resize RGB by factor of x3 in each axis, use nearest-neighbor interpolation.
K = imresize(RGB, 3, 'nearest');

figure;imshow(K);

Результат:
enter image description here

Есть некоторые отличия от вашей справки (возможно, из-за различных алгоритмов уменьшения цвета).

...