【问题标题】:image shows result in VS2010 but not showing output in Android using OpenCV图像显示 VS2010 中的结果,但未显示使用 OpenCV 在 Android 中的输出
【发布时间】:2014-08-17 20:49:42
【问题描述】:

我的代码使用 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 代码也是正确的。

输入图像:

结果后的结果图像:

【问题讨论】:

  • 你是说结果不对?根据en.wikipedia.org/wiki/Blend_modes#Overlay“叠加结合了正片叠底和屏幕混合模式。[3] 基础层较亮的顶层部分变亮,基础层较暗的部分变暗。”使用您的代码,我希望蓝色组件变得更亮,红色和绿色变得更暗,这与您的结果图像一致。
  • 它实际上是软模式混合,我输入的图像是我需要的结果图像,这就是我得到的问题代码(更正后),但是你建议的答案代码由于快速工作并没有用我在问题中使用的相同公式给我相同的结果,我想要上面的结果图像(在你的答案的代码下方)与我在应用 softmode 后从 Photoshop 获得的相同图像
  • 简单地说,Resultant image after result : 是我需要的图像,Resultant image after result : 是我现在得到的图像,但我的代码运行缓慢,这就是为什么我更喜欢你建议的下面的代码,但你的代码你建议作为替代没有向我显示与Resultant image after result : 相同的结果

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


【解决方案1】:

第 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 的 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);
}

使用您的输入图像,这会生成您想要的结果:


另外,问题可能出在您的 JNI 代码上,请检查调用 sow() 的代码是否正常工作,只需返回 img1img2

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

【讨论】:

  • 同上,不显示输出,我用的是android ndk,jni
  • 我上面问题中的代码也运行缓慢,我也更新了我的问题
  • 你的代码很慢,因为使用了at()——它只适用于随机访问,不应该用于顺序扫描。使用行指针扫描图像,就像我的回答一样,您的程序将尽可能快。
  • 代码调用工作正常,我测试了很多次,当你提到的调用 sow 进行测试时它也可以工作,但它不适用于公式代码(主代码)
  • 它显示了我的代码结果和你的代码结果之间的巨大差异,尽管公式是相同的
猜你喜欢
  • 2020-05-11
  • 1970-01-01
  • 2019-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多