Изображение Javafx в низкополигональном конвертере - PullRequest
0 голосов
/ 26 июня 2018

Я пытаюсь создать программу с javafx, которая будет конвертировать картинку следующим образом: left: normal picture, right : low poly picture

На этой картинке фон на самом деле не такой, как яМне бы это понравилось, но авокадо в середине - отличный пример того, чего я хочу достичь.Теперь у меня есть два фильтра, которые будут находить края на изображении в зависимости от яркости следующим образом:

public void processImage() {
    ww = (int) Math.ceil(image.getWidth());
    hh = (int) Math.ceil(image.getHeight());
    pixelAmount = (long) ww * (long) hh;
    pxDA = new pxInfo[ww][hh];
    PixelReader pr = image.getPixelReader();
    if(pr != null) {
        System.out.println("pixel reader found");
        WritableImage i = new WritableImage(ww, hh);
        for(int x = 0; x < ww; x++) {
            for(int y = 0; y < hh; y++) {
                Color c = pr.getColor(x, y);
                double a = c.getOpacity();
                double r = c.getRed();
                double g = c.getBlue();
                double b = c.getBlue();

                double[][] gray = new double[3][3];
                for (int j = 0; j < 3; j++) {
                    for (int k = 0; k < 3; k++) {
                        if(!((j == 0 && x == 0) || (k == 0 && y == 0) || (j 
== 2 && x == ww - 1) || (k == 2 && y == hh - 1))) {
                            Color cl = pr.getColor(x - 1 + j, y - 1 + k);
                            gray[j][k] = 0.299 * cl.getRed() +  0.587 * 
cl.getGreen() + 0.114 * cl.getBlue();
                        }
                    }
                }

                // apply filter
                double gray1 = 0, gray2 = 0;
                for (int j = 0; j < 3; j++) {
                    for (int k = 0; k < 3; k++) {
                        gray1 += gray[j][k] * filter1[j][k];
                        gray2 += gray[j][k] * filter2[j][k];
                    }
                }
                double magnitude = clamp(0.0, 1.0 - Math.sqrt(gray1 * gray1 + 
gray2 * gray2), 1.0);
                Color color = new Color(magnitude, magnitude, magnitude, 1);
                i.getPixelWriter().setColor(x, y, color);
            }
        }
        stackPane.getChildren().add(new ImageView(i));
    }
}

И эта часть кода работает довольно хорошо, вот некоторые результаты:

до фильтра: before applying filters после фильтра: after applying filters Но проблема в том, что я не знаю, куда идти дальше.Я ищу все виды алгоритмов в Интернете, но я не могу найти ничего с четким объяснением, поэтому я решил спросить здесь.Так что, если вы знаете какой-нибудь алгоритм / фильтр, который я могу применить для его улучшения, я бы хотел услышать.

Тогда есть еще одна часть, где мне действительно нужно создавать треугольники / многоугольники.Скажем, у меня все фильтры применены и т.д., что мне тогда делать?Например, как мне отличить фигуру от просто изображения в градациях серого?Любая помощь будет принята с благодарностью.

Заранее спасибо,

Lenardjee

1 Ответ

0 голосов
/ 02 апреля 2019

Я не знаком с JavaFX, в частности, но я пытался решить очень похожую проблему, используя Python и OpenCV :

https://github.com/tasercake/lowpolypy

Вот как я это сделал.


Общий поток:

  1. Изображение предварительной обработки (двустороннее / гауссово размытие для удаления шума и т. Д.)
  2. Получить ключевые точки из изображения (используя методы, подробно описанные ниже)
  3. Получить многоугольники из ключевых точек (используя триангуляцию Делоне или аналогичный алгоритм)
  4. Затенение полигонов (например, используя средний цвет всех пикселейвнутри многоугольника)
  5. Постобработка (регулировка контрастности, насыщенности и т. д.)

1.Предварительная обработка

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

Этого можно добиться с помощью фильтра, такого как Двусторонний фильтр или Гауссов фильтр .

Возможно, вы также захотите уменьшить изображение здесь, чтобы ускорить обработку, но это не обязательно.


2.Извлечение ключевой точки

Это, вероятно, самая сложная часть, которая потребует наиболее тонкой настройки / экспериментов.

Некоторые методы, которые вы можете попробовать:

Canny Edge Detection

Любая библиотека манипуляций с изображениями / компьютерного зрения (например, OpenCV) должна иметь встроенную функцию.

Этот метод дает вам логическое изображение, гдепотенциальные ребра помечены как «True».Затем вы можете выбрать случайное подмножество этих точек и преобразовать их в координаты (X, Y) (или любой другой формат, который вам наиболее удобен).

Я нашел этот метод в сочетании с небольшим количеством рандомизациитребовать наименьшей подстройки.

лапласиан Гауссовский

Это еще один метод обнаружения характерных особенностей в изображении, но основанный на второй производной пикселей изображения(в отличие от фильтра Канни, который основан на первой производной).

Этот фильтр возвращает изображение, которое можно нормализовать и использовать в качестве маски веса для случайной выборки набора ключевых точек (возможно, естьболее эффективные способы использования фильтра, чем этот, но меня это не беспокоило).

Случайная замена

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

Я обнаружил, что это помогает ввести сомЭстетически приятные неровности в конечном результате.

Перемешивание ключевых точек

В дополнение к прямой замене небольшого подмножества ключевых точек, я также «перемешал» (произвольно переведенный) каждую ключевую точку на очень маленькое количество,Это помогает ввести еще больше случайности и позволяет вам выполнить несколько прогонов вашей программы, чтобы получить один потенциально хороший вывод.

ПРИМЕЧАНИЕ : не забудьте добавить 4 углавашего изображения в качестве ключевых точек, или вы получите пустые / черные области вокруг вашего вывода.


3.Соедините ключевые точки с полигонами

Триангуляция Делоне - это алгоритм, который соединяет набор точек на плоскости таким образом, чтобы максимизировать наименьший угол в каждом сформированном треугольнике.(Очевидно, это не сработает, если вам не нужны исключительно треугольники).


4.Тени полигонов

Для каждого полигона вы хотите получить среднее значение всех пикселей изображения в пределах области, охватываемой полигоном.OpenCV имеет функцию (cv2.mean(image, mask)), которая позволяет вам сделать это в несколько строк, передавая многоугольник в виде двоичной маски.


Некоторые результаты:

fox | fox_lowpoly

eminem | eminem_lowpoly

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...