2012-02-12 21 views
8

Tôi đang làm việc trên một dự án robot bằng cách sử dụng điện thoại Android làm bộ xử lý chính và máy ảnh để phát hiện chuyển động. Tôi đã nhận được Android binary package from OpenCV và cài đặt chính xác. Tôi có thể chụp ảnh bằng camera gốc OpenCV và hiển thị chúng trên màn hình. Tuy nhiên, tôi đang gặp sự cố khi sử dụng lớp trừ nền. Tôi có thể tạo đối tượng BackgroundSubtractorMOG mới trong hàm dựng, nhưng khi tôi cố gắng chạy mã bên dưới, nó buộc các lỗi tôi nhận được lỗi "Hình ảnh 8-bit chỉ 1 và 3-bit được hỗ trợ trong BackgroundSubtractorMOG" từ mã gốc. Tôi đã cố gắng thay đổi Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA thành Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGB, và sau đó nó không buộc bỏ thuốc lá, nhưng tất cả những gì tôi nhận được là một màn hình màu đen. Tôi khá chắc chắn bmp vẫn còn null với FRAME_RGB, bởi vì màn hình vẫn đen, và fps truy cập tôi đã vẽ ngay sau khi bitmap (loại bỏ từ mã được đăng dưới đây cho rõ ràng và như một bước xử lý sự cố) không hiển thị.OpenCV Android Background Subtraction

Tôi đã xem mã OpenCV C++ cho hàm này (line 388 here) và lỗi loại hình ảnh xảy ra nếu loại hình ảnh không phải là CV_8UC1 hoặc CV_8UC3, vì vậy tôi đã thử sử dụng java CvType.CV_8UC3 thay vì Highgui. CV_CAP_ANDROID_COLOR_FRAME_RGBA trong capture.retrieve(), nhưng nó buộc đóng và tôi nhận được một lỗi "Định dạng khung đầu ra không được hỗ trợ".

Tôi đoán tôi vừa gặp vấn đề về chuyển đổi loại, nhưng tôi không thể tìm ra cuộc sống của mình ở nơi các loại hình ảnh dành riêng cho Android của OpenCV phù hợp với các loại hình ảnh thông thường được ghi lại. Bất kỳ trợ giúp sẽ được đánh giá cao.

Các biến:

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

My SurfaceView của run() chức năng:

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

Các processFrame() chức năng tham chiếu trong run():

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

Edit:

Các giải pháp mà kết thúc làm việc:

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

Trả lời

3

Bạn đã cố gắng sử dụng cvtColor với CV_RGB2RGBACV_RGBA2RGB. Vì vậy, có thể thử chuyển đổi khung RGBA thành RGB, sau đó thực hiện phép trừ nền. Một cái gì đó như thế này:

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

EDIT: Bạn có thể kiểm tra OpenCV đơn vị xét nghiệm cho BackgroundSubtractorMOG nằm here. Tuy nhiên, thử nghiệm có fail("Not yet implemented"); trong trường hợp thử nghiệm chính.

Tôi không chắc liệu điều đó có nghĩa là thử nghiệm chưa hoàn thành hay không hỗ trợ cho BackgroundSubtractorMOG. Bạn có thể thử chạy mã chứa trong bài kiểm tra đơn vị này để xem nó có thực sự hoạt động không.

Ngoài ra, mẫu C++ segment_objects.cpp có thể hữu ích như ví dụ sử dụng.

Hy vọng điều đó sẽ hữu ích! :)

+0

Điều này khiến tôi gần gũi hơn. Cú pháp chính xác cho phiên bản được gói java là: 'Imgproc.cvtColor (mRgba, rgb, Imgproc.COLOR_RGBA2RGB);' cho lần chuyển đổi đầu tiên và cú pháp thứ hai là không cần thiết (tôi không làm gì với hình ảnh thô sau khi trừ). Bây giờ, tôi nhận được một màn hình màu đen (không có lực lượng gần). Nếu tôi thay đổi định dạng bitmap thành Bitmap.Config.RGB_565, tôi nhận được bộ đếm FPS của mình, vì vậy tôi biết nó đang chạy, nhưng nó vẫn là một màn hình màu đen. Cảm ơn vì đã giúp tôi tiến xa hơn một chút. – RedPeasant

+0

@RedPeasant Cảm ơn thông tin về cú pháp chính xác. Tôi đã cập nhật câu trả lời của tôi để bao gồm điều đó. Máy ảnh có chuyển động và màn hình vẫn đen? – mevatron

+0

@RedPeasant Tôi đã cập nhật câu trả lời của mình để bao gồm thêm thông tin về 'BackgroundSubtractorMOG'. – mevatron

1

Cảm ơn các bạn rất nhiều! Và đối với những người xem trong tương lai đến trang này, bạn có thể phải tinh chỉnh kiến ​​thức này để làm cho mọi thứ hoạt động. Trong SDK v2.4.4, tôi đã áp dụng điều này trong phương thức onCameraFrame. Nhớ lại rằng phương thức lấy trong khung đầu vào từ máy ảnh.Bạn sử dụng đầu vào và trả lại khung được hiển thị trên màn hình thiết bị Android của bạn. Dưới đây là một ví dụ:

//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; 
} 

Để có thể đi qua quan điểm của tôi về hình ảnh màu xám mà đến ra khỏi apply(), nếu bạn muốn làm một phiên bản RGBA, bạn có thể phải sử dụng một cvtcolor sau khi cuộc gọi áp dụng ():

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

Tôi không chắc chắn về cách chọn giá trị cho hàm tạo BackgroundSubtractorMOG. Tôi thấy những người trên một sợi khác. Hãy chắc chắn để chơi với các giá trị để phù hợp hơn với ứng dụng của bạn. – austin

0

Ngoài ra với OpenCV mới nhất bạn cần phải khởi tạo với:

BackgroundSubtractorMOG2 tin Sub = Video.createBackgroundSubtractorMOG2();