algorithms-for-computing-li.../LinearRegressionTool/src/main/java/de/wwwu/awolf/presenter/evaluation/PictureProcessor.java

159 lines
5.9 KiB
Java

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<Data> {
private Mat image;
private Mat contour;
private Presenter presenter;
private File file;
private ArrayList<MatOfPoint> contours;
private double contourLength;
private Flow.Subscriber<? super Data> 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<? super Data> subscriber) {
this.subscriber = subscriber;
}
}