All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bytedeco.javacv.GNImageAlignerCL Maven / Gradle / Ivy

There is a newer version: 1.5.11
Show newest version
/*
 * Copyright (C) 2009-2012 Samuel Audet
 *
 * Licensed either under the Apache License, Version 2.0, or (at your option)
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation (subject to the "Classpath" exception),
 * either version 2, or any later version (collectively, the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *     http://www.gnu.org/licenses/
 *     http://www.gnu.org/software/classpath/license.html
 *
 * or as provided in the LICENSE.txt file that accompanied this code.
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.bytedeco.javacv;

import com.jogamp.opencl.CLImage2d;
import com.jogamp.opencl.CLImageFormat;
import com.jogamp.opencl.gl.CLGLContext;
import com.jogamp.opencl.gl.CLGLImage2d;
import com.jogamp.opengl.GL2;
import java.util.Arrays;
import org.bytedeco.javacv.ImageTransformer.Parameters;
import org.bytedeco.javacv.ImageTransformerCL.InputData;
import org.bytedeco.javacv.ImageTransformerCL.OutputData;

import org.bytedeco.opencv.opencv_core.*;
import static org.bytedeco.opencv.global.opencv_core.*;

/**
 *
 * @author Samuel Audet
 */
public class GNImageAlignerCL extends GNImageAligner implements ImageAlignerCL {
    public GNImageAlignerCL(ImageTransformerCL transformer, Parameters initialParameters,
            CLImage2d template0, double[] roiPts, CLImage2d target0) {
        this(transformer, initialParameters, template0, roiPts, target0, new GNImageAligner.Settings());
    }
    public GNImageAlignerCL(ImageTransformerCL transformer, Parameters initialParameters,
            CLImage2d template0, double[] roiPts, CLImage2d target0, GNImageAligner.Settings settings) {
        super(transformer, initialParameters);
        setSettings(settings);
        context = transformer.getContext();

        final int minLevel = settings.pyramidLevelMin;
        final int maxLevel = settings.pyramidLevelMax;

        this.template    = new IplImage[maxLevel+1];
        this.target      = new IplImage[maxLevel+1];
        this.transformed = new IplImage[maxLevel+1];
        this.residual    = new IplImage[maxLevel+1];
        this.mask        = new IplImage[maxLevel+1];

        this.templateCL    = new CLImage2d[maxLevel+1];
        this.targetCL      = new CLImage2d[maxLevel+1];
        this.transformedCL = new CLImage2d[maxLevel+1];
        this.residualCL    = new CLImage2d[maxLevel+1];
        this.maskCL        = new CLGLImage2d[maxLevel+1];
        this.maskrb        = new int[maxLevel+1];
        this.maskfb        = new int[maxLevel+1];
        int w = template0 != null ? template0.width  : target0.width;
        int h = template0 != null ? template0.height : target0.height;
        CLGLContext c = context.getCLGLContext();
//        GLContext glContext = c.getGLContext();
//        glContext.makeCurrent();
        GL2 gl = context.getGL2();
        gl.glGenRenderbuffers(maxLevel+1, maskrb, 0);
        gl.glGenFramebuffers(maxLevel+1, maskfb, 0);
        CLImageFormat f = new CLImageFormat(CLImageFormat.ChannelOrder.RGBA, CLImageFormat.ChannelType.FLOAT);
        for (int i = minLevel; i <= maxLevel; i++) {
            templateCL   [i] = i == minLevel && template0 != null ? template0 : c.createImage2d(w, h, f);
            targetCL     [i] = i == minLevel && target0   != null ? target0   : c.createImage2d(w, h, f);
            transformedCL[i] = c.createImage2d(w, h, f);
            residualCL   [i] = c.createImage2d(w, h, f);
            gl.glBindRenderbuffer(GL2.GL_RENDERBUFFER, maskrb[i]);
            gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, maskfb[i]);
            gl.glRenderbufferStorage(GL2.GL_RENDERBUFFER, GL2.GL_LUMINANCE8, w, h);
            gl.glFramebufferRenderbuffer(GL2.GL_FRAMEBUFFER, GL2.GL_COLOR_ATTACHMENT0, GL2.GL_RENDERBUFFER, maskrb[i]);
            assert gl.glCheckFramebufferStatus(GL2.GL_FRAMEBUFFER) == GL2.GL_FRAMEBUFFER_COMPLETE;
            maskCL[i] = c.createFromGLRenderbuffer(maskrb[i]);
            System.out.println(maskCL[i] + " " + maskCL[i].getElementSize() + " " + maskCL[i].getFormat());
            w /= 2;
            h /= 2;
        }
//        glContext.release();

