Android中的位图和OpenCV中的Mat

时间:2012-10-20 03:13:38

标签: java android c++ opencv bitmap

我在OpenCV C ++中有这段代码:

#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;

int main(){
    Mat src = imread("image.jpg");
    if (src.empty())
        return -1;
    pyrMeanShiftFiltering(src,src,10,20,1);
    imshow("src", src);
    waitKey(0);
    return 0;
}

这个来自OpenCV 2.4.2的Sample1View.java类作为名为“OpenCV Tutorial 1 - Add OpenCV”的示例:

import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.imgproc.Imgproc;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;

class Sample1View extends SampleViewBase {
    public static final int     VIEW_MODE_RGBA  = 0;
    public static final int     VIEW_MODE_GRAY  = 1;
    public static final int     VIEW_MODE_CANNY = 2;
    private Mat mYuv;
    private Mat mRgba;
    private Mat mGraySubmat;
    private Mat mIntermediateMat;
    private Bitmap mBitmap;
    private int mViewMode;

    public Sample1View(Context context) {
        super(context);
        mViewMode = VIEW_MODE_RGBA;
    }

    @Override
    protected void onPreviewStarted(int previewWidth, int previewHeight) {
        synchronized (this) {
            // initialize Mats before usage
            mYuv = new Mat(getFrameHeight() + getFrameHeight() / 2, getFrameWidth(), CvType.CV_8UC1);
            mGraySubmat = mYuv.submat(0, getFrameHeight(), 0, getFrameWidth());
            mRgba = new Mat();
            mIntermediateMat = new Mat();
            mBitmap = Bitmap.createBitmap(previewWidth, previewHeight, Bitmap.Config.ARGB_8888); 
        }
    }

    @Override
    protected void onPreviewStopped() {
        if(mBitmap != null) {
            mBitmap.recycle();
        }

        synchronized (this) {
            // Explicitly deallocate Mats
            if (mYuv != null)
                mYuv.release();
            if (mRgba != null)
                mRgba.release();
            if (mGraySubmat != null)
                mGraySubmat.release();
            if (mIntermediateMat != null)
                mIntermediateMat.release();
            mYuv = null;
            mRgba = null;
            mGraySubmat = null;
            mIntermediateMat = null;
        }
    }

    @Override
    protected Bitmap processFrame(byte[] data) {
        mYuv.put(0, 0, data);
        final int viewMode = mViewMode;

        switch (viewMode) {
        case VIEW_MODE_GRAY:
            Imgproc.cvtColor(mGraySubmat, mRgba, Imgproc.COLOR_GRAY2RGBA, 4);
            break;
        case VIEW_MODE_RGBA:
            Imgproc.cvtColor(mYuv, mRgba, Imgproc.COLOR_YUV420sp2RGB, 4);
            Core.putText(mRgba, "OpenCV + Android", new Point(10, 100), 3/* CV_FONT_HERSHEY_COMPLEX */, 2, new Scalar(255, 0, 0, 255), 3);
            break;
        case VIEW_MODE_CANNY:
            Imgproc.Canny(mGraySubmat, mIntermediateMat, 80, 100);
            Imgproc.cvtColor(mIntermediateMat, mRgba, Imgproc.COLOR_GRAY2BGRA, 4);
            break;
        }

        Bitmap bmp = mBitmap;

        try {
            Utils.matToBitmap(mRgba, bmp);
        } catch(Exception e) {
            Log.e("org.opencv.samples.tutorial1", "Utils.matToBitmap() throws an exception: " + e.getMessage());
            bmp.recycle();
            bmp = null;
        }
        return bmp;
    }

    public void setViewMode(int viewMode) {
        mViewMode = viewMode;
    }
}

现在我希望我的代码可以在Android上运行,所以我替换了这一行:

case VIEW_MODE_GRAY:
    Imgproc.cvtColor(mGraySubmat, mRgba, Imgproc.COLOR_GRAY2RGBA, 4);
    break;

到此:

case VIEW_MODE_GRAY:
    Imgproc.cvtColor(mGraySubmat, mRgba, Imgproc.COLOR_GRAY2RGBA, 4);
    Imgproc.pyrMeanShiftFiltering(mRgba,mRgba,10,20);
    break;

但我明白了:

10-20 11:08:45.929: I/Sample::Activity(12846): Menu Item selected Preview GRAY
10-20 11:08:46.049: W/dalvikvm(12846): threadid=9: thread exiting with uncaught exception (group=0x4013a560)
10-20 11:08:46.059: E/AndroidRuntime(12846): FATAL EXCEPTION: Thread-10
10-20 11:08:46.059: E/AndroidRuntime(12846): CvException [org.opencv.core.CvException: ..\..\modules\imgproc\src\segmentation.cpp:345: error: (-210) Only 8-bit, 3-channel images are supported in function void cvPyrMeanShiftFiltering(const CvArr*, CvArr*, double, double, int, CvTermCriteria)
10-20 11:08:46.059: E/AndroidRuntime(12846): ]
10-20 11:08:46.059: E/AndroidRuntime(12846):    at org.opencv.imgproc.Imgproc.pyrMeanShiftFiltering_1(Native Method)
10-20 11:08:46.059: E/AndroidRuntime(12846):    at org.opencv.imgproc.Imgproc.pyrMeanShiftFiltering(Imgproc.java:7247)
10-20 11:08:46.059: E/AndroidRuntime(12846):    at com.duckie.a.Sample1View.processFrame(Sample1View.java:80)
10-20 11:08:46.059: E/AndroidRuntime(12846):    at com.duckie.a.SampleViewBase.run(SampleViewBase.java:185)
10-20 11:08:46.059: E/AndroidRuntime(12846):    at java.lang.Thread.run(Thread.java:1019)

似乎有什么问题?如何让我的代码在Android中运行?而且,如何在没有延迟的情况下做到这一点?

1 个答案:

答案 0 :(得分:3)

似乎cvPyrMeanShiftFiltering期望一个3通道图像,你生成一个4通道图像:

Imgproc.cvtColor(mGraySubmat, mRgba, Imgproc.COLOR_GRAY2RGBA, 4);