在android中使用openCV Java方法检测图像中的圆形对象时帧速率极慢
Imgproc.HoughCircles(mGray, circles, Imgproc.CV_HOUGH_GRADIENT, 1, 50);
当我删除此方法时,它运行速度很快,但在此回调中添加此方法后
public Mat onCameraFrame(final CvCameraViewFrame inputFrame) {
帧速率减慢到每秒1到2帧,我不明白为什么它变得这么慢,我尝试将此方法放在一个单独的线程中并且它无济于事,唯一有效的方法是使用counter和if语句每10帧运行一次。
在OpenCV示例中有一个名为人脸检测的示例项目,它既有原生C ++版本又有Java相机版本,而且两者都变化很快,当我使用类似代码时,我怎么可能从这个缓慢的便秘行动OpenCV的?
我在这里做错了吗?在openCV示例的面部检测项目中,它们采用每一帧,并且它们不会启动单独的线程。如何修复此问题并使我的代码像OpenCV中的示例项目一样快速运行?
在一个不同的项目中我也有同样的帧速率慢的问题,在这个练习项目中我没有使用openCV,它只是android Camera类,因为我从onPreviewFrame获取图像( byte []数据,Camera camera)方法并进行一些光处理,例如将YUV格式从字节数组转换为位图,并将其放入与摄像机视图相同的屏幕上的另一个视图中,结果是帧速率变化很慢。
编辑:在一些额外的实验中,我将Imgproc.HoughCircles()方法添加到OpenCV人脸检测示例项目中。将此方法放在java检测器的onCameraFrame方法中。
结果与我的项目相同,变得缓慢。所以HoughCircles方法可能比面部检测方法CascadeClassifier.detectMultiScale()需要更多的处理能力,但是这并没有解释我在youTube上观看其他圈子检测项目的事实,并且在他们的视频中帧速率没有减慢。这就是为什么我认为我正在做的事情有问题。
这是我正在使用的代码示例
public class CircleActivity extends Activity implements CvCameraViewListener2 {
Mat mRgba;
Mat mGray;
File mCascadeFile;
CascadeClassifier mJavaDetector;
CameraBridgeViewBase mOpenCvCameraView;
LinearLayout linearLayoutOne;
ImageView imageViewOne;
int counter = 0;
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i("OPENCV", "OpenCV loaded successfully");
mOpenCvCameraView.enableView();
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
if (!OpenCVLoader.initDebug()) {
// Handle initialization error
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_coffee);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.fd_activity_surface_view);
mOpenCvCameraView.setCvCameraViewListener(this);
}
@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();
mOpenCvCameraView.disableView();
}
public void onCameraViewStarted(int width, int height) {
mGray = new Mat();
mRgba = new Mat();
}
public void onCameraViewStopped() {
mGray.release();
mRgba.release();
}
public Mat onCameraFrame(final CvCameraViewFrame inputFrame) {
mRgba = inputFrame.rgba();
mGray = inputFrame.gray();
if(counter == 9) {
MatOfRect circles = new MatOfRect();
Imgproc.HoughCircles(mGray, circles, Imgproc.CV_HOUGH_GRADIENT, 1, 50);
// returns number of circular objects found
Log.e("circle check", "circles.cols() " + circles.cols());
}
counterAdder();
return mRgba;
} // end oncamera frame
public void counterAdder() {
if (counter > 10) {
counter = 0;
}
counter++;
}
}
答案 0 :(得分:4)
降低相机框架的分辨率可能会有所帮助
mOpenCvCameraView.setMaxFrameSize(640, 480);
答案 1 :(得分:1)
根据我的简短经验,HoughCircles的运行时间在很大程度上取决于图像。具有大量潜在圆圈的纹理图像比具有均匀背景的图像花费更长的时间。希望这会有所帮助。
答案 2 :(得分:0)
您必须在后台而不是主要活动中执行Hough Circle变换!
否则,您的应用程序响应将太慢,并且可能由于应用程序无响应(ANR)错误而被操作系统杀死。
您需要将此类添加到您的主要活动中,您很高兴。
private class HoughCircleTransformTask
extends AsyncTask<Mat, Void, Integer> {
@Override
protected Boolean doInBackground(Mat mGray) {
MatOfRect circles = new MatOfRect();
Imgproc.HoughCircles(mGray, circles, Imgproc.CV_HOUGH_GRADIENT, 1, 50);
// returns number of circular objects found
// then display it from onPostExecute()
return circles.cols();
}
@Override
protected void onPostExecute(Integer circlesCols){
// This is only logging
// You can display it in a TextView as well in the main activity
Log.e("circle check", "circles.cols() " + circles.cols());
}
}
只需在onCameraFrame中仅用一行代码调用它
public Mat onCameraFrame(final CvCameraViewFrame inputFrame) {
mRgba = inputFrame.rgba();
mGray = inputFrame.gray();
if(counter == 9) {
// call AsyncTask
new HoughCircleTransformTask().execute(mGray);
}
counterAdder();
return mRgba;
} // end oncamera frame