【问题标题】:Java multithreading: Passing camera frame to running worker threadJava多线程:将相机帧传递给正在运行的工作线程
【发布时间】:2015-03-31 10:48:19
【问题描述】:

我正在使用 OpenCV4Android 并捕获相机帧,因此每次捕获一帧时,都会调用 Mat onCameraFrame(CvCameraViewFrame inputFrame) 方法。在该方法中,我在 Mat 对象 (mRgba) 中接收帧。

单击按钮后,我开始将这些帧发送到连接的 FTP 服务器。当再次单击该按钮时,我停止发送帧。我需要把它放在一个单独的线程上,因为发送这些帧会导致很多 GUI 延迟。

我正在努力概念化和编码的是...能够让一个线程在单击按钮时启动和停止,并初始化并启动线程一次 - 启动时,从相机接收每个相机帧并推送该相机帧输出到 FTP 服务器。

目前我有这个:

public class FdActivity extends Activity implements CvCameraViewListener2 { 

    private FTPImage ftp;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //connect to FTP server
        ftp = new FTPImage();   

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                String ftpResult = ftp.connectToFTP(config.getFtpIP());
            }
        };
        new Thread(runnable).start();       
    }

    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        mRgba = inputFrame.rgba();
        mGray = inputFrame.gray();

        if (isRecordFrames) {       
            Bitmap bmp;
            try {
                //convert Mat to Bitmap
                bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888);         
                Utils.matToBitmap(mRgba, bmp);  
                //scale down Bitmap
                final Bitmap scaledBmp = Bitmap.createScaledBitmap(bmp, bmp.getWidth()/2, bmp.getHeight()/2, false);

                //issue - this is going to create a Runnable for each frame     
                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        ftp.writeImageToFTP(scaledBmp);
                    }
                };
                new Thread(runnable).start();   
            }
            catch(Exception ex) {
                Log.i(TAG, "Exception onCameraFrame");
            }
        }   
        return mRgba;
    }
}

FTPImage 类:

public class FTPImage {

    private FTPClient ftpClient = null;

    public String connectToFTP(String ftpIP) {
        ftpClient = new FTPClient();
        String reply = "";

        try {
            ftpClient.connect(InetAddress.getByName(ftpIP));

            if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
                ftpClient.disconnect();
            }       
            ftpClient.enterLocalPassiveMode();          
            ftpClient.login("anonymous", "");       
            reply = ftpClient.getReplyString();         

        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                }
                catch (IOException ex)
                { }
            }
            e.printStackTrace();
        }
        return reply;
    }

    public void writeImageToFTP(Bitmap b) {
        if (ftpClient != null) {
            if (ftpClient.isConnected()) {
                try {
                    boolean res = ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

                    ByteArrayOutputStream stream = new ByteArrayOutputStream();         
                    b.compress(CompressFormat.PNG, 100, stream);

                    BufferedInputStream buffIn = new BufferedInputStream(
                            new ByteArrayInputStream(stream.toByteArray()));

                    res = ftpClient.storeFile("testImg.jpg", buffIn);
                    //when res returns, storeFile has finished uploading
                    String reply = ftpClient.getReplyString();

                    buffIn.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void disconnectFromFTP() {
        try {
            if (ftpClient.isConnected()) {
                ftpClient.logout(); 
                ftpClient.disconnect();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

如何将每个相机帧传递给一个单独的运行线程,然后将该帧发送到 FTP 服务器?

我希望这是有道理的……只是线程部分有问题。提前谢谢!

【问题讨论】:

    标签: java android multithreading ftp streaming


    【解决方案1】:

    我已尝试在此处添加线程 UploadThread:

    public class FdActivity extends Activity implements CvCameraViewListener2 { 
    
    private FTPImage ftp;
    
    // declaration
    private UploadThread mUploadThread;
    private Handler mUploadHandler;
    public static int UPLOAD_IMAGE = 11;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    // initialization
    mUploadThread = new UploadThread(this);
    mUploadThread.start();
        //connect to FTP server
        ftp = new FTPImage();   
    
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                String ftpResult = ftp.connectToFTP(config.getFtpIP());
            }
        };
        new Thread(runnable).start();       
    }
    
    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        mRgba = inputFrame.rgba();
        mGray = inputFrame.gray();
    
        if (isRecordFrames) {       
            Bitmap bmp;
            try {
                //convert Mat to Bitmap
                bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888);         
                Utils.matToBitmap(mRgba, bmp);  
                //scale down Bitmap
                final Bitmap scaledBmp = Bitmap.createScaledBitmap(bmp, bmp.getWidth()/2, bmp.getHeight()/2, false);
    
    
    
        Message msg = Message.obtain();
        msg.what = UPLOAD_IMAGE;
        mUploadHandler.sendMessage(msg);    // this way we send message to upload thread queue
            }
            catch(Exception ex) {
                Log.i(TAG, "Exception onCameraFrame");
            }
        }   
        return mRgba;
    }
    
    Thread UploadThread = new Thread() {
        private Context;
        public UploadThread(Context context) {
            this.context = context;
        }
        @Override
        public void run() {
            Looper.prepare();
            mUploadHandler = new Handler() {
                public void handleMessage(msg) {
                    case UPLOAD_IMAGE:
                    ftp.writeImageToFTP(scaledBmp);     // uploading    
                    break;              
                }
            }               
    
    
            Looper.loop();
    
            }
    };
    

    【讨论】:

    • 我觉得如果你使用 AsynkTask 而不是 Thread 那么你的情况会更好
    • 感谢您的帮助!我什至没有考虑过使用 Looper,所以我现在正在研究它。
    猜你喜欢
    • 2011-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-05
    • 2011-08-16
    • 2011-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多