/* * 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 java.util.ArrayList; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; import org.bytedeco.javacpp.opencv_core.IplImage; import java.util.logging.Level; import java.util.logging.Logger; import static org.bytedeco.javacpp.opencv_core.IPL_DEPTH_64F; import static org.bytedeco.javacpp.opencv_core.IPL_DEPTH_8U; import static org.bytedeco.javacpp.opencv_core.cvConvertScale; import static org.bytedeco.javacpp.opencv_imgproc.CV_BGR2GRAY; import static org.bytedeco.javacpp.opencv_imgproc.CV_RGBA2GRAY; import static org.bytedeco.javacpp.opencv_imgproc.cvCvtColor; import org.bytedeco.javacv.JavaCV; /** * * @author jeremylaviole */ class CameraThread extends Thread { private final Camera camera; private boolean compute; public boolean stop; private IplImage image; public CameraThread(Camera camera) { this.camera = camera; stop = false; } private final int nbThreads = 4; private ExecutorService threadPool = null; private void tryInitThreadPool() { if (threadPool == null) { this.initThreadPool(); } } private void initThreadPool() { threadPool = Executors.newFixedThreadPool(nbThreads); // threadPool = Executors.newCachedThreadPool(); } @Override public void run() { while (!stop) { camera.grab(); image = camera.getIplImage(); // TODO: check if img can be null... if (image != null && compute && !camera.getTrackedSheets().isEmpty()) { if (thresholdedImage == null) { initGrayScale(); } this.compute(); } } } public void compute() { try { camera.sheetsSemaphore.acquire(); for (MarkerBoard sheet : camera.getTrackedSheets()) { if (sheet.useARToolkit()) { computeGrayScaleImage(); break; } } // for (MarkerBoard markerBoard : camera.getTrackedSheets()) { // if (markerBoard.useARToolkit()) { // markerBoard.updatePosition(camera, grayImage); // } else { // markerBoard.updatePosition(camera, image); // } // } updateParallel(); camera.sheetsSemaphore.release(); } catch (InterruptedException ex) { Logger.getLogger(CameraThread.class.getName()).log(Level.SEVERE, null, ex); } } protected void updateParallel() { tryInitThreadPool(); ArrayList<FutureTask<DepthPixelTask>> tasks = new ArrayList<>(); for (MarkerBoard sheet : camera.getTrackedSheets()) { DepthPixelTask depthPixelTask = new DepthPixelTask(sheet); FutureTask<DepthPixelTask> task = new FutureTask<DepthPixelTask>(depthPixelTask); threadPool.submit(task); tasks.add(task); } // try { // for (FutureTask<DepthPixelTask> task : tasks) { // task.get(); // } // } catch (ExecutionException e) { // } catch (InterruptedException e) { // } } class DepthPixelTask implements Callable { private final MarkerBoard markerBoard; public DepthPixelTask(MarkerBoard markerBoard) { this.markerBoard = markerBoard; } @Override public Object call() { if (markerBoard.useARToolkit()) { markerBoard.updatePosition(camera, grayImage); } else { markerBoard.updatePosition(camera, image); } return null; } } private IplImage grayImage, tempImage2, sumImage, sqSumImage, thresholdedImage = null; private int width, height, depth, channels; private void initGrayScale() { width = image.width(); height = image.height(); depth = image.depth(); channels = image.nChannels(); if (depth != IPL_DEPTH_8U || channels > 1) { grayImage = IplImage.create(width, height, IPL_DEPTH_8U, 1); } if (depth != IPL_DEPTH_8U && channels > 1) { tempImage2 = IplImage.create(width, height, IPL_DEPTH_8U, 3); } sumImage = IplImage.create(width + 1, height + 1, IPL_DEPTH_64F, 1); sqSumImage = IplImage.create(width + 1, height + 1, IPL_DEPTH_64F, 1); thresholdedImage = IplImage.create(width, height, IPL_DEPTH_8U, 1); } private void computeGrayScaleImage() { // if (depth != IPL_DEPTH_8U && channels > 1) { // cvConvertScale(image, tempImage2, 255 / image.highValue(), 0); // cvCvtColor(tempImage2, grayImage, channels > 3 ? CV_RGBA2GRAY : CV_BGR2GRAY); //// image = tempImage; // } else if (depth != IPL_DEPTH_8U) { // cvConvertScale(image, grayImage, 255 / image.highValue(), 0); //// image = tempImage; // } else if (channels > 1) { cvCvtColor(image, grayImage, channels > 3 ? CV_RGBA2GRAY : CV_BGR2GRAY); // image = tempImage; // } /* boolean whiteMarkers = false; int thresholdWindowMax = 63; int thresholdWindowMin = 5; float thresholdVarMultiplier = 1.0f; float thresholdKBlackMarkers = 0.6f; float thresholdKWhiteMarkers = 1.0f; //long time1 = System.currentTimeMillis(); JavaCV.adaptiveThreshold(image, sumImage, sqSumImage, thresholdedImage, whiteMarkers, thresholdWindowMax, thresholdWindowMin, thresholdVarMultiplier, whiteMarkers ? thresholdKWhiteMarkers : thresholdKBlackMarkers); //CanvasFrame.global.showImage(thresholded, 0.5); //CanvasFrame.global.waitKey(); //long time2 = System.currentTimeMillis(); return thresholdedImage; */ } public boolean isCompute() { return compute; } public void setCompute(boolean compute) { this.compute = compute; if(compute == false && this.threadPool != null){ this.threadPool.shutdown(); this.threadPool = null; } } public void stopThread() { stop = true; } }