程序运行但不使用本机android显示结果

时间:2014-04-15 09:51:13

标签: java android eclipse android-ndk java-native-interface

这是我的jni文件native.cpp

    extern "C"
 Java_org_opencv_samples_NativeActivity_CvNativeActivity_CannyJNI(
        JNIEnv* env, jobject thiz,
        jint height, jint width, jintArray in, jintArray out)
{
    //get the data pointer.
    jint* _in = env->GetIntArrayElements(in, 0);
    jint* _out = env->GetIntArrayElements(out, 0);


    //Build the Mat structure for input data
    Mat mSrc(height, width, CV_8UC4, (unsigned char *)_in);
    //Build the Mat structure for output data
    Mat bgr(height, width, CV_8UC4, (unsigned char *)_out);

    //Convert Mat to IplImage
    IplImage mSrcImg = mSrc;
    IplImage mOutImg = bgr;

    //Create the gray image for input data.
    IplImage * mSrcGrayImg = cvCreateImage(cvGetSize(&mSrcImg), mSrcImg.depth, 1);
    IplImage * mOutGrayImg = cvCreateImage(cvGetSize(&mSrcImg), mSrcImg.depth, 1);

    IplImage *b,*g,*r;
    b = cvCreateImage( cvGetSize(mSrcGrayImg), 8, 1 );
    g = cvCreateImage( cvGetSize(mSrcGrayImg), 8, 1 );
    r = cvCreateImage( cvGetSize(mSrcGrayImg), 8, 1 ) ;

    cvSplit(&mSrcImg, b, g, r, 0 );
    cvEqualizeHist( b, b );
    cvEqualizeHist( g, g );
    cvEqualizeHist( r, r );
    cvMerge(b,g,r,0,&mOutImg);
    //release the pointer.
    env->ReleaseIntArrayElements(in, _in, 0);
    env->ReleaseIntArrayElements(out, _out, 0);
    return true;
}

当我添加这两行时,我的每个jni部分都适合我

cvCvtColor(mOutGrayImg, mSrcGrayImg, CV_BGR2YCrCb);
cvCvtColor(mSrcGrayImg, &mOutImg , CV_YCrCb2BGR);

从上面的代码中添加

cvMerge(b,g,r,0,mOutGrayImg);
cvCvtColor(mOutGrayImg, mSrcGrayImg, CV_BGR2YCrCb);
cvCvtColor(mSrcGrayImg, &mOutImg , CV_YCrCb2BGR);

它运行,和我的其他代码一样,任何人都可以告诉我Why and How吗?以及我如何摆脱这两行,只需cvMerge(b,g,r,0,mOutGrayImg);这些行发送输出图像以及如何为此代码设置C ++接口。

这是我的jave文件包含CvNativeActivity.java

public class CvNativeActivity extends Activity implements CvCameraViewListener2
{   
    public native boolean BrightnessJNI(int width, int height, int [] mPhotoIntArray, int [] mCannyOutArray);

    static 
    {
        System.loadLibrary("native_activity");
    }
    /** Called when the activity is first created. */ 
    ImageView imageview_1;
    ImageView imageview_2;
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
         imageview_1=(ImageView) findViewById(R.id.imageView1);
         imageview_2=(ImageView) findViewById(R.id.imageView2);

        InputStream is;
        is = this.getResources().openRawResource(R.drawable.foot);
        Bitmap bmInImg = BitmapFactory.decodeStream(is);

        int [] mPhotoIntArray;
        int [] mCannyOutArray;

        mPhotoIntArray = new int[bmInImg.getWidth() * bmInImg.getHeight()];
        // Copy pixel data from the Bitmap into the 'intArray' array
        bmInImg.getPixels(mPhotoIntArray, 0, bmInImg.getWidth(), 0, 0, bmInImg.getWidth(), bmInImg.getHeight());

        //create the Brightness result buffer
        mCannyOutArray = new int[bmInImg.getWidth() * bmInImg.getHeight()];

        //
        // Do Brightness
        //
        BrightnessJNI(bmInImg.getHeight(), bmInImg.getWidth(), mPhotoIntArray, mCannyOutArray);

        //
        // Convert the result to Bitmap
        //
        Bitmap bmOutImg = Bitmap.createBitmap(bmInImg.getWidth(), bmInImg.getHeight(), Config.ARGB_8888);  
        bmOutImg.setPixels(mCannyOutArray, 0, bmInImg.getWidth(), 0, 0, bmInImg.getWidth(), bmInImg.getHeight());


        imageview_2.setImageBitmap(bmOutImg);

        //
        // Save the result to file
        //
        String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
        String outFileName = extStorageDirectory + "/Brightness";

        OutputBitmapToFile(bmOutImg, outFileName);





    }

    void OutputBitmapToFile(Bitmap InBm, String Filename)
    {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        InBm.compress(Bitmap.CompressFormat.PNG, 100, bytes);

        File f = new File(Filename);
        try
        {
            f.createNewFile();
            //write the bytes in file
            FileOutputStream fo = new FileOutputStream(f);
            fo.write(bytes.toByteArray());
        } 
        catch (Exception e) 
        {
            e.printStackTrace();
        }           
    }
}

由于

1 个答案:

答案 0 :(得分:2)

好吧,我发现了这个问题。它没有显示图像,因为您已在alpha channel中将cvMerge设为0。位图是RGBA格式。并且alpha为0.因此完整的黑色图像。

