【问题标题】:cv::imencode required for outgoing byte[] in Android OpenCV?Android OpenCV 中传出字节 [] 需要 cv::imencode?
【发布时间】:2014-03-28 21:44:30
【问题描述】:

我一直在努力将 JNI 中的 CV:Mat 作为 Java byte[] 发送回,以便可以使用 BitmapFactory.decode() 成功解码。当我第一次从 Java 端引入我的 byte[] 数组(使用来自 Android 位图的数据构建)时,我能够在 C++ OpenCV 函数中成功使用它。我通过从传入的 byte[] 构建一个 Mat 并在 Mat 上调用 cv::imdecode 来做到这一点。

当我返回 Android 并尝试使用 BitmapFactory 将字节数组解码为 Android 位图时,问题就出现了。它返回 null 表示解码中存在问题。从 JNI 返回之前,我是否错误地执行了这些操作?由于必须在输入字节[]上使用 cv::imdecode,是否需要使用 cv::imencode?​​p>

任何和所有的帮助表示赞赏!下面的代码示例是我在 JNI 中从 Mat 中转换所需数据的地方。

注意我知道使用 Apache Android_Bitmap 函数,但使用字节数组是我目前正在处理的一项要求。

    //inData is a char* pointer that is set to a char* cast of the jbyte* pointer for the   
   // incoming Array.

    cv::Mat inMat = cv::Mat(rows, columns, CV_8UC4, inData);
    cv::Mat decodedMat = cv::imdecode(inMat, 1);

    //convertImage is a function that changes the color space from BGR to Gray and then Gray to  
    //RGB. 

    convertImage(decodedMat, decodedMat);

    cv::cvtColor(decodedMat, decodedMat, CV_RGB2RGBA);
    jbyteArray jDataArray = env->NewByteArray(pixelDataLength);
    env->SetByteArrayRegion(jDataArray,0,pixelDataLength,(jbyte*)decodedMat.data);
    env->SetObjectField(in,dataArray,jDataArray);
    env->ReleaseByteArrayElements(pixelData, bytePointerForIn, 0);

【问题讨论】:

    标签: android c++ opencv java-native-interface bitmapfactory


    【解决方案1】:

    BitmapFactory 期望提供给它的数据采用已知文件格式,但您传递的是原始像素。您可以通过调用 cv::imencode 使其工作,但也许从原始像素数据加载图像的更自然的解决方案是将原始 Java Bitmap 对象创建为可变的,然后调用 copyPixelsToBuffer 和 copyPixelsFromBuffer 方法来获取和设置该对象中的像素数据。

    【讨论】:

    • 我会尽快尝试并回复您。谢谢朋友的建议!如果我得到它的工作,你将获得答案。
    • 好消息和坏消息好友。我能够成功实现 copyPixelstoBuffer 和 copyPixelsFromBuffer 到可以发送字节 [] 的位置,将其重建为 Mat,然后将其发送回 Android。问题是当我需要使用 cv::imdecode 对从 byte[] 构建的 Mat 进行实际颜色空间操作时。详情在这里:answers.opencv.org/question/31751/…
    【解决方案2】:

    解决了!它是我使用 Bitmap.compress() 发送字节的原始版本,然后使用 copyPixelsFromBuffer 在返回的像素上的组合。感谢 Buddy 为我指明了正确的方向。

    Android: 
    
    //input was the original bitmap that was used to construct the byte[] array. I then used input.compress() in JPEG format to a Byte. Very important for it to be compressed in a format that will be recognized in cv::imdecode.
    
    ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
                    input.compress(CompressFormat.JPEG, 100, bos); 
                    data1.pixelData = bos.toByteArray();
    ...
    
        //Reconstruction after JNI call
        ByteBuffer buffer2 = ByteBuffer.wrap(data1.pixelData);
        Bitmap returnFromConvert = Bitmap.createBitmap(input.getWidth(),     
        input.getHeight(),Bitmap.Config.ARGB_8888);
        returnFromConvert.copyPixelsFromBuffer(buffer2);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-18
      • 1970-01-01
      • 2013-07-04
      • 1970-01-01
      • 2021-01-01
      • 2012-04-26
      • 1970-01-01
      • 2017-05-12
      相关资源
      最近更新 更多