图像显示VS2010中的结果,但未在Android中使用OpenCV显示输出

时间:2014-08-17 20:49:42

标签: opencv image-processing android-ndk java-native-interface computer-vision

我的代码在Visual Studio中使用OpenCV。但它没有在Android NDK应用程序中显示输出,并且没有显示错误

以下是我的代码。

void sow(Mat& img1, Mat& img2, Mat& out)
{
    Mat result(img1.size(), CV_32FC4);                           

    img2 = Mat(img1.size(), img1.type(), Scalar(186, 44, 28, 0));

    for (int i = 0; i < img1.size().height; ++i){
        for (int j = 0; j < img1.size().width; ++j){

            for (int c = 0; c<img1.channels(); c++){                // Iterate through colors

                //Formula 
                float target = (float)img1.at<uchar>(i, 4 * j + c) / 255.;
                float blend = (float)img2.at<uchar>(i, 4 * j + c) / 255.;
                if (blend > 0.5){
                    result.at<float>(i, 4 * j + c) = ((1 - (1 - target) * (1 - 2 * (blend - 0.5))));
                }
                else{
                    result.at<float>(i, 4 * j + c) = (target * (2 * blend));
                }
            }
        }
    }
    result.convertTo(out, CV_8UC4, 255);

}

它适用于带有8UC3图像的Visual Studio,但不适用于Android中的8UC4图像。除了imageview中的n输出外,没有错误。

当我更改公式时,同样适用于我的Android,但这个公式适用于Visual Studio。当我有相同的代码但

中的公式不同时,有些图像适合我
if (blend > 0.5)
{
    result.at<float>(i, 4 * j + c) = ((1 - (1 - target) * (1 - 2 * (blend - 0.5))));
}
else
{
    result.at<float>(i, 4 * j + c) = (target * (2 * blend));
}

他们正在显示输出。

我使用的方式相同:

void BL(Mat& img1, Mat& img2, Mat& out)
{
    img2 = Mat(img1.size(), img1.type(), Scalar(186, 44, 28, 0));
    max(img1, img2, out);
}

它显示输出但是当我在同一代码中使用max(img1, img2, out);时它没有显示输出。他们都在Visual Studio中工作,但在使用NDK的Android中工作。我测试了我的JNI并且它工作正常,Java代码也是正确的。

输入图片: enter image description here

结果后的结果图片:

enter image description here

1 个答案:

答案 0 :(得分:2)

第1部分

我认为您的问题是在此行中将alpha设置为0(透明):

img2 = Mat(img1.size(), img1.type(), Scalar(186, 44, 28, 0));

将其更改为

img2 = Mat(img1.size(), img1.type(), Scalar(186, 44, 28, 255));

由于唯一的区别是alpha通道,这是第一个看的地方。如果img1或img2的0都是0,那么你的结果将是完全透明的! 根据{{​​3}},建议的处理方法是 result.alpha = 1 - (1 - target.alpha) * (1 - blend.alpha)

试试这个:

 void sow(Mat& img1, Mat& img2, Mat& out)
{
    Mat result(img1.size(), CV_32FC4);                           

    img2 = Mat(img1.size(), img1.type(), Scalar(186, 44, 28, 255));

    for (int i = 0; i < img1.rows; ++i)
    {
        Vec4b* i1 = img1.ptr<Vec4b>(i);
        Vec4b* i2 = img2.ptr<Vec4b>(i);
        Vec4f* r  = result.ptr<Vec4f>(i);

        for (int j = 0; j < img1.cols; ++j)
        {
            Vec4b p1 = i1[j];
            Vec4b p2 = i2[j];
            Vec4f& pr = r[j];

            // Blend overlay color channels
            for (int c = 0; c < 3; ++c)
            { 
                //Formula 
                float target = (float) p1[c] / 255.0f;
                float blend = (float) p2[c] / 255.0f;
                if (blend > 0.5)
                {
                    pr[c] = 1 - (1 - target) * (1 - 2 * (blend - 0.5f));
                }
                else
                {
                    pr[c] = target * 2 * blend;
                }
            }
            // Alpha channel
            float target_alpha  = (float) p1[3] / 255.0f;
            float blend_alpha = (float) p2[3] / 255.0f;
            pr[3] = 1 - (1 - target_alpha) * (1 - blend_alpha);
        }
    }
    result.convertTo(out, CV_8UC4, 255);
}

使用输入图像,可以生成所需的结果:

enter image description here


此外,问题可能在于您的JNI代码,请检查调用sow()的代码是否正常工作,只需返回img1&amp; img2

void sow(Mat& img1, Mat& img2, Mat& out)
{
    img1.copyTo(out);
}

顺便说一句,除了img2之外,这些席子上的参考调用是多余的。 E.g。

void sow(Mat img1, Mat& img2, Mat out)
{
    img2 = Mat(img1.size(), img1.type(), Scalar(186, 44, 28, 255));
    img2.copyTo(out);
}

第2部分

的原因
void BL(Mat& img1, Mat& img2, Mat& out)
{
    img2 = Mat(img1.size(), img1.type(), Scalar(186, 44, 28, 0));
    min(img1, img2, out);
}

不显示任何内容out中的Alpha通道始终设置为0(完全透明)。在img2中将alpha更改为255,它应该可以工作:

void BL(Mat& img1, Mat& img2, Mat& out)
{
    img2 = Mat(img1.size(), img1.type(), Scalar(186, 44, 28, 255));
    min(img1, img2, out);
}