2015-03-31 55 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