这是C API实现代码。这很有效。

#include <jni.h>
#include <stdio.h>
#include "opencv2/core/core.hpp"
#include <opencv2/imgproc/imgproc_c.h>

using namespace std;
using namespace cv;

extern "C"
{
    JNIEXPORT jint JNICALL 
    Java_com_fenchtose_equalizehist_EqActivity_eqhist(
            JNIEnv* env, jobject,
            jint width, jint height, jintArray in, jintArray out)
    {
        jint* _in = env->GetIntArrayElements(in, 0);
        jint* _out = env->GetIntArrayElements(out, 0);

        Mat mSrc(height, width, CV_8UC4, (unsigned char*)_in);
        Mat bgra(height, width, CV_8UC4, (unsigned char*)_out);

        IplImage mSrcImg = mSrc;
        IplImage mOutImg = bgra;

        IplImage *b, *g, *r, *a;

        b = cvCreateImage(cvSize(width, height), mSrcImg.depth, 1);
        g = cvCreateImage(cvSize(width, height), mSrcImg.depth, 1);
        r = cvCreateImage(cvSize(width, height), mSrcImg.depth, 1);
        a = cvCreateImage(cvSize(width, height), mSrcImg.depth, 1);

        cvSplit(&mSrcImg, b, g, r, a);
        cvEqualizeHist(b, b);
        cvEqualizeHist(g, g);
        cvEqualizeHist(r, r);

        cvMerge(b, g, r, a, &mOutImg); // merge alpha layer too
        jint retVal;
        int ret = 1;
        retVal = jint(retVal);

        env->ReleaseIntArrayElements(in, _in, 0);
        env->ReleaseIntArrayElements(out, _out, 0);

        return retVal;


    }
}

老答案: 我复制了你的Java文件。做了一些小改动。 (在imageView1中显示原始图像,更改了本机函数调用)。

这是JNI文件。

#include <jni.h>
#include <stdio.h>
#include "opencv2/core/core.hpp"
#include <opencv2/imgproc/imgproc.hpp>
#include <vector>

using namespace std;
using namespace cv;

extern "C"
{
    JNIEXPORT jint JNICALL 
    Java_com_example_equalizehist_EqActivity_eqhist(
            JNIEnv* env, jobject,
            jint width, jint height, jintArray in, jintArray out)
    {
        jint* _in = env->GetIntArrayElements(in, 0);
        jint* _out = env->GetIntArrayElements(out, 0);

        Mat mSrc(height, width, CV_8UC4, (unsigned char*)_in);
        Mat bgra(height, width, CV_8UC4);

        vector<Mat> sChannels;
        split(mSrc, sChannels);

        for(int i=0; i<sChannels.size(); i++)
        {
            equalizeHist(sChannels[i], sChannels[i]);
        }

        merge(sChannels, bgra);

        for(int i=0; i<height; i++)
        {
            memcpy(&(_out[i*width]), &(bgra.data[i*bgra.step]), width*bgra.channels());
        }

        env->ReleaseIntArrayElements(in, _in, 0);
        env->ReleaseIntArrayElements(out, _out, 0);

        jint retVal;
        int ret = 1;
        retVal = jint(retVal);
        return retVal;
    }
}
  • Step1:将Pixel(int数组)传递给本机函数。
  • 第2步:使用输入像素创建Mat。
  • 步骤3:创建一个空向量以保存mSrc Mat。
  • 的每个频道
  • 步骤4:将mSrc Mat拆分为sChannels vector。
  • 步骤5:在每个通道上应用equalizeHist功能。循环遍历sChannels矢量。
  • 步骤6:合并bgra Mat。中的所有频道。
  • 步骤7:将bgra Mat的数据复制到像素数组。对于此用途memcpy。迭代bgra Mat的每一行并复制每个通道的数据。这是CV_8UC4 Mat。每个通道都有2个字节的数据。因此每个像素将包含8个字节的数据。
  • 步骤8:释放阵列。

以下是该应用的截图。

enter image description here

我已在GitHub上提出此代码。如果遇到任何问题,您可能需要检查它。

注意:如果您使用此代码,请确保正确声明本机功能。

如果您不想使用memcpy,可以直接分配

#include <jni.h>
#include <stdio.h>
#include "opencv2/core/core.hpp"
#include <opencv2/imgproc/imgproc.hpp>
#include <vector>

using namespace std;
using namespace cv;

extern "C"
{
    JNIEXPORT jint JNICALL 
    Java_com_example_equalizehist_EqActivity_eqhist(
            JNIEnv* env, jobject,
            jint width, jint height, jintArray in, jintArray out)
    {
        jint* _in = env->GetIntArrayElements(in, 0);
        jint* _out = env->GetIntArrayElements(out, 0);

        Mat mSrc(height, width, CV_8UC4, (unsigned char*)_in);
        Mat bgra(height, width, CV_8UC4, (unsigned char*)_out);

        vector<Mat> sChannels;
        split(mSrc, sChannels);

        for(int i=0; i<sChannels.size(); i++)
        {
            equalizeHist(sChannels[i], sChannels[i]);
        }

        merge(sChannels, bgra);
        env->ReleaseIntArrayElements(in, _in, 0);
        env->ReleaseIntArrayElements(out, _out, 0);

        jint retVal;
        int ret = 1;
        retVal = jint(retVal);
        return retVal;
    }
}

即使这样也能正常工作。