2016-03-09 39 views
3

我不能鏈接URL超過2所以我張貼我的圖片這個博客使圖像透明的白色部分。 請在這裏看到我的問題。 http://blog.naver.com/mail1001/220650041897如何使用Android的OpenCV的

我想知道如何製作圖像的白色部分,這是白皮書寫在上面,使用Android opencv透明。

我已經通過網址(我寫在了博客),這使得黑色背景透明的研究,我認爲「Alpha通道」有事情做吧。

我認爲它會工作,我做Alpha通道通過使我要讓透明的黑色部分,另一部分白色,併合並該Alpha通道的原始RGB通道。

所以我做了兩個實驗。

1)我做了篾部分爲黑色和寫作部分的白色,使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

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

1.You're使用TMP(灰色)和阿爾法墊與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.顏色類型混淆
SRC墊和TMP墊與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); 


3.Splitting和合並
你的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); 



新增: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 
+0

謝謝你的好意的答案!我嘗試過但失敗了。 T_T 我在我的問題中寫了編輯代碼。 昨天我看了一些博客如何使用photoshop的alpha通道。有人說,當他們用alpha通道保存圖像時,背景變成白色不透明。有人說這是在用戶保存圖像* .tga格式時發生的。 所以我想,Android的位圖對象可以有類似的問題。你對這種方法有什麼看法? – beginner

+0

@beginner我不知道你是如何從位圖轉換爲Mat的,也許有一些格式轉換的問題。我認爲你刪除了RED頻道而不是ALPHA頻道。剛剛從Bitmap中解析出原始位圖後,是否檢查過原始位圖?嘗試bgra.remove(0); bgra.add(alpha,0); –

+0

@beginner此外,灰度轉換代碼不會更改。將Imgproc.COLOR_BGR2GRAY替換爲Imgproc.COLOR_BGRA2GRAY –