Perspektivní napasování fotek

Vyfotíme placatou scénu (například černou mřížku namalovanou na stole) dvakrát z různých úhlů. Pak o něco později chceme přesně zjistit, odkud jsme kterou fotku fotili.

Postup:

  1. najdeme na první fotce (aspoň) čtyři výrazné body,
  2. najdeme ty samé body na druhé fotce,
  3. spočítáme, jaká geometrická transformace vyrobí z jedněch bodů ty druhé,
  4. dopočítáme, z jakého místa jsme fotili druhou fotku.
Buďto potřebujeme vědět všechny podrobnosti o použité kameře, anebo vědět, odkud byla jedna z fotek pořízená. Rozsekneme to tak, že si prostě vymyslíme pozici kamery na první fotce.

Dosavadní kód

Dostali jsme se jenom k hledání výrazných bodů. Následující program zpracuje zadanou fotku. V původním nastavení to je "a.jpg". Musíte stáhnout nebo vyrobit vlastní fotku a program pak nasměrovat na ni.

A jako obvykle, musíte v nastavení projektu ⇒ Java Build Path mít přidanou knihovnu OpenCV.

HelloCV.java

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.InputStream;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.core.MatOfKeyPoint;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.imgproc.Imgproc;
import org.opencv.features2d.FeatureDetector;
import org.opencv.imgcodecs.Imgcodecs;

public class HelloCV {
	public static void main(String[] args){
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
		Mat img;
		img = Imgcodecs.imread("a.jpg");
		FeatureDetector detector = FeatureDetector.create(FeatureDetector.HARRIS);
		MatOfKeyPoint points = new MatOfKeyPoint();
		detector.detect(img, points);
		for (int i=0; i<points.rows(); i++) {
			double x = points.get(i, 0)[0];
			double y = points.get(i, 0)[1];
			Imgproc.circle(img, new Point(x, y), 5, new Scalar(0,0,255));
		}
		JFrame window= new JFrame();
		imshow(img, window);
	}
	
	public static void imshow(Mat img, JFrame frame) {
		MatOfByte matOfByte = new MatOfByte();
		Imgcodecs.imencode(".jpg", img, matOfByte);
		byte[] byteArray = matOfByte.toArray();
		BufferedImage bufImage = null;
		InputStream in = new ByteArrayInputStream(byteArray);
		bufImage = ImageIO.read(in);
		frame.getContentPane().removeAll();
		frame.getContentPane().add(new JLabel(new ImageIcon(bufImage)));
		frame.pack();
		frame.setVisible(true);
	}
}