如何使用Android opencv使图像的白色部分透明

beg*_*ner 5 android opencv image

我无法链接超过2的网址,所以我将我的图片发布到此博客.请在这里看看我的问题. http://blog.naver.com/mail1001/220650041897

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

我通过url(我在博客上写过)研究了黑色背景透明,我认为"Alpha Channel"与它有关.

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

所以我做了两个实验.

1)我将papaer部分设为黑色,将写入部分设为白色以制作Alpha通道.并将其合并到RGB Channel.

(请参阅博客.实验1的alpha通道图片)

我认为写作应该是相同的,背景应该是透明的,但背景只会变成白色而且很透明.

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

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

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

在第二个实验中,我的意思是透明变透明,但在第一个实验中它不起作用.

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

这是我测试的来源.

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;
}
Run Code Online (Sandbox Code Playgroud)

谢谢你的善意答复.

我尝试了但是它是相同的实验1的结果图.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;
}
Run Code Online (Sandbox Code Playgroud)

Suh*_*Lee 4

您的代码中有几个问题。
我猜这两个案例都错了,但第二个案例只是幸运地假装成功。
第二种情况看起来工作正常的原因是字体大部分是黑色的。
仔细观察心形(红色)图像,你会发现第二种情况也失败了。
(对你来说可能不太幸运,如果两种情况都失败了,你可以立即注意到问题:))

1.您正在使用 tmp(gray) 和 alpha Mat 以及 CV_8UC4。
灰色和 Alpha 通道每个像素只需要 1 个字节,因此将它们更改为 CV_8U。

Mat tmp = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8U);
Mat alpha = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8U);
Run Code Online (Sandbox Code Playgroud)


2.颜色类型令人困惑
src Mat 和 tmp Mat 使用 CV_8UC4 初始化,并且您使用转换代码将 src 转换为 tmp:COLOR_BGR2GRAY。
即使实际颜色类型与转换代码不匹配,OpenCV 也会转换矩阵,因此您必须同步它们才能有意义。

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


3.分割和合并
你的src是4通道,你把它分成3个
。我不知道OpenCV在这种情况下如何工作,但我强烈建议你匹配通道。

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);
Run Code Online (Sandbox Code Playgroud)



添加:C++ 版本源代码
希望这有帮助。

// 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
Run Code Online (Sandbox Code Playgroud)