簡體   English   中英

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

[英]How to make white part of the image transparent by using Android opencv

我無法鏈接超過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;
}

謝謝你的善意答復。

我嘗試了但是它是相同的實驗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;
}

您的代碼中存在幾個問題。
我猜兩個案子都出錯了,但第二個案例很幸運,​​假裝成功。
第二種情況似乎工作正常的原因是字體大多是黑色的。
仔細觀察心臟(紅色)圖像,你會發現第二個案例也失敗了。
(你可能不幸運,如果兩種情況都失敗了你可以立即注意到問題:))

1.你正在使用tmp(灰色)和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);


2.顏色類型令人困惑
使用CV_8UC4初始化src Mat和tmp Mat,並使用轉換代碼將src轉換為tmp:COLOR_BGR2GRAY。
即使實際顏色類型與轉換代碼不匹配,OpenCV也會轉換矩陣,因此您必須同步它們才能理解。

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


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);



ADDED: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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM