【问题标题】:NDK Bitmap manipulation using OpenCv blue color is orange?使用 OpenCv 处理 NDK 位图 蓝色是橙色吗?
【发布时间】:2012-05-23 00:16:05
【问题描述】:

我正在测试使用 OpenCv 在 JNI 层上操作位图像素的性能。

两种选择:
1. 传递整数数组,操作像素并将像素写回位图。 [41 毫秒]
2.传递整个Bitmap。 [35 毫秒]

我注意到传递 Bitmap 比传递像素数组并将数组分配给 Bitmap 快大约 5 毫秒。

问题在于,使用选项 2,我失去了蓝色,而用橙色代替了我期望的蓝色。图像是 ARGB 并且似乎已更改为 RGBA?可能是什么问题?

方法 1:
Java

Bitmap out = Bitmap.createBitmap(width, height, Config.ARGB_8888);

int[] rgba = new int[width*height];

mSmasher.loadImage(imagePath, rgba, 0);

out.setPixels(rgba, 0, width, 0, 0, width, height);

JNI

JNIEXPORT void JNICALL Java_com_vblast_smasher_Smasher_loadImage
    (JNIEnv *pEnv, jobject obj, jstring jFilePath, jintArray jbgra, jint options)
{
    jint*  _bgra = pEnv->GetIntArrayElements(jbgra, 0);
    const char *filePath = pEnv->GetStringUTFChars(jFilePath, 0);

    if (NULL != filePath)
    {
        // init our output image
        Mat bgra(outputHeight, outputWidth, CV_8UC4, (unsigned char *)_bgra);

                // bgra image manipulations
    }

    pEnv->ReleaseIntArrayElements(jbgra, _bgra, 0);
    pEnv->ReleaseStringUTFChars(jFilePath, filePath);
}

方法二:

JNIEXPORT void JNICALL Java_com_vblast_smasher_Smasher_getLayersBitmap
    (JNIEnv *pEnv, jobject obj, jobject bitmap)
{
    int ret;
    AndroidBitmapInfo  info;
    void*              pixels = 0;

    if ((ret = AndroidBitmap_getInfo(pEnv, bitmap, &info)) < 0) {
        LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
        return;
    }

    if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888 )
    {
        LOGE("Bitmap format is not RGBA_8888!");
        return;
    }

    if ((ret = AndroidBitmap_lockPixels(pEnv, bitmap, &pixels)) < 0) {
        LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    }

    // init our output image
    Mat mbgra(info.height, info.width, CV_8UC4, pixels);

    mLayers[0].copyTo(mbgra);

    AndroidBitmap_unlockPixels(pEnv, bitmap);
}

解决方案 05/23:
问题在于,当使用整数数组并将其传递给 JNI 时,字节顺序从 ARGB (java) 更改为 BGRA(native)。这对于处理像素很好。但是,在锁定像素时传递实际的位图对象,字节顺序没有改变,因此需要在修改像素数据后进行更改。

cvtColor(mbgra, mbgra, COLOR_BGR2RGBA, 4); 

【问题讨论】:

  • 我对你的速度测试很感兴趣。你能总结一下这两种方法吗,我不明白第一种是什么意思。
  • 添加了更多细节...希望有意义:)

标签: android opencv android-ndk


【解决方案1】:

Opencv 顺序是 BGR 而不是 RGB。我猜 A 是在正确的位置(或者你会看到半透明的图像),但是蓝色和红色会互换。

【讨论】:

  • 我记得在 clrConvert (sp?) 中有一个 BGR2RGB。还有mixchannels(再次,sp?现在离我的opencv2refman.pdf很远)。
  • 啊!这是解决方案。 cvtColor(mbgra, mbgra, COLOR_BGR2RGBA, 4);
  • 为您提供答案,因为您正在寻找解决方案的目标。另外,它帮助我知道有参考手册之类的东西! :)
  • 我怀疑你已经失去了 5ms 的时间,但不得不这样做。我想不出办法避免交换。
【解决方案2】:

在 JNI 中颜色值返回为 ARGB,而在 JAVA 中返回为 RGBA 试试这个

alpha = (int) ((color & 0xFF000000) >> 24);
    blue = (int) ((color & 0xFF0000) >> 16);
    green = (int)((color & 0x00FF00) >> 8);
    red = (int) (color & 0x0000FF);
    blue = blue * alpha / 255;
    green = green * alpha / 255;
    red = red * alpha / 255;

    int tmp = 0;
    tmp = red;
    red = blue;
    blue = tmp;

    color =  ((alpha<< 24) & 0xFF000000) | ((blue<< 16) & 0xFF0000) |
                  ((green << 8) & 0x00FF00) |
                  (red & 0x0000FF);

【讨论】:

    猜你喜欢
    • 2014-02-23
    • 1970-01-01
    • 2012-04-20
    • 1970-01-01
    • 2014-03-07
    • 2018-09-04
    • 1970-01-01
    • 2020-05-17
    相关资源
    最近更新 更多