不知道如果這個任務實際上需要 opencv(可能有點矯枉過正)但如果你選擇它,它相當容易。
看到所有我們在這裏做的是不斷地記錄幀,並實時/回放模式之間的一些事件(爲簡單起見,這裏onTouch)切換:
package com.berak.echo;
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.app.Activity;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import com.berak.echo.R;
public class EchoActivity extends Activity implements CvCameraViewListener2, OnTouchListener {
CameraBridgeViewBase mOpenCvCameraView;
List<Mat> ring = new ArrayList<Mat>(); // recording buffer
int delay = 100; // delay == length of buffer
boolean delayed = false; // state
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_echo);
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.cam3_surface_view);
mOpenCvCameraView.setCvCameraViewListener(this);
mOpenCvCameraView.setOnTouchListener(this); // setup as touchlistener
}
// lots of boilerplate, ugly, but needed.
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
mOpenCvCameraView.enableView();
break;
default:
super.onManagerConnected(status);
break;
}
}
};
@Override
public void onResume() {;
super.onResume();
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_5,this, mLoaderCallback);
}
@Override
public void onPause() {
super.onPause();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public void onCameraViewStarted(int width, int height) { }
@Override
public void onCameraViewStopped() { }
// here's the bread & butter stuff:
@Override
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
Mat mRgba = inputFrame.rgba();
ring.add(mRgba.clone()); // add one at the end
if (ring.size() >= delay) { // pop one from the front
ring.get(0).release();
ring.remove(0);
}
Mat ret;
String txt;
if (delayed && ring.size()>0) { // depending on 'delayed' return either playback
ret = ring.get(0); // return the 'oldest'
txt = "playback";
} else {
ret = mRgba; // or realtime frame
txt = "realtime";
}
Core.putText(ret, txt, new Point(20,20), Core.FONT_HERSHEY_PLAIN, 1.2, new Scalar(200,0,0));
return ret;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
// just toggle between delayed an realtime view:
delayed = ! delayed;
return false;
}
}
聽起來是可行的。只需將您的幀記錄到內存中的環形緩衝區,然後根據需要 – berak
重播即可。但這並不簡單或不重要,我也不認爲有人能夠在StackOverflow上回復幾行。作爲第一次Android程序員,您將很難完成這項任務。 – Budius
@Budius,爲什麼嚇到他?實際上這很容易。非常好的noob項目imho。 – berak