本文介绍了如何使用Android opencv使图像的白色部分透明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法链接超过2的网址,所以我将我的图片发布到此博客。
请在这里查看我的问题。

I can't link url more than 2 so I post my pictures to this blog.please see my problems here.http://blog.naver.com/mail1001/220650041897

我想知道如何制作图像的白色部分,即使用Android opencv透明的白皮书。

I want to know how to make white part of the image, which is white paper with writing on it, transparent by using Android opencv.

我通过网址学习(我在博客上写过),这使得黑色背景变得透明,我认为Alpha Channel与它有关。

I have studied through url(I wrote it on blog) which makes the black background transparent, and I think "Alpha Channel" has something to do with it.

我认为通过制作我希望制作透明黑色而另一部分为白色的部分来制作Alpha通道,并将此Alpha通道合并到原始RGB通道。

I think it will work as I make Alpha Channel by making the part I want to make transparent black and the other part white, and merge this Alpha Channel to the original RGB Channel.

所以我进行了两次实验。

So I made two experiments.

1)我将纸张部分设为黑色,将书写部分设为白色以制作Alpha通道。并将其合并为RGB频道。

1) I made the papaer part black and the writing part white to make the Alpha Channel. And merged it to RGB Channel.

(请参阅博客。实验1的alpha频道图片)

(Please see blog. Experiment 1's alpha channel picture)

我以为写作应该是相同的,背景应该是透明的,但背景只能变成白色和透明。

I thought the writing should be the same and the background should be transparent, but the background only turned to white and little transparent.

(请参阅博客。实验1的结果图)

(Please see blog. Experiment 1's result picture)

2)这次,纸张部分为白色,书写部分为黑色。但是这次只有写作才变得透明。

2) This time, the paper part is white and the writing part is black. But this time only writing turned to transparent.

(请参阅博客。实验2的alpha通道图片和结果图片)

(Please see blog. Experiment 2's alpha channel picture and result picture)

在第二个实验中,我打算将透明变为透明但在第一个实验中它的工作方式不同。

In the second experiment, what I meant to make transparent turned transparent but it did not work the same in the first experiment.

我做错了哪一部分?有没有我错误理解的概念?

Which part am I doing wrong? Is there any concept I understand wrongly?

这是我测试的来源。

Bitmap test(Bitmap image) {
// convert image to matrix
Mat src = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC4);
Utils.bitmapToMat(image, src);

// init new matrices
Mat dst = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC4);
Mat tmp = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC4);
Mat alpha = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC4);

// convert image to grayscale
Imgproc.cvtColor(src, tmp, Imgproc.COLOR_BGR2GRAY);

// threshold the image to create alpha channel with complete transparency in black background region and zero transparency in foreground object region.
Imgproc.threshold(tmp, alpha, 100, 255, Imgproc.THRESH_BINARY_INV);
//Imgproc.threshold(tmp, alpha, 100, 255, Imgproc.THRESH_BINARY);

// split the original image into three single channel.
List<Mat> rgb = new ArrayList<Mat>(3);
Core.split(src, rgb);

// Create the final result by merging three single channel and alpha(BGRA order)
List<Mat> rgba = new ArrayList<Mat>(4);
rgba.add(rgb.get(0));
rgba.add(rgb.get(1));
rgba.add(rgb.get(2));
rgba.add(alpha);
Core.merge(rgba, dst);

// convert matrix to output bitmap
Bitmap output = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(dst, output);
//Utils.matToBitmap(alpha, output);
return output;
}






谢谢你的好意回答。


Thank you for your kindness answer.

我尝试了但是它与实验1的结果图相同。 T_T

I tried it but it was same Experiment 1's result picture. T_T

编辑代码