        this.inputData = new InputData();
        this.outputData = new OutputData(false);
        this.templateChanged = new boolean[maxLevel+1];
        Arrays.fill(templateChanged, true);

        setConstrained(settings.constrained);
        setTemplateImageCL(template0, roiPts);
        setTargetImageCL(target0);
    }
    public void release() {
        final int minLevel = settings.pyramidLevelMin;
        final int maxLevel = settings.pyramidLevelMax;

        if (templateCL != null && targetCL != null && transformedCL != null &&
                residualCL != null && maskCL != null) {
            for (int i = minLevel; i <= maxLevel; i++) {
                if (i > minLevel) templateCL[i].release();
                if (i > minLevel) targetCL  [i].release();
                transformedCL[i].release();
                residualCL   [i].release();
                maskCL       [i].release();
            }
            templateCL = targetCL = transformedCL = residualCL = maskCL = null;
        }

        // NVIDIA drivers crash if we don't delete those before terminating
        context.getGLContext().makeCurrent();
        GL2 gl = context.getGL2();
        if (maskfb != null) {
            gl.glDeleteFramebuffers(maxLevel+1, maskfb, 0);
            maskfb = null;
        }
        if (maskrb != null) {
            gl.glDeleteRenderbuffers(maxLevel+1, maskrb, 0);
            maskrb = null;
        }
    }
    @Override protected void finalize() throws Throwable {
        super.finalize();
        release();
    }

    private final JavaCVCL context;
    private CLImage2d[] templateCL, targetCL, transformedCL, residualCL;
    private CLGLImage2d[] maskCL;
    private int[] maskrb, maskfb;
    private CLImage2d[] imagesCL = new CLImage2d[5];
    private InputData inputData;
    private OutputData outputData;
    private boolean[] templateChanged;

    @Override public IplImage getTemplateImage() {
        return getTemplateImage(true);
    }
    public IplImage getTemplateImage(boolean blocking) {
        if (templateChanged[pyramidLevel]) {
            templateChanged[pyramidLevel] = false;
            return template[pyramidLevel] = context.readImage(getTemplateImageCL(), template[pyramidLevel], blocking);
        } else {
            return template[pyramidLevel];
        }
    }
    @Override public void setTemplateImage(IplImage template0, double[] roiPts) {
        context.writeImage(templateCL[settings.pyramidLevelMin], template0, false);
        setTemplateImageCL(templateCL[settings.pyramidLevelMin], roiPts);
    }

    @Override public IplImage getTargetImage() {
        return getTargetImage(true);
    }
    public IplImage getTargetImage(boolean blocking) {
        return target[pyramidLevel] = context.readImage(getTargetImageCL(), target[pyramidLevel], blocking);
    }
    @Override public void setTargetImage(IplImage target0) {
        context.writeImage(targetCL[settings.pyramidLevelMin], target0, false);
        setTargetImageCL(targetCL[settings.pyramidLevelMin]);
    }

    @Override public IplImage getTransformedImage() {
        return getTransformedImage(true);
    }
    public IplImage getTransformedImage(boolean blocking) {
        return transformed[pyramidLevel] = context.readImage(getTransformedImageCL(), transformed[pyramidLevel], blocking);
    }

    @Override public IplImage getResidualImage() {
        return getResidualImage(true);
    }
    public IplImage getResidualImage(boolean blocking) {
        return residual[pyramidLevel] = context.readImage(getResidualImageCL(), residual[pyramidLevel], blocking);
    }

    @Override public IplImage getMaskImage() {
        return getMaskImage(true);
    }
    public IplImage getMaskImage(boolean blocking) {
        context.acquireGLObject(maskCL[pyramidLevel]);
        mask[pyramidLevel] = context.readImage(getMaskImageCL(), mask[pyramidLevel], blocking);
        context.releaseGLObject(maskCL[pyramidLevel]);
        return mask[pyramidLevel];
    }

    @Override public double getRMSE() {
        if (residualUpdateNeeded) {
            doRoi();
            doResidual();
        }
        return RMSE;
    }

    @Override public int getPixelCount() {
        if (residualUpdateNeeded) {
            doRoi();
            doResidual();
        }
        return outputData.dstCount;
    }

    @Override public int getOutlierCount() {
        return outputData.dstCountOutlier;
    }

    @Override public CvRect getRoi() {
        if (residualUpdateNeeded) {
            doRoi();
        }
        return roi.x(inputData.roiX).y(inputData.roiY).
                width(inputData.roiWidth).height(inputData.roiHeight);
    }

    @Override public IplImage[] getImages() {
        return getImages(true);
    }
    public IplImage[] getImages(boolean blocking) {
        images[0] = getTemplateImage(false);
        images[1] = getTargetImage(false);
        images[2] = getTransformedImage(false);
        images[3] = getResidualImage(false);
        images[4] = getMaskImage(blocking);
        return images;
    }

    public CLImage2d getTemplateImageCL() {
        return templateCL[pyramidLevel];
    }
    public void setTemplateImageCL(CLImage2d template0, double[] roiPts) {
        final int minLevel = settings.pyramidLevelMin;
        final int maxLevel = settings.pyramidLevelMax;

        if (roiPts == null && template0 != null) {
            int w = template0.width  << minLevel;
            int h = template0.height << minLevel;
            this.srcRoiPts.put(0.0, 0.0,  w, 0.0,  w, h,  0, h);
        } else {
            this.srcRoiPts.put(roiPts);
        }

        if (template0 == null) {
            return;
        }

//        if (templateCL == null || templateCL.length != settings.pyramidLevels) {
//            templateCL = new CLImage2d[settings.pyramidLevels];
//        }
        templateCL[minLevel] = template0;
        for (int i = minLevel+1; i <= maxLevel; i++) {
//            if (templateCL[i] == null) {
//                int w = templateCL[i-1].width/2;
//                int h = templateCL[i-1].height/2;
//                CLImageFormat format = new CLImageFormat(CLImageFormat.ChannelOrder.RGBA, CLImageFormat.ChannelType.FLOAT);
//                templateCL[i] = JavaCVCL.getCLContext().createImage2d(w, h, format);
//            }
            context.pyrDown(templateCL[i-1], templateCL[i]);
        }
        setPyramidLevel(maxLevel);
        Arrays.fill(templateChanged, true);
    }

    public CLImage2d getTargetImageCL() {
        return targetCL[pyramidLevel];
    }
    public void setTargetImageCL(CLImage2d target0) {
        final int minLevel = settings.pyramidLevelMin;
        final int maxLevel = settings.pyramidLevelMax;

//        if (targetCL == null || targetCL.length != settings.pyramidLevels) {
//            targetCL = new CLImage2d[settings.pyramidLevels];
//        }
        targetCL[minLevel] = target0;
        for (int i = minLevel+1; i <= maxLevel; i++) {
//            if (targetCL[i] == null) {
//                int w = targetCL[i-1].width/2;
//                int h = targetCL[i-1].height/2;
//                CLImageFormat format = new CLImageFormat(CLImageFormat.ChannelOrder.RGBA, CLImageFormat.ChannelType.FLOAT);
//                targetCL[i] = JavaCVCL.getCLContext().createImage2d(w, h, format);
//            }
            context.pyrDown(targetCL[i-1], targetCL[i]);
        }
        setPyramidLevel(maxLevel);
    }

    public CLImage2d getTransformedImageCL() {
        if (residualUpdateNeeded) {
            doRoi();
            doResidual();
        }
        return transformedCL[pyramidLevel];
    }
    public CLImage2d getResidualImageCL() {
        if (residualUpdateNeeded) {
            doRoi();
            doResidual();
        }
        return residualCL[pyramidLevel];
    }
    public CLImage2d getMaskImageCL() {
        return maskCL[pyramidLevel];
    }

    public CLImage2d[] getImagesCL() {
        imagesCL[0] = templateCL   [pyramidLevel];
        imagesCL[1] = targetCL     [pyramidLevel];
        imagesCL[2] = transformedCL[pyramidLevel];
        imagesCL[3] = residualCL   [pyramidLevel];
        imagesCL[4] = maskCL       [pyramidLevel];
        return imagesCL;
    }

    @Override protected void doHessianGradient(final double[] scale) {
        final double constraintError = parameters.getConstraintError();
        final double stepSize = settings.stepSize;

        cvSetZero(gradient);
        cvSetZero(hessian);

        Parallel.loop(0, n, new Parallel.Looper() {
        public void loop(int from, int to, int looperID) {
//        for (int i = 0; i < n; i++) {
        for (int i = from; i < to; i++) {
            tempParameters[i].set(parameters);
            tempParameters[i].set(i, tempParameters[i].get(i) + /*(1<




© 2015 - 2024 Weber Informatics LLC | Privacy Policy