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

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

The 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 org.bytedeco.opencv.opencv_calib3d.*;
import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_imgproc.*;
import static org.bytedeco.opencv.global.opencv_calib3d.*;
import static org.bytedeco.opencv.global.opencv_core.*;
import static org.bytedeco.opencv.global.opencv_imgproc.*;

/**
 *
 * @author Samuel Audet
 */
public class MarkedPlane {

    public MarkedPlane(int width, int height, Marker[] planeMarkers, double superScale) {
        this(width, height, planeMarkers, false, CvScalar.BLACK, CvScalar.WHITE, superScale);
    }
    public MarkedPlane(int width, int height, Marker[] markers,
            boolean initPrewarp, CvScalar foregroundColor, CvScalar backgroundColor, double superScale) {
        this.markers = markers;
        this.foregroundColor = foregroundColor;
        this.backgroundColor = backgroundColor;

//        this.srcPts    = CvMat.create(planeMarkers.length*4, 2);
//        this.dstPts    = CvMat.create(planeMarkers.length*4, 2);

        this.prewarp = null;
//        this.totalWarp = CvMat.create(3, 3);
//        this.tempWarp = CvMat.create(3, 3);

        if (initPrewarp) {
            prewarp = CvMat.create(3, 3);
            double minx = Double.MAX_VALUE, miny = Double.MAX_VALUE,
                   maxx = Double.MIN_VALUE, maxy = Double.MIN_VALUE;
            for (Marker m : markers) {
                double[] c = m.corners;
                minx = Math.min(Math.min(Math.min(Math.min(minx, c[0]), c[2]), c[4]), c[6]);
                miny = Math.min(Math.min(Math.min(Math.min(miny, c[1]), c[3]), c[5]), c[7]);
                maxx = Math.max(Math.max(Math.max(Math.max(maxx, c[0]), c[2]), c[4]), c[6]);
                maxy = Math.max(Math.max(Math.max(Math.max(maxy, c[1]), c[3]), c[5]), c[7]);
            }
            double aspect = (maxx-minx)/(maxy-miny);
            if (aspect > (double)width/height) {
                double h = (double)width/aspect;
//                srcPtsBuf.position(0); srcPtsBuf.put(new double[] { minx, miny, maxx, miny, maxx, maxy, minx, maxy });
//                dstPtsBuf.position(0); dstPtsBuf.put(new double[] { 0, height-h, width, height-h, width, height, 0, height });
//                srcPts.height = dstPts.height = 4;
//                cvFindHomography(srcPts, dstPts, preWarp);
                JavaCV.getPerspectiveTransform(
                        new double[] { minx, miny, maxx, miny, maxx, maxy, minx, maxy },
                        new double[] { 0, height-h, width, height-h, width, height, 0, height }, prewarp);
            } else {
                double w = height*aspect;
//                srcPtsBuf.position(0); srcPtsBuf.put(new double[] { minx, miny, maxx, miny, maxx, maxy, minx, maxy });
//                dstPtsBuf.position(0); dstPtsBuf.put(new double[] { 0, 0, w, 0, w, height, 0, height });
//                srcPts.height = dstPts.height = 4;
//                cvFindHomography(srcPts, dstPts, preWarp);
                JavaCV.getPerspectiveTransform(
                        new double[] { minx, miny, maxx, miny, maxx, maxy, minx, maxy },
                        new double[] { 0, 0, w, 0, w, height, 0, height }, prewarp);
            }
        }

        if (width > 0 && height > 0) {
            planeImage = IplImage.create(width, height, IPL_DEPTH_8U, 1);
            if (superScale == 1.0) {
                superPlaneImage = null;
            } else {
                superPlaneImage = IplImage.create((int)Math.ceil(width*superScale),
                        (int)Math.ceil(height*superScale), IPL_DEPTH_8U, 1);
            }
            setPrewarp(prewarp);
        }

        localSrcPts = CvMat.createThreadLocal(markers.length*4, 2);
        localDstPts = CvMat.createThreadLocal(markers.length*4, 2);
    }

    private Marker[] markers = null;
//    private CvPoint tempPts = new CvPoint(4);
//    private CvMat srcPts, dstPts;
    private CvMat prewarp;//, totalWarp, tempWarp;

    private IplImage planeImage = null, superPlaneImage = null;
    private CvScalar foregroundColor, backgroundColor;

    private ThreadLocal localSrcPts, localDstPts;

