1

I am working on a project aiming to reproduce images using only a fixed number of convex hull / polygons.

I am using JavaFX to have a nice GUI.

A solution to the problem is a list of polygons drawn on a canvas, letting us obtain an image.

To evaluate the quality of the solution, I am taking the image to reproduce and the image obtained from the list of polygons and I calculate the distance between the color of each pixels.

If I have a null distance between the colors of each pixels, I can say that I reproduced the goal image.

The impletation I made of this function is really slow.

To summarize, I search, for each pixels what are the polygons that contains it and then I add their color in the correct order (I am using transparent color so order is important). I calculate the distance between this color and the color I try to reach (on the goal image). I sum up these distances and that's it !

private void computeEval() {
    PixelReader pixelReaderSolution = image.getPixelReader();
    AtomicReference<Double> eval2 = new AtomicReference<>((double) 0);
    Lock lock = new ReentrantLock();

    IntStream.range(0, (int) image.getWidth()).parallel()
            .forEach(x -> IntStream.range(0, (int) image.getHeight()).parallel()
                    .forEach(y -> {
                        Color colorSolution = pixelReaderSolution.getColor(x, y);
                        Point2D pixel = new Point2D(x, y);
                        AtomicReference<Color> pixelColor = new AtomicReference<>();
                        pixelColor.set(null);

                        polygons.stream()
                                .filter(convexPolygon -> convexPolygon.getAsPolygon().contains(pixel))
                                .forEach(convexPolygon -> {
                                    if (pixelColor.get() == null) {
                                        pixelColor.set(convexPolygon.color);
                                    } else {
                                        pixelColor.set(addColor(pixelColor.get(), convexPolygon.color));
                                    }
                                });
                        if (pixelColor.get() == null) {
                            pixelColor.set(Color.WHITE);
                        }
                        lock.lock();
                        eval2.updateAndGet(v -> v + distanceColor(colorSolution, pixelColor.get()));
                        lock.unlock();
                    }));
    evaluation = 1 - (eval2.get() / (3 * image.getWidth() * image.getHeight()));
}

In the past, I was using the function snapshot which was fast but that forced me to compute the evaluation inside a JavaFX thread; therefore, blocking my entire GUI by putting to much computations in GUI threads.

This current solution allows me to put the computations inside a Service but it is really slow.

I am a bit stuck on this and I am wondering if anyone could have an idea for me...

I may also be using JavaFX in a wrong way.

I can give more of the code, if people are wondering what's the different function around but I'm 100% that it is this function that slow down everything.

c0der
  • 18,467
  • 6
  • 33
  • 65
XanX3601
  • 15
  • 2
  • Wouldn't it be more efficient to test the final reproduced image against the original one ? When comparing two images each pixel is tested once. When checking the original image against all polygons, each pixel is tested multiple times. – c0der Dec 08 '18 at 13:00
  • That is what I was doing at the beginning.But the only way I know to do so is to add each Polygon to a [Group](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/Group.html) and then to make a snapshot out of it. But snapshot can only be used in JavaFX thread and I can't put all computations in JavaFX thread. Maybe there's a way to obtain an image without snapshot but I have search for it in vain... – XanX3601 Dec 08 '18 at 13:45
  • See also [*What is the best way to read pixels of a JavaFX Canvas?*](https://stackoverflow.com/q/45685190/230513) – trashgod Dec 09 '18 at 02:37

0 Answers0