我正在使用 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 服务器?
我希望这是有道理的......只是在线程部分遇到问题。预先感谢您!
最佳答案
我尝试在这里添加Thread 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();
}
};
关于Java多线程: Passing camera frame to running worker thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29366839/