【发布时间】:2019-05-30 06:09:24
【问题描述】:
我在 NV21 帧的感兴趣区域(中心)周围添加一个黑色 (0) 填充,该帧是从线程中的 Android CameraPreview 回调获得的。
为避免转换为 RGB/位图和反向的开销,我尝试直接操作 NV21 字节数组,但这涉及嵌套循环,这也使预览/处理速度变慢。
这是我的run()方法在调用blackNonROI方法后向检测器发送帧。
public void run() {
Frame outputFrame;
ByteBuffer data;
while (true) {
synchronized (mLock) {
while (mActive && (mPendingFrameData == null))
try{ mLock.wait(); }catch(InterruptedException e){ return; }
if (!mActive) { return; }
// Region of Interest
mPendingFrameData = blackNonROI(mPendingFrameData.array(),mPreviewSize.getWidth(),mPreviewSize.getHeight(),300,300);
outputFrame = new Frame.Builder().setImageData(mPendingFrameData, mPreviewSize.getWidth(),mPreviewSize.getHeight(), ImageFormat.NV21).setId(mPendingFrameId).setTimestampMillis(mPendingTimeMillis).setRotation(mRotation).build();
data = mPendingFrameData;
mPendingFrameData = null;
}
try {
mDetector.receiveFrame(outputFrame);
} catch (Throwable t) {
} finally {
mCamera.addCallbackBuffer(data.array());
}
}
}
下面是方法blackNonROI
private ByteBuffer blackNonROI(byte[] yuvData, int width, int height, int roiWidth, int roiHeight){
int hozMargin = (width - roiWidth) / 2;
int verMargin = (height - roiHeight) / 2;
// top/bottom of center
for(int x=0; x<width; x++){
for(int y=0; y<verMargin; y++)
yuvData[y * width + x] = 0;
for(int y=height-verMargin; y<height; y++)
yuvData[y * width + x] = 0;
}
// left/right of center
for(int y=verMargin; y<height-verMargin; y++){
for (int x = 0; x < hozMargin; x++)
yuvData[y * width + x] = 0;
for (int x = width-hozMargin; x < width; x++)
yuvData[y * width + x] = 0;
}
return ByteBuffer.wrap(yuvData);
}
请注意,我没有裁剪图像,只是在图像的指定中心周围填充黑色像素,以保持协调以进行进一步的活动。这可以正常工作,但速度不够快,会导致预览和帧处理出现延迟。
- 能否进一步改进字节数组更新?
- 调用blackNonROI的时间/地点合适吗?
- 还有什么其他方式/lib 可以更有效地做到这一点?
- 我简单的像素迭代这么慢,YUV/Bitmap 库怎么做复杂的事情这么快?他们使用 GPU 吗?
编辑:
我已经用以下代码替换了两个for 循环,现在速度非常快(详情请参阅greeble31 的回答):
// full top padding
from = 0;
to = (verMargin-1)*width + width;
Arrays.fill(yuvData,from,to,(byte)1);
// full bottom padding
from = (height-verMargin)*width;
to = (height-1)*width + width;
Arrays.fill(yuvData,from,to,(byte)1);
for(int y=verMargin; y<height-verMargin; y++) {
// left-middle padding
from = y*width;
to = y*width + hozMargin;
Arrays.fill(yuvData,from,to,(byte)1);
// right-middle padding
from = y*width + width-hozMargin;
to = y*width + width;
Arrays.fill(yuvData,from,to,(byte)1);
}
【问题讨论】:
标签: android image-processing android-camera yuv google-vision