Android OpenCV : update camera frames while executing AsyncTask

标签 android opencv android-asynctask camera

我创建了一个 AsyncTask用于在调用 onClick() 后处理多个相机帧,但相机会卡住,直到 AsyncTask已完成执行。

有没有办法避免这种行为?我的意思是,在执行 AsyncTask 期间是否可以不断更新相机帧? ?

异步任务代码:

private class ReadCodeTask extends AsyncTask<Mat[], List<Mat>, List<Bitmap>> {

    protected Mat[] onPreExecute(List<Mat> frames){
        Mat[] output = new Mat[4];;
        for(int i=0; i<frames.size(); i++){
            mH = new Mat();
            List<Mat> channels = new ArrayList<Mat>(3);
            // convert inputFrame to HSV for segmentation
            Mat hsvFrame = new Mat(frames.get(i).height(), frames.get(i).width(), CvType.CV_8UC3, new Scalar(4));
            Imgproc.cvtColor(frames.get(i), hsvFrame, Imgproc.COLOR_RGB2HSV, 0);

            Core.split(hsvFrame, channels);

            // get H channel of the input image
            mH = channels.get(0);

            if(mH!=null){
                double meanH = 0;
                double size = mH.rows()*mH.cols();
                // average saturation in frame
                for(int k=0; k<mH.rows(); k++){
                    for(int j=0; j<mH.cols(); j++){
                        meanH += mH.get(k, j)[0]/size;
                    }
                }
                if(meanH<=0.2*180){ // if WHITE BACKGROUND
                    output[i] = frames.get(i);
                    continue;
                }
            }else{
                Log.e("ERR", "Error converting to HSV");
            }
            gray = new Mat(frames.get(i).height(), frames.get(i).width(), CvType.CV_8UC1, new Scalar(4));
            Imgproc.cvtColor(frames.get(i), gray, Imgproc.COLOR_RGB2GRAY, 0);
            Mat grayBin = new Mat();
            Scalar lowG = new Scalar(0.9*255);
            Scalar highG = new Scalar(1*255);
            Core.inRange(gray, lowG, highG, grayBin);
            Imgproc.findContours(grayBin, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_NONE);
            for(int c=0; c<contours.size(); c++){
                if(couldItBeASquare(contours.get(c))){
                    boundingRect = Imgproc.boundingRect(contours.get(c));
                }
            }
            Mat qrSubIm = new Mat();
            try{
                qrSubIm = frames.get(i).submat(boundingRect);
            }catch(NullPointerException e){
                //          Log.e("ERR", e.getMessage());
            }
            if(qrSubIm != null){
                output[i] = qrSubIm;
            }else{
                output[i] = frames.get(i);
            }
        }
        return output;
    }

    @Override
    protected List<Bitmap> doInBackground(Mat[]... params) {
        List<Bitmap> bmp = new ArrayList<Bitmap>();

        for(int i=0; i<params.length; i++){
            Mat mRgb = params[0][i];
            qr = new Mat();
            mQrFinder.qrFindJNI(mRgb.getNativeObjAddr(), qr.getNativeObjAddr());
            Bitmap aux = null;
            if(qr.cols()!=0 || qr.rows()!=0){
                try {
                    aux = Bitmap.createBitmap(qr.cols(), qr.rows(), Bitmap.Config.ARGB_8888);
                    Utils.matToBitmap(qr, aux);
                    bmp.add(aux);
                }catch (CvException e){
                    Log.e("Exception",e.getMessage());
                }
            }
        }
        return bmp;
    }

