2012-02-12 112 views
8

我正在使用Android手機作爲主處理器和相機來檢測移動的機器人項目。我得到了Android binary package from OpenCV,並得到它正確安裝。我可以使用OpenCV本機攝像頭捕捉圖像並將它們顯示在屏幕上。不過,我在使用背景減法類時遇到了問題。我可以在構造函數中創建一個新的BackgroundSubtractorMOG對象,但是當我嘗試運行下面的代碼時,它強制退出,從本機代碼中收到錯誤「BackgroundSubtractorMOG中僅支持1通道和3通道8位圖像」。我嘗試將Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA更改爲Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGB,然後它不強制退出,但我得到的只是一個黑屏。我非常確定bmp對於FRAME_RGB仍然是空的,因爲屏幕保持黑屏,並且我在位圖之後繪製的fps計數器(從下面的代碼中移除以清楚起見並作爲故障排除步驟)不顯示。OpenCV Android背景減去

我看了一下這個函數的OpenCV C++代碼(line 388 here),並且如果圖像類型不是CV_8UC1或CV_8UC3,就會發生圖像類型錯誤,所以我嘗試使用java CvType.CV_8UC3代替Highgui。 capture.retrieve()中的CV_CAP_ANDROID_COLOR_FRAME_RGBA,但強制關閉,並且出現「輸出幀格式不受支持」錯誤。

我猜我剛剛得到了一個類型轉換的問題,但我無法弄清楚我的生活在哪裏OpenCV的Android特定的圖像類型適合他們的常規圖像類型的記錄。任何幫助,將不勝感激。

的變量:

private SurfaceHolder mHolder; 
private VideoCapture mCamera; 
private Mat mRgba; 
private Mat mFGMask; 
private BackgroundSubtractorMOG mBGSub; 

我SurfaceView的run()函數:

public void run() {  
    Bitmap bmp = null; 

    synchronized (this) { 
     if (mCamera == null) 
      break; 

     if (!mCamera.grab()) { 
      Log.e(TAG, "mCamera.grab() failed"); 
      break; 
     } 

     processFrame(mCamera); 
     bmp = Bitmap.createBitmap(mFGMask.cols(), mFGMask.rows(), Bitmap.Config.ARGB_8888); 
     Utils.matToBitmap(mFGMask, bmp); 
    } 

    if (bmp != null) { 
     Canvas canvas = mHolder.lockCanvas(); 
     if (canvas != null) { 
      canvas.drawBitmap(bmp, (canvas.getWidth() - bmp.getWidth())/2, (canvas.getHeight() - bmp.getHeight())/2, null); 
      mHolder.unlockCanvasAndPost(canvas); 
     } 
     bmp.recycle(); 
    } 
} 

中的run()引用的processFrame()函數:

protected void processFrame(VideoCapture capture) { 
    capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA); 
    mBGSub.apply(mRgba, mFGMask); 
} 

編輯:

該結束了工作的解決方案:

protected void processFrame(VideoCapture capture) { 
    capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGB); 
    //GREY_FRAME also works and exhibits better performance 
    //capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_GREY_FRAME); 
    mBGSub.apply(mRgba, mFGMask, 0.1); 
    Imgproc.cvtColor(mFGMask, mRgba, Imgproc.COLOR_GRAY2BGRA, 4); 
} 

回答

3

您是否嘗試過使用cvtColorCV_RGB2RGBACV_RGBA2RGB。所以,也許嘗試轉換幀RGBA到RGB,然後做背景減法。事情是這樣的:

protected void processFrame(VideoCapture capture) { 
    capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA); 
    Mat rgb; 
    Imgproc.cvtColor(mRgba, rgb, Imgproc.COLOR_RGBA2RGB); 
    mBGSub.apply(rgb, mFGMask); 
} 

編輯:你可以看看OpenCV的單元測試BackgroundSubtractorMOG位於here。但是,主測試案例中的測試有fail("Not yet implemented");

我不確定這是否意味着測試沒有完成,或者對BackgroundSubtractorMOG的支持沒有實現。你可以嘗試運行這個單元測試中包含的代碼,看它是否真的有效。

此外,C++示例segment_objects.cpp作爲使用示例可能會有所幫助。

希望有幫助! :)

+0

這讓我更接近。 java包裝版本的確切語法是:'Imgproc.cvtColor(mRgba,rgb,Imgproc.COLOR_RGBA2RGB);'用於第一次轉換,第二次轉換不需要(我對原始圖像沒有做任何處理在減法之後)。現在,我得到一個黑屏(沒有強制關閉)。如果我將位圖格式更改爲Bitmap.Config.RGB_565,我得到我的FPS計數器,所以我知道它正在運行,但它仍然是黑屏。儘管如此,謝謝你讓我走得更遠。 – RedPeasant 2012-02-12 06:49:28

+0

@RedPeasant感謝您提供正確語法的信息。我已經更新了我的答案,以包括這一點。相機是否移動並且屏幕仍然是黑色的? – mevatron 2012-02-13 17:48:52

+0

@RedPeasant我已經更新了我的答案,以包含更多關於'BackgroundSubtractorMOG'的信息。 – mevatron 2012-02-13 17:55:23

1

謝謝你們這麼多!對於來到這個頁面的未來觀衆,您可能需要調整這些知識才能使事情順利進行。在SDK v2.4.4中,我將其應用於onCameraFrame方法。回想一下,該方法需要從相機的輸入框。您使用輸入並返回要在Android設備的屏幕上顯示的幀。這裏有一個例子:

//Assume appropriate imports  
private BackgroundSubtractorMOG sub = new BackgroundSubtractorMOG(3, 4, 0.8); 
private Mat mGray = new Mat(); 
private Mat mRgb = new Mat(); 
private Mat mFGMask = new Mat(); 

public Mat onCameraFrame(CvCameraViewFrame inputFrame) { 
    mGray = inputFrame.gray(); //I chose the gray frame because it should require less resources to process 
    Imgproc.cvtColor(mGray, mRgb, Imgproc.COLOR_GRAY2RGB); //the apply function will throw the above error if you don't feed it an RGB image 
    sub.apply(mRgb, mFGMask, learningRate); //apply() exports a gray image by definition 

    return mFGMask; 
} 

要在我的有關散發出來的應用(灰度圖像點獲得),如果你想做一個RGBA版本,您可能需要使用一個cvtcolor通話結束後申請( ):

private Mat mRgba = new Mat(); 

public Mat onCameraFrame(CvCameraViewFrame inputFrame) { 
    mRgba = inputFrame.rgba(); 
    Imgproc.cvtColor(mRgba, mRgb, Imgproc.COLOR_RGBA2RGB); //the apply function will throw the above error if you don't feed it an RGB image 
    sub.apply(mRgb, mFGMask, learningRate); //apply() exports a gray image by definition 
    Imgproc.cvtColor(mFGMask, mRgba, Imgproc.COLOR_GRAY2RGBA); 

    return mRgba; 
} 
+0

我不確定如何選擇BackgroundSubtractorMOG構造函數的值。我在另一個線程上看到了這些。確保使用這些值來更好地適應您的應用程序。 – austin 2013-03-05 07:25:47

0

而且你需要初始化最新的OpenCV:

私人BackgroundSubtractorMOG2分= Video.createBackgroundSubtractorMOG2();