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

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

我的代码使用 OpenCV 在 Visual Studio 中运行。但它没有在 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);

}

它适用于我在 Visual Studio 中使用 8UC3 图像,但不适用于 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 部分

我认为您的问题是在这一行中将 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 channel ,所以这是第一个要看的地方。如果 img1 或 img2 的 alpha 为 0,您的结果将是完全透明的! 根据 this question 的建议处理方式, 是 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 & img2:

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

顺便说一句,除了 img2,那些垫子上的引用调用是多余的。例如

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 channel 始终设置为 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);
}

关于opencv - 图像显示 VS2010 中的结果,但未显示使用 OpenCV 在 Android 中的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25353492/

相关文章:

opencv - 'W'上的字符分割失败

python - 估计图像的信噪比

multithreading - 如何在 NodeJS 中进行线程图像处理?

android - 从 native C/C++ 代码调用 JAVA 类成员

android - 无法在 Qt Creator 中构建 Android APK

android - Android.mk 中的预处理器宏被忽略,但在 Application.mk 中有效

iphone - 错误 : expected specifier-qualifier-list before 'cv'

ios - 保存高质量图像,进行实时处理——什么是最好的方法?

python - 相机拍摄+步进马达

algorithm - 类似 photoshop 的快速选择算法的开源实现?