Bitmap makeBackgroundWhite(Bitmap image) {
    // convert image to matrix
    Mat src = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC4);
    Utils.bitmapToMat(image, src);

    // init new matrices
    Mat dst = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC4);
    Mat tmp = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8U);
    Mat alpha = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8U);

    // convert image to grayscale
    Imgproc.cvtColor(src, tmp, Imgproc.COLOR_BGR2GRAY);

    // threshold the image to create alpha channel with complete transparency in black background region and zero transparency in foreground object region.
    Imgproc.threshold(tmp, alpha, 100, 255, Imgproc.THRESH_BINARY_INV);

    // split the original image into three single channel.
    List<Mat> bgra = new ArrayList<Mat>(4);
    Core.split(src, bgra);

    // Create the final result by merging three single channel and alpha(BGRA order)
    bgra.remove(3);
    bgra.add(alpha);
    Core.merge(bgra, dst);

    // convert matrix to output bitmap
    Bitmap output = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
    Utils.matToBitmap(dst, output);

    return output;
}


推荐答案

你的问题有多处代码。

我猜两种情况都出错了但第二种情况只是幸运地假装成功。

第二种情况似乎工作正常的原因是字体大多是黑色的。

仔细观察心脏(红色)图像,你会发现第二个案例也失败了。

(如果两种情况都可能对你不幸失败你可以立即注意到问题:))

There are several problems in your code.
I guess both case went wrong but second case was just lucky to pretend success.
The reason why the second case seems to work fine is that the fonts are mostly black.
Have a close look at the heart(red) image, and you can find that second case has failed, too.
(It might not been lucky to you, if both case failed you could immediately notice the problem :))

1.你正在使用tmp(灰色)和alpha Mat与CV_8UC4。

灰色和alpha通道每个像素只需要1个字节,因此将它们更改为CV_8U。

1.You're using tmp(gray) and alpha Mat with CV_8UC4.
gray and alpha channel only needs 1 byte per pixel, so change them to CV_8U.

Mat tmp = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8U);
Mat alpha = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8U);



2.颜色类型令人困惑

src使用CV_8UC4初始化Mat和tmp Mat并使用转换代码将src转换为tmp:COLOR_BGR2GRAY。

即使实际颜色类型与转换代码不匹配,OpenCV也会转换矩阵,因此您必须同步它们才有意义。


2.Color types are confusing
src Mat and tmp Mat are initialized with CV_8UC4 and you're converting src to tmp with conversion code: COLOR_BGR2GRAY.
OpenCV converts the matrix even though actual color type doesn't match with conversion code, so you MUST sync them in order to make sense.

// suppose you've already changed the type of tmp to CV_8U
Imgproc.cvtColor(src, tmp, Imgproc.COLOR_BGRA2GRAY);



3.拆分和合并

你的src是4通道,你把它分成3个。

我不知道OpenCV在这种情况下是如何工作的,但我强烈建议你匹配频道。


3.Splitting and Merging
your src is 4-channel and you split it into 3.
I don't know how OpenCV works in such a situation, but I strongly suggest you to match channels.

ArrayList<Mat> bgra = new ArrayList<Mat>(4);
Core.split(src, bgra);
bgra.remove(3);
bgra.add(alpha);  // suppose your alpha channel is already CV_8U
Core.merge(bgra, dst);





增加:C ++版本源代码

希望这会有所帮助。



ADDED : C++ version Source Code
Hope this helps.

// 1. Loading
Mat src = imread("yourImagePath/yourOriginalImage.jpg");  // This code will automatically loads image to Mat with 3-channel(BGR) format

// 2. Grayscaling
Mat gray;
cvtColor(src, gray, CV_BGR2GRAY);   // This will convert BGR src to GRAY

// 3. Thresholding
Mat mask;
threshold(gray, mask, 100, 255, CV_THRES_BINARY); // Or use CV_THRES_BINARY_INV for inverting result

// 4. Splitting & adding Alpha
vector<Mat> channels;   // C++ version of ArrayList<Mat>
split(src, channels);   // Automatically splits channels and adds them to channels. The size of channels = 3
channels.push_back(mask);   // Adds mask(alpha) channel. The size of channels = 4

// 5. Merging
Mat dst;
merge(channels, dst);   // dst is created with 4-channel(BGRA).
// Note that OpenCV applies BGRA by default if your array size is 4,
// even if actual order is different. In this case this makes sense.

// 6. Saving
imwrite("yourImagePath/yourDstImage.png", dst);   // Used PNG format for preserving ALPHA channel

这篇关于如何使用Android opencv使图像的白色部分透明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 13:57
查看更多