    public CvScalar getForegroundColor() {
        return foregroundColor;
    }
    public void setForegroundColor(CvScalar foregroundColor) {
        this.foregroundColor = foregroundColor;
        setPrewarp(prewarp);
    }

    public CvScalar getBackgroundColor() {
        return backgroundColor;
    }
    public void setBackgroundColor(CvScalar backgroundColor) {
        this.backgroundColor = backgroundColor;
        setPrewarp(prewarp);
    }

    public Marker[] getMarkers() {
        return markers;
    }
    public void setColors(CvScalar foregroundColor, CvScalar backgroundColor) {
        this.foregroundColor = foregroundColor;
        this.backgroundColor = backgroundColor;
        setPrewarp(prewarp);
    }

    public CvMat getPrewarp() {
        return prewarp;
    }
    public void setPrewarp(CvMat prewarp) {
        this.prewarp = prewarp;
        if (superPlaneImage == null) {
            cvSet(planeImage, backgroundColor);
        } else {
            cvSet(superPlaneImage, backgroundColor);
        }
        for (int i = 0; i < markers.length; i++) {
            if (superPlaneImage == null) {
                markers[i].draw(planeImage, foregroundColor, 1.0, prewarp);
            } else {
                markers[i].draw(superPlaneImage, foregroundColor, (double)
                        superPlaneImage.width()/planeImage.width(), prewarp);
            }
        }
        if (superPlaneImage != null) {
            cvResize(superPlaneImage, planeImage, CV_INTER_AREA);
        }
        //cvSaveImage("planeImage.png", planeImage);
    }

    public IplImage getImage() {
        return planeImage;
    }
    public int getWidth() {
        return planeImage.width();
    }
    public int getHeight() {
        return planeImage.height();
    }

    public double getTotalWarp(Marker[] imagedMarkers, CvMat totalWarp) {
        return getTotalWarp(imagedMarkers, totalWarp, false);
    }
    private static ThreadLocal
            tempWarp3x3 = CvMat.createThreadLocal(3, 3);
    public double getTotalWarp(Marker[] imagedMarkers, CvMat totalWarp, boolean useCenters) {
        double rmse = Double.POSITIVE_INFINITY;
        int pointsPerMarker = useCenters ? 1 : 4;

        CvMat srcPts = localSrcPts.get(); srcPts.rows(markers.length*pointsPerMarker);
        CvMat dstPts = localDstPts.get(); dstPts.rows(markers.length*pointsPerMarker);

        int numPoints = 0;
        for (Marker m1 : markers) {
            for (Marker m2 : imagedMarkers) {
                if (m1.id == m2.id) {
                    if (useCenters) {
                        srcPts.put(numPoints*2, m1.getCenter());
                        dstPts.put(numPoints*2, m2.getCenter());
                    } else {
                        srcPts.put(numPoints*2, m1.corners);
                        dstPts.put(numPoints*2, m2.corners);
                    }
                    numPoints += pointsPerMarker;
                    break;
                }
            }
        }

        if (numPoints > 4 || (srcPts.rows() == 4 && numPoints == 4)) {
            // compute homography ... should we use a robust method?
            srcPts.rows(numPoints); dstPts.rows(numPoints);
            if (numPoints == 4) {
                JavaCV.getPerspectiveTransform(srcPts.get(), dstPts.get(), totalWarp);
            } else {
                cvCopy(cvMat(findHomography(cvarrToMat(srcPts), cvarrToMat(dstPts))), totalWarp);
            }

            // compute transformed source<->dest RMSE
            srcPts.cols(1); srcPts.type(CV_64F, 2);
            dstPts.cols(1); dstPts.type(CV_64F, 2);
            cvPerspectiveTransform(srcPts, srcPts, totalWarp);
            srcPts.cols(2); srcPts.type(CV_64F, 1);
            dstPts.cols(2); dstPts.type(CV_64F, 1);

            rmse = 0;
            for (int i = 0; i < numPoints; i++) {
                double dx = dstPts.get(i*2  )-srcPts.get(i*2  );
                double dy = dstPts.get(i*2+1)-srcPts.get(i*2+1);
                rmse += dx*dx+dy*dy;
            }
            rmse = Math.sqrt(rmse/numPoints);
//            System.out.println(rmse);

            if (prewarp != null) {
                // remove pre-warp from total warp
                CvMat tempWarp = tempWarp3x3.get();
                cvInvert(prewarp, tempWarp);
                cvMatMul(totalWarp, tempWarp, totalWarp);
            }
//            System.out.println("totalWarp:\n" + totalWarp);
        }
        return rmse;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy