2013-02-19 29 views
6

Tôi đang sử dụng OpenCV để cố gắng thực hiện một số xử lý video trực tiếp. Vì quá trình xử lý khá nặng nên nó làm chậm đáng kể khung hình đầu ra, làm cho luồng trực tiếp bị biến dạng.Android Asynctask để xử lý các khung hình video trực tiếp

Tôi muốn giảm bớt một số quá trình xử lý thành AsyncTask. Tôi đã thử nó và nó thực sự làm cho video mượt mà hơn nhiều. Tuy nhiên, nó kết thúc việc bắt đầu một lượng lớn Công việc cùng một lúc, và sau đó họ sẽ dần dần bắt đầu trở lại với một số kết quả.

Có cách nào để làm chậm điều này xuống và chờ kết quả, bằng cách sử dụng các câu lệnh Đồng bộ hóa hoặc một số phương pháp khác không?

Trên mỗi khung máy ảnh, tôi bắt đầu một trong các tác vụ này. DoImgProcessing thực hiện xử lý dài và trả về một kết quả chuỗi.

private class LongOperation extends AsyncTask<Mat, Void, String> { 

    @Override 
    protected String doInBackground(Mat... params) { 
     Mat inputFrame = params[0]; 
     cropToCenter(inputFrame); 
     return doImgProcessing(inputFrame); 
    }  

    @Override 
    protected void onPostExecute(String result) { 
     Log.d(TAG, "on post execute: "+result); 

    } 

    @Override 
    protected void onPreExecute() { 
     Log.d(TAG, "on pre execute"); 
    } 
} 

public Mat onCameraFrame(Mat inputFrame) { 
    inputFrame.copyTo(mRgba);//this will be used for the live stream 
    LongOperation op = new LongOperation(); 
    op.execute(inputFrame); 
    return mRgba; 
} 
+0

Tôi muốn sử dụng một sợi đơn có ngăn chặn để đặt khung vào. – njzk2

+0

Tôi chưa bao giờ viết một trong số này, Id vui lòng chấp nhận câu trả lời của bạn nếu bạn có thể cung cấp mã mẫu dễ vỡ – Jameo

Trả lời

3

tôi sẽ làm một cái gì đó như thế:

// Example value for a timeout. 
private static final long TIMEOUT = 1000L; 

private BlockingQueue<Mat> frames = new LinkedBlockingQueue<Mat>(); 

Thread worker = new Thread() { 
    @Override 
    public void run() { 
     while (running) { 
      Mat inputFrame = frames.poll(TIMEOUT, TimeUnit.MILLISECONDS); 
      if (inputFrame == null) { 
       // timeout. Also, with a try {} catch block poll can be interrupted via Thread.interrupt() so not to wait for the timeout. 
       continue; 
      } 
      cropToCenter(inputFrame); 
      String result = doImgProcessing(inputFrame); 
     } 
    } 
}; 
worker.start(); 

public Mat onCameraFrame(Mat inputFrame) { 
    inputFrame.copyTo(mRgba);//this will be used for the live stream 
    frames.put(inputFrame); 
    return mRgba; 
} 

Các onCameraFrame đặt khung trên Queue, các cuộc thăm dò công nhân Chủ đề từ Queue.

Trang trí này tiếp nhận và xử lý khung. Bạn có thể theo dõi sự tăng trưởng của Hàng đợi bằng cách sử dụng frames.size().

Đây là ví dụ điển hình cho người tiêu dùng sản xuất.

+0

Ví dụ tuyệt vời. Hai câu hỏi mặc dù, đầu tiên, biến chạy boolean này, về mặt lý thuyết có nên chạy trong toàn bộ hoạt động không? Ngoài ra, bạn có đề nghị rằng khi thêm các khung vào hàng đợi, tôi nói một cái gì đó như thế, nếu (frames.size() <4) {frames.put (inputFrame);} ?? – Jameo

+1

Thông thường, bạn sẽ phải quyết định điều kiện dừng. 'running = false' là một cách xử lý nhanh chóng và đơn giản, nhưng nó có nghĩa là bạn sẽ bỏ phần còn lại của hàng đợi (có thể hoặc không thể là hành vi mong đợi). – njzk2

+1

Đối với kích thước hàng đợi, bạn có thể sử dụng hàng đợi dung lượng cố định (thêm giới hạn trong hàm tạo) và sử dụng 'offer (inputFrame)', sẽ cố gắng đặt đối tượng và trả về false nếu không có phòng trống. Điều đó có nghĩa là bạn có thể thả khung hình, nhưng bạn sẽ có một cái gì đó gần với điều trị thời gian thực. – njzk2

1

Nếu bạn làm điều này trên mỗi khung hình, có vẻ như bạn cần một chuỗi thay thế. AsyncTask là khi bạn muốn thực hiện một hoạt động một lần trên một luồng khác. Ở đây bạn muốn làm điều đó nhiều lần. Chỉ cần tạo một chuỗi, và khi nó kết thúc một khung, nó sẽ gửi một thông báo tới một trình xử lý để chạy bước đăng trên luồng giao diện người dùng. Nó có thể chờ đợi trên một semaphore ở đầu vòng lặp của nó cho khung tiếp theo để sẵn sàng.

+0

Tôi có thể thấy cách hoạt động . Nhưng không phải là một AsyncTask thực sự chỉ là một sợi không? – Jameo

+0

Bạn có nghĩ rằng có một lợi thế để cho phép hệ thống khởi động nhiều quá trình xử lý khung hình tại một thời điểm không? – Jameo

+0

Nó chạy trên một chuỗi, nhưng thoát khỏi chuỗi. Nếu bạn đang làm một cái gì đó contantly, đó là thực sự truy cập vào những gì bạn muốn. Đối với hơn 1 - thực sự nhận được nhiều hơn 1 nhiệm vụ không đồng bộ tại một thời điểm là khó khăn, nó đòi hỏi mã đặc biệt trên một số phiên bản Android. Và nó sẽ chỉ hữu ích nếu hệ điều hành là thông minh để chạy chúng trên lõi khác nhau, mà tôi nghi ngờ nó được. –

Các vấn đề liên quan