此问题与Android多线程,OpenCV和JNI有关。在onCameraFrame内部进行的JNI调用是一种昂贵的图像处理操作,因此相机预览帧速率变得非常慢(大量帧滞后)。何时,原生方法 - ' FindSquare'在一个新线程的后台调用,性能提高了一点但不是很多。
请建议最有效的方法来执行我打算在下面执行的操作,以便提高帧速率。
boolean isCallFinished = false;
public Mat onCameraFrame(Mat inputFrame) {
Size originalSize = inputFrame.size();
Imgproc.cvtColor(inputFrame, mDstImg, Imgproc.COLOR_RGBA2BGR);
Imgproc.resize(inputFrame, mDstImg, new Size(mScreenWidth,
mScreenHeight)); // 2048, 1536
new Thread(new Runnable() {
public void run() {
Message msg = new Message();
if(!isCallFinished) {
msg.arg1 = FindSquares(mDstImg.getNativeObjAddr()); // JNI call
isCallFinished = true;
messageHandler.sendMessage(msg);
}
}
}).start();
if (mDraw == 1) {
Imgproc.resize(mDstImg, inputFrame, originalSize);
}
return inputFrame;
}
答案 0 :(得分:0)
乍一看快速优化是为了避免为每个帧创建一个新线程。
创建一个新线程非常昂贵。
尝试以下方法:
我会尝试写下以下概念,并根据您的需求进行调整(请注意,代码未在适当的环境中进行测试)。
public class MyWorkerThread extends Thread
{
ArrayList<FrameEvent> frameList;
boolean runWorkerThread;
public WorkerThread
{
super("FrameEventsWorkerThread");
runWorkerThread=true;
frameList= new ArrayList<FrameEvent>();
}
public synchronized AddFrameEvent(FrameEvent aEvent)
{
frameList.add(aEvent);
}
public void kill ()
{
runWorkerThread=true;
}
public void run()
{
while (true && runWorkerThread)
{
synchronized(this)
{
if (frameList.size()>0)
{
for (int i=0;i<frameList.size();i++)
{
Message msg = new Message();
if (!isCallFinished) { // don't quite understand what you want with this
FrameEvent evt = frameList.get(i);
msg.arg1 = FindSquares(evt.dstImg.getNativeObjAddr());
isCallFinished=true;
messageHandler.sendMessage(msg);
}
}
frameList.clear();
}
}
try {
Thread.sleep(10);
} catch (Exception e)
{
}
}
}
}
您的新功能应如下所示:
boolean isCallFinished = false;
MyWorkerThread theThread;
public Mat onCameraFrame(Mat inputFrame) {
Size originalSize = inputFrame.size();
Imgproc.cvtColor(inputFrame, mDstImg, Imgproc.COLOR_RGBA2BGR);
Imgproc.resize(inputFrame, mDstImg, new Size(mScreenWidth,
mScreenHeight)); // 2048, 1536
FrameEvent newEvt = new FrameEvent();
newEvt.dstImg = mDstImg;
theThread.AddFrameEvent(newEvt); // avoid creating new threads
if (mDraw == 1) {
Imgproc.resize(mDstImg, inputFrame, originalSize);
}
return inputFrame;
}