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

org.bytedeco.javacv.ProjectiveTransformer 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 static org.bytedeco.javacpp.opencv_calib3d.*;
import static org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_imgproc.*;
import static org.bytedeco.javacv.cvkernels.*;

/**
 *
 * @author Samuel Audet
 */
public class ProjectiveTransformer implements ImageTransformer {
    public ProjectiveTransformer() {
        this(null, null, null, null, null, new double[0], null);
    }
    public ProjectiveTransformer(double[] referencePoints) {
        this(null, null, null, null, null, referencePoints, null);
    }
    public ProjectiveTransformer(ProjectiveDevice d1, ProjectiveDevice d2, CvMat n,
            double[] referencePoints1, double[] referencePoints2) {
        // assuming d1 has identity values, use d2's stuff directly
        this(d1.cameraMatrix, d2.cameraMatrix, d2.R, d2.T, n, referencePoints1, referencePoints2);
    }
    public ProjectiveTransformer(CvMat K1, CvMat K2, CvMat R, CvMat t, CvMat n,
            double[] referencePoints1, double[] referencePoints2) {
        this.K1    = K1 == null ? null : K1.clone();
        this.K2    = K2 == null ? null : K2.clone();
        this.invK1 = K1 == null ? null : K1.clone();
        this.invK2 = K2 == null ? null : K2.clone();
        if (K1 != null) {
            cvInvert(K1, invK1);
        }
        if (K2 != null) {
            cvInvert(K2, invK2);
        }
        this.R = R == null ? null : R.clone();
        this.t = t == null ? null : t.clone();
        this.n = n == null ? null : n.clone();

        this.referencePoints1 = referencePoints1 == null ? null : referencePoints1.clone();
        this.referencePoints2 = referencePoints2 == null ? null : referencePoints2.clone();
    }

    protected static ThreadLocal
            H3x3   = CvMat.createThreadLocal(3, 3),
            pts4x1 = CvMat.createThreadLocal(4, 1, CV_64F, 2);

    protected CvMat K1 = null, K2 = null, invK1 = null, invK2 = null, R = null, t = null, n = null;
    protected double[] referencePoints1 = null, referencePoints2 = null;
    protected CvScalar fillColor = cvScalar(0.0, 0.0, 0.0, 1.0);

    protected KernelData kernelData = null;
    protected CvMat[] H = null;

    public CvScalar getFillColor() {
        return fillColor;
    }
    public void setFillColor(CvScalar fillColor) {
        this.fillColor = fillColor;
    }

    public double[] getReferencePoints1() {
        return referencePoints1;
    }
    public double[] getReferencePoints2() {
        return referencePoints2;
    }
    public CvMat getK1() {
        return K1;
    }
    public CvMat getK2() {
        return K2;
    }
    public CvMat getInvK1() {
        return invK1;
    }
    public CvMat getInvK2() {
        return invK2;
    }
    public CvMat getR() {
        return R;
    }
    public CvMat getT() {
        return t;
    }
    public CvMat getN() {
        return n;
    }

