2015-03-31 57 views
0

我使用OpenCV4Android并捕获相机帧,因此每次捕获帧时都会调用方法Mat onCameraFrame(CvCameraViewFrame inputFrame)。在该方法中,我收到Mat对象(mRgba)中的帧。Java多线程:将相机帧传递给正在运行的工作线程

当一个按钮被点击后,我开始发送这些帧到一个连接的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服务器?

我希望这是有道理的...只是有线程部分的麻烦。先谢谢你!

回答

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

     } 
}; 
+0

我觉得如果你使用AsynkTask,而不是线程那么这将是对你的情况 – Kushal 2015-03-31 11:17:04

+0

更好的是你的问题解决了吗? – Kushal 2015-03-31 13:52:05

+0

谢谢你的帮助!我甚至没有考虑过使用Looper,所以我现在正在研究它。 – LKB 2015-04-01 02:41:34