Android:使用OpenCV对齐图像

时间:2017-06-06 07:26:33

标签: android opencv

我正在尝试使用OpenCV对齐两个图像。我将这段代码基于我发现的C ++ / Python教程:http://www.learnopencv.com/image-alignment-ecc-in-opencv-c-python/

android中的findTransformECC()函数需要一个额外的inputMask参数。 C ++和Python函数没有这个。

我的代码:

import android.graphics.Bitmap;

import org.opencv.android.Utils;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.TermCriteria;
import org.opencv.imgproc.Imgproc;

import static org.opencv.core.CvType.CV_32F;
import static org.opencv.video.Video.MOTION_EUCLIDEAN;
import static org.opencv.video.Video.findTransformECC;

public class ImageProcessor {

    public static Bitmap alignImages(Bitmap A, Bitmap B){
        final int warp_mode = MOTION_EUCLIDEAN;
        Mat matA = new Mat(A.getHeight(),A.getWidth(), CvType.CV_8UC3);
        Mat matAgray = new Mat(A.getHeight(),A.getWidth(), CvType.CV_8U);
        Mat matB = new Mat(B.getHeight(),B.getWidth(), CvType.CV_8UC3);
        Mat matBgray = new Mat(B.getHeight(),B.getWidth(), CvType.CV_8U);
        Mat matBaligned = new Mat(A.getHeight(),A.getWidth(), CvType.CV_8UC3);
        Mat warpMatrix = Mat.eye(3,3,CV_32F);

        Utils.bitmapToMat(A,matA);
        Utils.bitmapToMat(B,matB);


        Imgproc.cvtColor(matA,matAgray, Imgproc.COLOR_BGR2GRAY);
        Imgproc.cvtColor(matB,matBgray,Imgproc.COLOR_BGR2GRAY);

        int numIter = 5000;
        double terminationEps = 1e-10;
        TermCriteria criteria = new TermCriteria(TermCriteria.COUNT+TermCriteria.EPS,numIter,terminationEps);

        findTransformECC(matAgray,matBgray,warpMatrix,warp_mode,criteria,matBgray);
        Imgproc.warpPerspective(matA,matBaligned,warpMatrix,matA.size(),Imgproc.INTER_LINEAR+ Imgproc.WARP_INVERSE_MAP);
        Bitmap alignedBMP = Bitmap.createBitmap(A.getWidth(),A.getHeight(),null);
        Utils.matToBitmap(matBaligned,alignedBMP);
        return alignedBMP;
    }

}

我收到以下错误

W/System.err: CvException [org.opencv.core.CvException: cv::Exception: /build/master_pack-android/opencv/modules/imgproc/src/imgwarp.cpp:5987: error: (-215) (M0.type() == CV_32F || M0.type() == CV_64F) && M0.rows == 2 && M0.cols == 3 in function void cv::warpAffine(cv::InputArray, cv::OutputArray, cv::InputArray, cv::Size, int, int, const Scalar&)
W/System.err: ]
W/System.err:     at org.opencv.video.Video.findTransformECC_0(Native Method)
W/System.err:     at org.opencv.video.Video.findTransformECC(Video.java:132)
W/System.err:     at com.test.imgptest.ImageProcessor.alignImages(ImageProcessor.java:42)
W/System.err:     at com.test.imgptest.MainActivity.onActivityResult(MainActivity.java:141)
W/System.err:     at android.app.Activity.dispatchActivityResult(Activity.java:6937)
W/System.err:     at android.app.ActivityThread.deliverResults(ActivityThread.java:4122)
W/System.err:     at android.app.ActivityThread.handleSendResult(ActivityThread.java:4169)
W/System.err:     at android.app.ActivityThread.-wrap20(ActivityThread.java)
W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1552)
W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
W/System.err:     at android.os.Looper.loop(Looper.java:154)
W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6186)
W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)

2 个答案:

答案 0 :(得分:2)

您正在输入完整的3x3单应矩阵warpMatrixfindTransformECC,但您选择的warp_modeMOTION_EUCLIDEAN

如果您想使用3x3单应性,则应将warp_mode设为MOTION_HOMOGRAPHY

如果你想进行欧几里德变换,你只需要从输入warpMatrix剪掉最后一行,因为2x3矩阵给出了欧几里德变换。根据{{​​3}},

  

MOTION_EUCLIDEAN将欧几里德(刚性)变换设置为运动模型;估计三个参数; warpMatrix是2x3

