2015-06-16 152 views
15

最近我得到了一個項目,我必須從給定的圖像中提取臉部(臉部+頭髮)。在opencv-java中優化GrabCut的性能

我正在通過以下方式解決此問題。

  1. 我從提供的圖像中提取人臉位置。 [我得到一個矩形]
  2. 我提取該矩形並將其置於相同尺寸的另一圖像作爲輸入圖像。[face_image]
  3. 我上步驟的face_image施加grabCut算法2.

當face_image包含平滑背景則算法grabCut它工作良好,但是當face_image的背景是複雜的,則算法grabCut提取處理後的圖像中的背景的某些部分過多。

這是我得到的結果的快照。

results of each step

這裏是我的grabCut代碼:

public void extractFace(Mat image, String fileNameWithCompletePath, 
         int xOne, int xTwo, int yOne, int yTwo) throws CvException { 

    System.loadLibrary(Core.NATIVE_LIBRARY_NAME); 

    Rect rectangle = new Rect(xOne, yOne, xTwo, yTwo); 
    Mat result = new Mat(); 
    Mat bgdModel = new Mat(); 
    Mat fgdModel = new Mat(); 
    Mat source = new Mat(1, 1, CvType.CV_8U, new Scalar(3)); 
    Imgproc.grabCut(image, result, rectangle, bgdModel, fgdModel, 8, Imgproc.GC_INIT_WITH_RECT); 
    Core.compare(result, source, result, Core.CMP_EQ); 
    Mat foreground = new Mat(image.size(), CvType.CV_8UC3, new Scalar(255, 255, 255)); 
    image.copyTo(foreground, result); 
    Imgcodecs.imwrite(fileNameWithCompletePath, foreground); 
} 

我怎樣才能提高grabCut算法的性能,所以它會檢測從給定的圖像只有臉和頭髮?

回答

8

你應該可以通過「幫助」grabCut瞭解一些關於前景和背景的知識。有一個python tutorial,它顯示瞭如何通過選擇前景和背景來手動完成此操作。

要做到這一點自動,你需要找到編程方式來檢測前景和背景。前景主要由頭髮和皮膚組成,因此您需要檢測它們。

皮膚 - 有several紙和blogs如何做到這一點。其中一些是pretty simplethis OpenCV tutorial也可能有所幫助。我找到了簡單的色調/飽和度,讓我覺得很遠。

毛髮 - 這is trickier但是definitely仍然doable。如果事實證明工作太多,你可能會頭髮和皮膚和背景。

背景 - 您應該可以使用range()在圖像中查找紫色,綠色和藍色的東西。你肯定知道這些東西不是皮膚或頭髮,因此是背景的一部分。

使用閾值創建最有可能是皮膚,頭髮和背景的區域的蒙版。然後,您可以使用它們作爲bgdModelfgdModel(或皮膚和頭髮面罩)而不是Mat()

對不起,這是如此高級別。我希望它有幫助!

+0

我已經嘗試了很多這些東西,這些東西並不按照我的期望工作..... –

+0

如果你可以更詳細地描述你嘗試過的東西以及它如何不起作用並將它添加到你的問題,也許我可以多一點幫助。 –

+0

我有不同類型的圖像,對於一些圖像的背景是非常相似的頭髮,它是不可能的程序來區分它們,也提到的東西不適用於所有的情況.... –

0

我會建議「玩」與矩形座標(int xOne, int xTwo, int yOne, int yTwo)。使用你的代碼和這些座標1,400,30,400,我可以避開背景。 (我試圖張貼我成功裁剪的圖像,但我至少需要10個聲望才能這樣做)

+1

這不提供問題的答案。要批評或要求作者澄清,在他們的帖子下留下評論 - 你總是可以評論你自己的帖子,一旦你有足夠的[聲譽](http://stackoverflow.com/help/whats-reputation),你會能夠[評論任何帖子](http://stackoverflow.com/help/privileges/comment)。 – Ram

+0

嗨拉姆,我很抱歉,如果這不是正確的地方張貼。 問:我如何提高grabCut算法的性能,以便它只會檢測給定圖像中的臉部和頭髮? 我的回答:越靠近臉部,結果越好。 – sp1r0s

+1

我在審閱您的文章,並選擇了要顯示的通用系統消息。它基本上是說這更像是一個有用的評論,而不是一個答案,因爲它不夠詳盡,無法成爲答案,並要求您將其作爲評論發佈。我知道你不能將它作爲評論發佈,因爲你沒有這個聲望。請回答一些你知道的問題來收集聲譽,然後嘗試評論或使用例子和圖像作爲你的答案更詳細的鏈接,我將鏈接轉換爲圖像,爲你添加它們。 – Ram

-4

可以對任何Java例程執行的最佳優化是轉換爲本地語言。

2

另一種方法,因爲你已經檢測到臉部,只是簡單地選擇一個更好的初始化GrabCut的初始蒙版 - 例如,通過使用橢圓形而不是矩形。

  1. 檢測臉部矩形(因爲你已經這樣做)
  2. 創建遮罩:

    一)創建一個同樣大小的新的黑色圖像作爲輸入圖像

    B)繪製與面部矩形具有相同高度,寬度,頂部和左側位置的白色橢圓形

  3. 使用GC_INIT_WITH_MASK而不是GC_INIT_WITH_RECT調用GrabCut:

    Imgproc.grabCut(image, mask, rectangle, bgdModel, fgdModel, 8, Imgproc.GC_INIT_WITH_MASK); 
    

這將初始化前景具有更好的模型,因爲面是更橢圓形比矩形形狀的,所以它應該包括以下開始與背景。

+0

我已經使用它,這不會產生期望的結果.... –