/*
* Copyright Inria and Bordeaux University.
* Author Jeremy Laviole. jeremy.laviole@inria.fr
* PapAR project is the open-source version of the
* PapARt project. License is LGPLv3, distributed with the sources.
* This project can also distributed with standard commercial
* licence for closed-sources projects.
*/
package fr.inria.papart.procam.camera;
import fr.inria.papart.procam.MarkerBoard;
import fr.inria.papart.procam.PaperScreen;
import fr.inria.papart.procam.Utils;
import fr.inria.papart.procam.camera.Camera;
import org.bytedeco.javacpp.opencv_core.CvMat;
import org.bytedeco.javacpp.opencv_core.IplImage;
import processing.core.PApplet;
import processing.core.PImage;
import processing.core.PMatrix3D;
import processing.core.PVector;
/**
*
* @author jeremylaviole
*/
public class TrackedView {
private PImage extractedImage = null;
private IplImage extractedIplImage = null;
// private data
private final PVector[] corner3DPos = new PVector[4];
private final PVector[] screenPixelCoordinates = new PVector[4];
private final PVector[] imagePixelCoordinates = new PVector[4];
// external information
private MarkerBoard board = MarkerBoard.INVALID_MARKERBOARD;
private PaperScreen paperScreen = null; // todo : invalid one...
private boolean useBoardLocation = false;
private boolean usePaperLocation = false;
private boolean useManualConrers = false;
private PVector bottomLeftCorner = new PVector(0, 0), captureSizeMM = new PVector(100, 100);
private int imageWidthPx = 128, imageHeightPx = 128;
// temporary variables
private IplImage mainImage;
private Camera camera;
// Public constructor for capturing the whole markerboard
public TrackedView(MarkerBoard board) {
this.board = board;
this.useBoardLocation = true;
allocateMemory();
// this.setImageHeightPx((int) board.getHeight());
// this.setImageWidthPx((int) board.getWidth());
this.setCaptureSizeMM(new PVector(board.getWidth(), board.getHeight()));
}
public TrackedView(PaperScreen paperScreen) {
this.paperScreen = paperScreen;
this.usePaperLocation = true;
allocateMemory();
// this.setImageHeightPx((int) board.getHeight());
// this.setImageWidthPx((int) board.getWidth());
this.setCaptureSizeMM(paperScreen.getDrawingSize());
}
public TrackedView() {
this.useManualConrers = true;
allocateMemory();
}
/**
*
* @param corners
*/
public void setCorners(PVector[] corners) {
if (corners.length == 4) {
for (int i = 0; i < 4; i++) {
screenPixelCoordinates[i] = corners[i];
}
}
}
public void init() {
extractedImage = new PImage(imageWidthPx, imageHeightPx, PApplet.RGB);
initiateImageCoordinates();
}
private void allocateMemory() {
for (int i = 0; i < 4; i++) {
corner3DPos[i] = new PVector();
}
}
private void initiateImageCoordinates() {
imagePixelCoordinates[0] = new PVector(0, imageHeightPx);
imagePixelCoordinates[1] = new PVector(imageWidthPx, imageHeightPx);
imagePixelCoordinates[2] = new PVector(imageWidthPx, 0);
imagePixelCoordinates[3] = new PVector(0, 0);
}
public PImage getViewOf(Camera camera) {
if (extractedImage == null) {
System.err.println("You should init the TrackedView before getting the view.");
return null;
}
if (camera.getIplImage() == null) {
return null;
}
this.mainImage = camera.getIplImage();
this.camera = camera;
CvMat homography = computeHomography();
Utils.remapImage(homography, camera.getIplImage(), extractedIplImage, extractedImage);
return extractedImage;
}
public IplImage getIplViewOf(Camera camera) {
if (camera.getIplImage() == null) {
return null;
}
this.mainImage = camera.getIplImage();
this.camera = camera;
CvMat homography = computeHomography();
Utils.remapImageIpl(homography, camera.getIplImage(), extractedIplImage);
return extractedIplImage;
}
private CvMat computeHomography() {
checkMemory();
computeCorners();
CvMat homography = Utils.createHomography(screenPixelCoordinates, imagePixelCoordinates);
return homography;
}
private void checkMemory() {
if (extractedIplImage == null) {
extractedIplImage = Utils.createImageFrom(extractedImage);
}
}
private void computeCorners() {
PMatrix3D pos = null;
if(useManualConrers){
return ;
}
if (usePaperLocation) {
pos = paperScreen.getLocation();
}
if (useBoardLocation) {
pos = board.getTransfoMat(camera).get();
}
if (pos == null) {
throw new RuntimeException("ERROR in TrackedView, report this.");
}
PMatrix3D tmp = new PMatrix3D();
tmp.apply(pos);
// bottom left
tmp.translate(bottomLeftCorner.x, bottomLeftCorner.y);
corner3DPos[0].x = tmp.m03;
corner3DPos[0].y = tmp.m13;
corner3DPos[0].z = tmp.m23;
// bottom right
tmp.translate(captureSizeMM.x, 0);
corner3DPos[1].x = tmp.m03;
corner3DPos[1].y = tmp.m13;
corner3DPos[1].z = tmp.m23;
// top right
tmp.translate(0, captureSizeMM.y, 0);
corner3DPos[2].x = tmp.m03;
corner3DPos[2].y = tmp.m13;
corner3DPos[2].z = tmp.m23;
// top left
tmp.translate(-captureSizeMM.x, 0, 0);
corner3DPos[3].x = tmp.m03;
corner3DPos[3].y = tmp.m13;
corner3DPos[3].z = tmp.m23;
for (int i = 0; i < 4; i++) {
screenPixelCoordinates[i] = camera.pdp.worldToPixel(corner3DPos[i], true);
}
}
public MarkerBoard getBoard() {
return this.board;
}
public PVector getBottomLeftCorner() {
return bottomLeftCorner;
}
public TrackedView setBottomLeftCorner(PVector bottomLeftCorner) {
this.bottomLeftCorner = bottomLeftCorner;
return this;
}
public PVector getCaptureSizeMM() {
return captureSizeMM;
}
public TrackedView setCaptureSizeMM(PVector captureSizeMM) {
this.captureSizeMM = captureSizeMM;
return this;
}
public int getImageWidthPx() {
return imageWidthPx;
}
public TrackedView setImageWidthPx(int imageWidthPx) {
this.imageWidthPx = imageWidthPx;
return this;
}
public int getImageHeightPx() {
return imageHeightPx;
}
public TrackedView setImageHeightPx(int imageHeightPx) {
this.imageHeightPx = imageHeightPx;
return this;
}
// @Override
// public void prepareToDisplayOn(PGraphicsOpenGL display) {
// throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
// }
//
// @Override
// public void addDisplay(PGraphicsOpenGL display) {
// throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
// }
//
// @Override
// public PImage getDisplayedOn(PGraphicsOpenGL display) {
// throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
// }
}