然后,由于您将使用2x3扭曲矩阵,因此请使用findTransformECC() documentation代替warpPerspective()来对齐图像。

答案 1 :(得分:0)

已接受答案中的完整功能:

public static Bitmap alignImagesHomography(Bitmap A, Bitmap B)
{
    final int warp_mode = MOTION_HOMOGRAPHY;
    Mat matA = new Mat(A.getHeight(), A.getWidth(), CvType.CV_8UC3);
    Mat matAgray = new Mat(A.getHeight(), A.getWidth(), CvType.CV_8U);
    Mat matB = new Mat(B.getHeight(), B.getWidth(), CvType.CV_8UC3);
    Mat matBgray = new Mat(B.getHeight(), B.getWidth(), CvType.CV_8U);
    Mat matBaligned = new Mat(A.getHeight(), A.getWidth(), CvType.CV_8UC3);
    Mat warpMatrix = Mat.eye(3, 3, CV_32F);
    Utils.bitmapToMat(A, matA);
    Utils.bitmapToMat(B, matB);
    Imgproc.cvtColor(matA, matAgray, Imgproc.COLOR_BGR2GRAY);
    Imgproc.cvtColor(matB, matBgray, Imgproc.COLOR_BGR2GRAY);
    int numIter = 5;
    double terminationEps = 1e-10;
    TermCriteria criteria = new TermCriteria(TermCriteria.COUNT + TermCriteria.EPS, numIter, terminationEps);
    findTransformECC(matAgray, matBgray, warpMatrix, warp_mode, criteria, matBgray);
    Imgproc.warpPerspective(matB, matBaligned, warpMatrix, matA.size(), Imgproc.INTER_LINEAR + Imgproc.WARP_INVERSE_MAP);
    Bitmap alignedBMP = Bitmap.createBitmap(A.getWidth(), A.getHeight(), Bitmap.Config.RGB_565);
    Utils.matToBitmap(matBaligned, alignedBMP);
    return alignedBMP;
}

public static Bitmap alignImagesEuclidean(Bitmap A, Bitmap B)
{
    final int warp_mode = MOTION_EUCLIDEAN;
    Mat matA = new Mat(A.getHeight(), A.getWidth(), CvType.CV_8UC3);
    Mat matAgray = new Mat(A.getHeight(), A.getWidth(), CvType.CV_8U);
    Mat matB = new Mat(B.getHeight(), B.getWidth(), CvType.CV_8UC3);
    Mat matBgray = new Mat(B.getHeight(), B.getWidth(), CvType.CV_8U);
    Mat matBaligned = new Mat(A.getHeight(), A.getWidth(), CvType.CV_8UC3);
    Mat warpMatrix = Mat.eye(2,3,CV_32F);
    Utils.bitmapToMat(A, matA);
    Utils.bitmapToMat(B, matB);
    Imgproc.cvtColor(matA, matAgray, Imgproc.COLOR_BGR2GRAY);
    Imgproc.cvtColor(matB, matBgray, Imgproc.COLOR_BGR2GRAY);
    int numIter = 5;
    double terminationEps = 1e-10;
    TermCriteria criteria = new TermCriteria(TermCriteria.COUNT + TermCriteria.EPS, numIter, terminationEps);
    findTransformECC(matAgray, matBgray, warpMatrix, warp_mode, criteria, matBgray);
    Imgproc.warpAffine(matB, matBaligned, warpMatrix, matA.size(), Imgproc.INTER_LINEAR + Imgproc.WARP_INVERSE_MAP);
    Bitmap alignedBMP = Bitmap.createBitmap(A.getWidth(), A.getHeight(), Bitmap.Config.RGB_565);
    Utils.matToBitmap(matBaligned, alignedBMP);
    return alignedBMP;
}

,这里是使用alignMTB的更快版本:

public static Bitmap AlignExposures(Mat[] image_list) {
    List<Mat> src = Arrays.asList(image_list);
    Bitmap output = Bitmap.createBitmap(bitmapWidth,bitmapHeight, Bitmap.Config.ARGB_8888);
    AlignMTB align = createAlignMTB(8, 4, false);
    align.process(src,src);
    for(int i = 1; i < src.size(); i++) {
        addWeighted(src.get(0),1-1/(i+1),src.get(i),1/(i+1),0,src.get(0));
    }
    Utils.matToBitmap(src.get(0),output);
    return output;
}