    @Override
    protected void onPostExecute(List<Bitmap> bmp) {
        List<String> results = new ArrayList<String>(bmp.size());
        for(int i=0; i<bmp.size(); i++){
            try {
                String aux = readQRCode(bmp.get(i));
                results.add(aux);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (NotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        for(int i=0; i<results.size(); i++){
            if(!results.get(i).contentEquals("NOTHING")){
                Toast toast = Toast.makeText(mContext, results.get(i), android.widget.Toast.LENGTH_SHORT);
                toast.show();
            }
        }
        return;
    }
}

注意 onPreExecute()方法没有被覆盖,我必须像这样手动调用它:
ReadCodeTask task = new ReadCodeTask();
task.execute(task.onPreExecute(frames));

为了完成,以下代码对应于 camera listener我用于检索帧:
camListener = new CvCameraViewListener2() {

        @Override
        public void onCameraViewStopped() {
            // TODO Auto-generated method stub
        }

        @Override
        public void onCameraViewStarted(int width, int height) {
            //              
        }

        @Override
        public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
            rgb = inputFrame.rgba();
            if(frames != null){
                if(frames.size()<4){
                    frames.add(rgb);
                }
                if(frames.size()==4){
                    List<Mat> aux = frames;
                    for (int k = 0; k<aux.size()-1; k++){
                        frames.set(k, aux.get(k+1));
                    }
                    frames.set(aux.size()-1, rgb);
                }
            }
            return rgb;
        }
    };

最佳答案

我的意思是这样的。请注意 mContext,您应该传递一个上下文,或者如果您的 asynctask 是扩展 Activiti 的类中的私有(private)类,那么您可以将“.this”传递给 toast。

private class ReadCodeTask extends AsyncTask<List<Mat>, Void, List<Bitmap>> {       

    @Override
    protected List<Bitmap> doInBackground(List<Mat>... frames) {

         Mat[] output = new Mat[4];;
         for(int i=0; i<frames.length; i++){
             mH = new Mat();
             List<Mat> channels = new ArrayList<Mat>(3);
             // convert inputFrame to HSV for segmentation
             Mat hsvFrame = new Mat(frames[0].get(i).height(), frames[0].get(i).width(), CvType.CV_8UC3, new Scalar(4));
             Imgproc.cvtColor(frames[0].get(i), hsvFrame, Imgproc.COLOR_RGB2HSV, 0);

             Core.split(hsvFrame, channels);

             // get H channel of the input image
             mH = channels.get(0);

             if(mH!=null){
                 double meanH = 0;
                 double size = mH.rows()*mH.cols();
                 // average saturation in frame
                 for(int k=0; k<mH.rows(); k++){
                     for(int j=0; j<mH.cols(); j++){
                         meanH += mH.get(k, j)[0]/size;
                     }
                 }
                 if(meanH<=0.2*180){ // if WHITE BACKGROUND
                     output[i] = frames[0].get(i);
                     continue;
                 }
             }else{
                 Log.e("ERR", "Error converting to HSV");
             }
             gray = new Mat(frames[0].get(i).height(), frames[0].get(i).width(), CvType.CV_8UC1, new Scalar(4));
             Imgproc.cvtColor(frames[0].get(i), gray, Imgproc.COLOR_RGB2GRAY, 0);
             Mat grayBin = new Mat();
             Scalar lowG = new Scalar(0.9*255);
             Scalar highG = new Scalar(1*255);
             Core.inRange(gray, lowG, highG, grayBin);
             Imgproc.findContours(grayBin, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_NONE);
             for(int c=0; c<contours.size(); c++){
                 if(couldItBeASquare(contours.get(c))){
                     boundingRect = Imgproc.boundingRect(contours.get(c));
                 }
             }
             Mat qrSubIm = new Mat();
             try{
                 qrSubIm = frames[0].get(i).submat(boundingRect);
             }catch(NullPointerException e){
                 //          Log.e("ERR", e.getMessage());
             }
             if(qrSubIm != null){
                 output[i] = qrSubIm;
             }else{
                 output[i] = frames[0].get(i);
             }
         }

        List<Bitmap> bmp = new ArrayList<Bitmap>();

        for(int i=0; output.length; i++){
            Mat mRgb = output[i];
            qr = new Mat();
            mQrFinder.qrFindJNI(mRgb.getNativeObjAddr(), qr.getNativeObjAddr());
            Bitmap aux = null;
            if(qr.cols()!=0 || qr.rows()!=0){
                try {
                    aux = Bitmap.createBitmap(qr.cols(), qr.rows(), Bitmap.Config.ARGB_8888);
                    Utils.matToBitmap(qr, aux);
                    bmp.add(aux);
                }catch (CvException e){
                    Log.e("Exception",e.getMessage());
                }
            }
        }
        return bmp;
    }

    @Override
    protected void onPostExecute(List<Bitmap> bmp) {
        List<String> results = new ArrayList<String>(bmp.size());
        for(int i=0; i<bmp.size(); i++){
            try {
                String aux = readQRCode(bmp.get(i));
                results.add(aux);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (NotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        for(int i=0; i<results.size(); i++){
            if(!results.get(i).contentEquals("NOTHING")){
                Toast toast = Toast.makeText(mContext, results.get(i), android.widget.Toast.LENGTH_SHORT);
                toast.show();
            }
        }
        return;
    }
}

我不确定我是否拼错了什么。为什么会这样?通常 onPreExceute 的类型为 void,因此当您重载此方法时,UI 可能会被阻塞。反正我会试一试。

请记住,onPreExecute 方法在 UI 线程中运行。参见文档:http://developer.android.com/reference/android/os/AsyncTask.html#onPreExecute()

关于Android OpenCV : update camera frames while executing AsyncTask,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24861360/

相关文章:

android - 带有 UTF8 文本的 POST 以 ASCII 形式出现

java - 无法使用 Android Gradle 插件 2.1 生成 View 绑定(bind)程序 java.util.NoSuchElementException

python-3.x - 当同时存在白色和黑色背景时,如何将整个图像的背景转换为白色?

java - 将 AsyncTask 从类中调用到 MainActivity 中

java - android平台sqlite数据库的可扩展访问

android - Button数组的RecyclerView - 如何更新数据?

c++ - 实时应用的OpenCV fastNlMeansDenoising的替代方法?

opencv - 使用 cv2.imread (OpenCV) 和 PIL.Image.open (Pillow) 将图像打开到 numpy 数组时的不同结果

android - Kotlin Coroutine,Android Async Task 和 Async await 的区别

android - AsyncTask调用主类方法,它在后台完全工作吗?