private void calibrateGeometry(final FrameGrabber.Array frameGrabberArray) throws Exception {
// create camera calibrators...
geometricCalibrators = new GeometricCalibrator[cameraDevices.length];
proCamGeometricCalibrators = new ProCamGeometricCalibrator[projectorDevices.length];
for (int i = 0; i < geometricCalibrators.length; i++) {
geometricCalibrators[i] = new GeometricCalibrator(geometricCalibratorSettings,
markerDetectorSettings, boardPlane, cameraDevices[i]);
}
// create projector calibrators...
for (int i = 0; i < proCamGeometricCalibrators.length; i++) {
GeometricCalibrator g = new GeometricCalibrator(geometricCalibratorSettings,
markerDetectorSettings, projectorPlanes[i], projectorDevices[i]);
proCamGeometricCalibrators[i] = new ProCamGeometricCalibrator(
geometricCalibratorSettings, markerDetectorSettings,
boardPlane, projectorPlanes[i], geometricCalibrators, g);
}
// define the device at origin to be the first camera...
final int cameraAtOrigin = 0;
int currentProjector = 0;
final boolean[] hasDetectedMarkers = new boolean[frameGrabberArray.size()];
final IplImage[] colorImages = new IplImage[frameGrabberArray.size()];
boolean done = false;
long lastAddedTime = -1;
while (!done && !isCancelled()) {
// display projector pattern
if (currentProjector < projectorCanvasFrames.length) {
projectorCanvasFrames[currentProjector].showImage(
proCamGeometricCalibrators[currentProjector].getProjectorImage());
projectorCanvasFrames[currentProjector].waitLatency();
}
// capture images from cameras
frameGrabberArray.trigger();
final IplImage[] grabbedImages = frameGrabberArray.grab();
assert (grabbedImages.length == cameraDevices.length);
final int curProj = currentProjector;
for (int i = 0; i < grabbedImages.length; i++) {
if (grabbedImages[i] == null) {
throw new Exception("Image grabbed from " + cameraDevices[i].getSettings().getName() + " is null, unexcepted end of stream?");
}
}
// for (int i = 0; i < grabbedImages.length && !isCancelled(); i++) {
Parallel.loop(0, grabbedImages.length, new Looper() {
public void loop(int from, int to, int looperID) {
for (int i = from; i < to && !isCancelled(); i++) {
// gamma "uncorrection", linearization
double gamma = frameGrabberArray.getFrameGrabbers()[i].getGamma();
if (gamma != 1.0) {
grabbedImages[i].applyGamma(gamma);
}
// convert camera image to color so we can draw in color
if (colorImages[i] == null) {
colorImages[i] = IplImage.create(grabbedImages[i].width(), grabbedImages[i].height(), IPL_DEPTH_8U, 3);
}
switch (grabbedImages[i].depth()&~IPL_DEPTH_SIGN) {
case 8:
cvCvtColor(grabbedImages[i], colorImages[i], CV_GRAY2RGB);
break;
case 16:
ByteBuffer colorBuf = colorImages[i].getByteBuffer();
ShortBuffer shortBuf = grabbedImages[i].getByteBuffer().asShortBuffer();
for (int j = 0; j < colorBuf.limit()/3; j++) {
byte msb = (byte)((int)(shortBuf.get()>>8) & 0xFF);
colorBuf.put(msb);
colorBuf.put(msb);
colorBuf.put(msb);
}
break;
default: assert(false);
}
// process camera images.. detect markers..
if (curProj < projectorCanvasFrames.length) {
hasDetectedMarkers[i] = proCamGeometricCalibrators[curProj].processCameraImage(grabbedImages[i], i) != null;
proCamGeometricCalibrators[curProj].drawMarkers(colorImages[i], i);
} else {
hasDetectedMarkers[i] = geometricCalibrators[i].processImage(grabbedImages[i]) != null;
geometricCalibrators[i].drawMarkers(colorImages[i]);
}
// show camera images with detected markers drawn
if (cameraCanvasFrames[i] != null) {
cameraCanvasFrames[i].showImage(colorImages[i], cameraSettings.getMonitorWindowsScale());
//cameraCanvasFrames[i].showImage(geometricCalibrators[i].getMarkerDetector().getBinarized());
}
}}});
// check if we have any missing markers from all camera images
boolean missing = false;
for (int i = 0; i < hasDetectedMarkers.length; i++) {
if (!hasDetectedMarkers[i]) {
missing = true;
break;
}
}
// if we have waited long enough, and all calibrators want to add
// the markers, then add them
long time = System.currentTimeMillis();
if (!missing && time-lastAddedTime > geometricCalibratorSettings.timeIntervalMin) {
lastAddedTime = time;
for (int i = 0; i < cameraCanvasFrames.length; i++) {
// the calibrators have decided to save these markers, make a little flash effect
if (cameraCanvasFrames[i] != null) {
cameraCanvasFrames[i].showColor(Color.WHITE);
}
if (currentProjector < projectorCanvasFrames.length) {
// the cameras are calibrated through the current projector...
proCamGeometricCalibrators[currentProjector].addMarkers(i);
if (proCamGeometricCalibrators[currentProjector].getImageCount()
>= geometricCalibratorSettings.imagesInTotal) {
projectorCanvasFrames[currentProjector].showColor(Color.BLACK);
done = true;
}
} else {
geometricCalibrators[i].addMarkers();
if (geometricCalibrators[i].getImageCount()
>= geometricCalibratorSettings.imagesInTotal) {
done = true;
}
}
}
if (done && currentProjector+1 < proCamGeometricCalibrators.length) {
currentProjector++;
done = false;
}
Thread.sleep(200);
}
}
// once we have accumulated enough markers, proceed to calibration
if (!isCancelled()) {
GeometricCalibrator calibratorAtOrigin = geometricCalibrators[cameraAtOrigin];
for (int i = 0; i < geometricCalibrators.length; i++) {
geometricCalibrators[i].calibrate(geometricCalibratorSettings.useMarkerCenters);
if (geometricCalibrators[i] != calibratorAtOrigin) {
calibratorAtOrigin.calibrateStereo(
geometricCalibratorSettings.useMarkerCenters, geometricCalibrators[i]);
}
}
for (int i = 0; i < proCamGeometricCalibrators.length; i++) {
proCamGeometricCalibrators[i].calibrate(