package de.wwwu.awolf.presenter.evaluation; import de.wwwu.awolf.model.Line; import de.wwwu.awolf.model.communication.Data; import de.wwwu.awolf.model.communication.SubscriberType; import de.wwwu.awolf.model.communication.TypeData; import de.wwwu.awolf.presenter.Presenter; import de.wwwu.awolf.presenter.util.Logging; import org.opencv.core.*; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import javax.swing.*; import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; import java.io.File; import java.util.ArrayList; import java.util.concurrent.Flow; /** * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. * * @Author: Armin Wolf * @Email: a_wolf28@uni-muenster.de * @Date: 17.09.2017. */ public class PictureProcessor implements Flow.Publisher { private Mat image; private Mat contour; private Presenter presenter; private File file; private ArrayList contours; private double contourLength; private Flow.Subscriber subscriber; /** * Konstruktor * * @param presenter Presenter * @param file Bilddatei */ public PictureProcessor(Presenter presenter, File file) { this.file = file; this.presenter = presenter; subscribe(presenter); } /** * startet den Import des Bild und die Vorverarbeitung */ public void run() { image = Imgcodecs.imread(file.getAbsolutePath()); contour = process(image); contourLength = image.width() * 0.3; createInputData(); } /** * Vorverarbeitung des Eingabebilds. Dabei wird auf verschiedene OpenCV Methoden zurückgegriffen. * * @param image Eingabebild * @return Matrix representation des Bilds */ private Mat process(Mat image) { Mat threshold = new Mat(image.width(), image.height(), CvType.CV_8UC1); Mat source = new Mat(image.width(), image.height(), CvType.CV_8UC1); Imgcodecs.imwrite(file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf(".")) + "-orig.png", image); Imgproc.cvtColor(image, source, Imgproc.COLOR_BGR2GRAY); Imgcodecs.imwrite(file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf(".")) + "-Greyscale.png", source); Imgproc.GaussianBlur(source, threshold, new Size(3, 3), 0, 0); Imgproc.Canny(threshold, source, 300, 600, 5, true); Imgcodecs.imwrite(file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf(".")) + "-Canny.png", source); //Konturen berechnen und filtern contours = new ArrayList<>(); Imgproc.findContours(source, contours, new Mat(), Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0, 0)); Mat viscont = new Mat(source.size(), source.type()); double minArea = 50; double maxArea = 0.2 * image.cols() * image.rows(); for (int i = 0; i < contours.size(); i++) { double acutualArea = Imgproc.contourArea(contours.get(i)); if (minArea < acutualArea && maxArea > acutualArea) { Imgproc.drawContours(viscont, contours, i, new Scalar(255, 0, 0), 1); } } Imgcodecs.imwrite(file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf(".")) + "-Contour.png", viscont); Mat resized = new Mat(); Imgproc.resize(viscont, resized, new Size(560, 560)); SwingUtilities.invokeLater(() -> { JDialog dialog = new JDialog(); dialog.setSize(560, 560); JLabel label = new JLabel(); label.setSize(560, 560); label.setIcon(new ImageIcon(toBufferedImage(resized))); dialog.add(label); dialog.setVisible(true); }); return viscont; } /** * Das Bild wird passend umgewandelt, um im nächsten Schritt visualisiert werden zu können. * * @param m Matrix representation des Bilds * @return visualisierbares Bild */ private BufferedImage toBufferedImage(Mat m) { int type = BufferedImage.TYPE_BYTE_GRAY; if (m.channels() > 1) { type = BufferedImage.TYPE_3BYTE_BGR; } int bufferSize = m.channels() * m.cols() * m.rows(); byte[] b = new byte[bufferSize]; m.get(0, 0, b); // get all the pixels BufferedImage image = new BufferedImage(m.cols(), m.rows(), type); final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); System.arraycopy(b, 0, targetPixels, 0, b.length); return image; } /** * Das gefilerte Bild ist bereit ins Modell aufgenommen zu werden um darauf dann die Algorithmen laufen zu lassen. */ private void createInputData() { Thread t = new Thread(() -> { double minArea = 50; double maxArea = 0.2 * image.cols() * image.rows(); int id = 0; for (int j = 0; j < contours.size(); j++) { Point[] p = contours.get(j).toArray(); double acutualArea = Imgproc.contourArea(contours.get(j)); if (minArea < acutualArea && maxArea > acutualArea) { for (int i = 0; i < p.length; i++) { Line line = new Line(-1 * (500 - p[i].x), p[i].y); line.setId("" + id++); presenter.getModel().getLines().add(line); } } } TypeData data = new TypeData(); data.setType(SubscriberType.PICTURE); this.subscriber.onNext(data); }); t.start(); try { t.join(); } catch (InterruptedException e) { Logging.logError(e.getMessage(), e); Thread.currentThread().interrupt(); } } @Override public void subscribe(Flow.Subscriber subscriber) { this.subscriber = subscriber; } }