    protected void prepareHomography(CvMat H, int pyramidLevel, Parameters p, boolean inverse) {
        if (K2 != null && invK1 != null && R != null && t != null && p.fakeIdentity) {
            // no identity available for plane parameter...
            // fakeIdentity needs to be implemented..
            cvSetIdentity(H);
            return;
        }

        if (inverse) {
            H.put(p.getH());
        } else {
            cvInvert(p.getH(), H);
        }

        // adjust the scale of the transformation based on the pyramid level
        if (pyramidLevel > 0) {
            int scale = 1<= 8) {
//                    projectiveParameters[i] += scale;
//                } else {
//                    // translation vector
//
//                    // assuming a reference plane at [0, 0, 1],
//                    // this is about 1% of image resolution?
//                    projectiveParameters[i] += 0.01 * scale;
//                }
//            }
//            setUpdateNeeded(true);
//            return false;
//        }
        public double getConstraintError() {
            update();
            return constraintError;
        }
        public void set(CvMat setH, boolean inverse) {
            if (projectiveParameters.length == 8 && referencePoints1 != null) {
                if (inverse) {
                    cvInvert(setH, H);
                } else if (setH != H) {
                    cvCopy(setH, H);
                }
                if (referencePoints1.length == 0) {
                    // direct homography parameterization
                    for (int i = 0; i < 8; i++) {
                        projectiveParameters[i] = H.get(i)/H.get(8);
                    }
                } else {
                    // 4 point parametrization
                    CvMat pts = pts4x1.get().put(referencePoints1);
                    cvPerspectiveTransform(pts, pts, H);
                    pts.get(projectiveParameters);
                }
                setUpdateNeeded(true);
            } else {
                throw new UnsupportedOperationException("Set homography operation not supported.");
            }
        }
        public void compose(ImageTransformer.Parameters p1, boolean inverse1,
                ImageTransformer.Parameters p2, boolean inverse2) {
            Parameters pp1 = (Parameters)p1, pp2 = (Parameters)p2;
            if (K2 != null && invK1 != null && R != null && t != null && pp1.fakeIdentity) {
                // no identity available for plane parameter...
                // fakeIdentity needs to be implemented..
                return;
            }

            compose(pp1.getH(), inverse1, pp2.getH(), inverse2);
        }
        public void compose(CvMat H1, boolean inverse1, CvMat H2, boolean inverse2) {
            if (inverse1 && inverse2) {
                cvMatMul(H2, H1, H);
                cvInvert(H, H);
            } else if (inverse1) {
                cvInvert(H1, H);
                cvMatMul(H, H2, H);
            } else if (inverse2) {
                cvInvert(H2, H);
                cvMatMul(H1, H, H);
            } else {
                cvMatMul(H1, H2, H);
            }
            set(H, false);
        }

        public CvMat getH() {
            update();
            return H;
        }
        public CvMat getN() {
            update();
            return n2;
        }
        public CvMat getR() {
            update();
            return R2;
        }
        public CvMat getT() {
            update();
            return t2;
        }

        protected void update() {
            if (!isUpdateNeeded()) {
                return;
            }

            if (referencePoints1 != null && (referencePoints1.length == 0 || referencePoints1.length == 8)) {
                if (referencePoints1.length == 0) {
                    // direct homography parameterization
                    H.put(0, projectiveParameters, 0, 8);
                    H.put(8, 1);
                } else {
                    // 4 point parameterization
                    JavaCV.getPerspectiveTransform(referencePoints1, projectiveParameters, H);
                }
//                if (K1 != null && invK2 != null && n != null) {
//                    CvMat Hprime = CvMat.take(3, 3);
//                    cvCopy(H, Hprime);
//                    if (R2 == null) {
//                        R2 = CvMat.create(3, 3);
//                    }
//                    if (t2 == null) {
//                        t2 = CvMat.create(3, 1);
//                    }
//
//                    cvMatMul(invK2,  Hprime, Hprime);
//                    cvMatMul(Hprime, K1,     Hprime);
//
//                    // get 3D rotation and translation, with given n
//                    constraintError = JavaCV.HnToRt(Hprime, n, R2, t2);
//                    //System.out.println(constraintError);
//                    Hprime.pool();
//                }
            } else if (K2 != null && invK1 != null) {
                if (R != null && t != null) {
                    // 3D plane motion, with given R and t
//                    if (n2 == null) {
//                        n2 = CvMat.create(3, 1);
//                    }
                    double[] src = referencePoints2; 
                    double[] dst = { projectiveParameters[0], referencePoints1[1],
                                     projectiveParameters[1], referencePoints1[3],
                                     projectiveParameters[2], referencePoints1[5] };
                    if (R2 == null) {
                        R2 = CvMat.create(3, 3);
                    }
                    if (t2 == null) {
                        t2 = CvMat.create(3, 1);
                    }
                    cvTranspose(R, R2);
                    cvGEMM(R2, t, -1, null, 0, t2, 0);
                    JavaCV.getPerspectiveTransform(src, dst, invK2, K1, R2, t2, H);
//cvConvertScale(H, H, 1/H.get(8), 0);
//System.out.println(H);

//                    n2.put(projectiveParameters);
//                    // H = R-t*n^T
//                    cvGEMM(t, n2, -1,  R, 1,  H, CV_GEMM_B_T);
                } else {
                    // 3D rotation and translation, with given n
                    if (n != null) {
                        n2 = n; // take n from transformer
                    } else {
                        if (n2 == null) {
                            n2 = CvMat.create(3, 1);
                        }
                        n2.put(0, projectiveParameters, 8, 3); // take n from parameters
                    }

                    // put rotation angle and translation in matrices
                    if (R2 == null) {
                        R2 = CvMat.create(3, 3);
                    }
                    if (t2 == null) {
                        t2 = CvMat.create(3, 1);
                    }
                    t2.put(0, projectiveParameters, 0, 3);
                    cvRodrigues2(t2, R2, null);
                    t2.put(0, projectiveParameters, 3, 3);

                    // H = R-tn^T
                    cvGEMM(t2, n2, -1,  R2, 1,  H, CV_GEMM_B_T);
                }
//                // H = K2 * H * K1^-1
//                cvMatMul(K2,    H, H);
//                cvMatMul(H, invK1, H);
            }

            setUpdateNeeded(false);
        }

//        public void project() {
//            CvMat t2 = getT(), n2 = getN(), R2 = getR();
//            cvSetIdentity(H);
//            cvGEMM(t2, n2, -1,  H, 1,  H, CV_GEMM_B_T);
//            cvMatMul(R2,    H,  H);
//            cvMatMul(K2,    H,  H);
//            cvMatMul(H, invK1,  H);
//
//            CvMat pts = CvMat.take(4, 1, CV_64F, 2);
//            pts.put(referencePoints);
//            cvPerspectiveTransform(pts, pts, H);
//            pts.get(projectiveParameters);
//            pts.pool();
//        }

        public boolean preoptimize() {
            return false;
        }
        public double[] getSubspace() {
            return null;
        }
        public void setSubspace(double ... p) {
        }

        @Override public Parameters clone() {
            Parameters p = new Parameters();
            p.set(this);
            return p;
        }

        @Override public String toString() {
            String s = "[";
            double[] p = get();
            for (int i = 0; i < p.length; i++) {
                s += (float)p[i];
                if (i < p.length-1) {
                    s+= ", ";
                }
            }
            s += "]";
            return s;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy