我目前正在尝试使用OpenCV创建一个Android应用程序,允许用户使用智能手机相机跟踪移动对象的点。可以在以下链接中找到C ++中完全符合我要求的类似代码:OpticalFlow C++ Sample Code
我一直在谷歌搜索和浏览StackOverflow,但我仍然无法弄清楚为什么我的代码不起作用。每次按下某个位置时,我都可以在屏幕上放置点,但即使我在相机前移动物体,这些点似乎也一动不动。用于计算opitcal流的方法如下:
void org.opencv.video.Video.calcOpticalFlowPyrLK(Mat prevImg, Mat nextImg, MatOfPoint2f prevPts, MatOfPoint2f nextPts, MatOfByte status, MatOfFloat err)
我相信我正在传递计算连续图像光流所需的确切参数,但由于某种原因它无法正常工作。以下是我的代码:
package org.opencv.UActivity;
//INCLUDE FILES
...
public class U2Activity extends Activity implements OnTouchListener,CvCameraViewListener2{
private static final String TAG = "OCVSample::Activity";
private Mat nextGray,Rscale;
private Mat prevGray;
private MatOfPoint2f prev2D,next2D;
private MatOfByte status;
private MatOfFloat err;
private Scalar color;
private CameraBridgeViewBase mOpenCvCameraView;
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i(TAG, "OpenCV loaded successfully");
mOpenCvCameraView.enableView();
mOpenCvCameraView.setOnTouchListener(U2Activity.this);
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
public U2Activity() {
Log.i(TAG, "Instantiated new " + this.getClass());
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "called onCreate");
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.u2_surface_view);
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.u2_activity_surface_view);
mOpenCvCameraView.setCvCameraViewListener(this);
color = new Scalar(0, 255, 0);
}
@Override
public void onPause()
{
super.onPause();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
@Override
public void onResume()
{
super.onResume();
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);
}
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
public void onCameraViewStarted(int width, int height) {
nextGray = new Mat(height, width, CvType.CV_8UC1); //unsigned char
Rscale = new Mat(height, width, CvType.CV_8UC1);
prevGray = new Mat(height, width, CvType.CV_8UC1);
prev2D = new MatOfPoint2f(new Point());
next2D = new MatOfPoint2f(new Point());
status = new MatOfByte();
err = new MatOfFloat();
}
public void onCameraViewStopped() {
nextGray.release();
Rscale.release();
}
public boolean onTouch(View v, MotionEvent event) {
int cols = nextGray.cols();
int rows = nextGray.rows();
int xOffset = (mOpenCvCameraView.getWidth() - cols) / 2;
int yOffset = (mOpenCvCameraView.getHeight() - rows) / 2;
int x = (int)event.getX() - xOffset;
int y = (int)event.getY() - yOffset;
if ((x < 0) || (y < 0) || (x > cols) || (y > rows)) return false;
prev2D.push_back(new MatOfPoint2f(new Point((double)x,(double)y)));
next2D.push_back(new MatOfPoint2f(new Point()));
return false; // don't need subsequent touch events
}
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
nextGray = inputFrame.gray(); //get current image
Rscale = nextGray; //make a copy of current image
if(prevGray.empty()) prevGray = nextGray; //on start there is no prevGray. Copy current.
Video.calcOpticalFlowPyrLK(prevGray,nextGray,prev2D,next2D,status,err); //Calc the Optical Flow
prevGray = nextGray; //Overwrite old Image (prevGray)
prev2D = next2D; //Overwrite old point coordinates
for(int i=0;i<next2D.toArray().length;i++){ //Draw the points in the image
Core.circle(Rscale, next2D.toArray()[i], 3, color);
}
return Rscale;
}
}
答案 0 :(得分:0)
<强>解决强>:
我改变了:
prevGray = nextGray;
prev2D = next2D;
为:
nextGray.copyTo(prevGray);
next2D.copyTo(prev2D);
我希望它可以帮助任何遇到类似问题的人。