移动设备上的 YUV (NV21) 到 BGR 转换(本机代码)
YUV (NV21) to BGR conversion on mobile devices (Native Code)
我正在开发一个在Android和IOS上运行的移动应用程序。它能够实时处理视频流。在Android上,我通过android.hardware.Camera.PreviewCallback.onPreviewFrame获得相机的Preview-Videostream。我决定使用NV21格式,因为它应该被所有Android设备支持,而RGB则不是(或者只是RGB565)。
对于我的算法,主要用于模式识别,我需要灰度图像以及颜色信息。灰度不是问题,但是从NV21到BGR的颜色转换需要太长时间。
如上所述,我使用以下方法来捕获图像;
在应用程序中,我覆盖了相机的onPreviewFrame处理程序。这是在 CameraPreviewFrameHandler .java 中完成的:
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
{
try {
AvCore.getInstance().onFrame(data, _prevWidth, _prevHeight, AvStreamEncoding.NV21);
} catch (NativeException e)
{
e.printStackTrace();
}
}
然后,onFrame-Function 调用一个本机函数,该函数从 Java 对象中获取数据作为本地引用。然后将其转换为无符号 char* 字节流,并调用以下 c++ 函数,该函数使用 OpenCV 从 NV21 转换为 BGR:
void CoreManager::api_onFrame(unsigned char* rImageData, avStreamEncoding_t vImageFormat, int vWidth, int vHeight)
{
// rImageData is a local JNI-reference to the java-byte-array "data" from onPreviewFrame
Mat bgrMat; // Holds the converted image
Mat origImg; // Holds the original image (OpenCV-Wrapping around rImageData)
double ts; // for profiling
switch(vImageFormat)
{
// other formats
case NV21:
origImg = Mat(vHeight + vHeight/2, vWidth, CV_8UC1, rImageData); // fast, only creates header around rImageData
bgrMat = Mat(vHeight, vWidth, CV_8UC3); // Prepare Mat for target image
ts = avUtils::gettime(); // PROFILING START
cvtColor(origImg, bgrMat, CV_YUV2BGRA_NV21);
_onFrameBGRConversion.push_back(avUtils::gettime()-ts); // PROFILING END
break;
}
[...APPLICATION LOGIC...]
}
正如人们可能从代码中的注释中得出的结论一样,我已经分析了转换,结果发现我的 Nexus 30 需要 ~4 毫秒,这对于这样一个"微不足道"的预处理步骤来说是不可接受的。(我的分析方法经过仔细检查,可以正常工作以进行实时测量)
现在,我拼命地寻找从 NV21 到 BGR 的颜色转换的更快实现。这是我已经做的;
- 采用本主题中提供的代码"convertYUV420_NV21toRGB8888"C++(转换时间的倍数)
- 将代码从 1 修改为仅使用整数运算(openCV 解决方案的转换时间加倍)
- 浏览了其他几个实现,所有这些实现都具有相似的转换时间
- 检查了OpenCV实现,他们使用大量的位移来获得性能。猜猜我靠自己不能做得更好
您是否有建议/了解良好的实施,甚至有完全不同的方法来解决此问题?我需要以某种方式从Android相机捕获RGB/BGR帧,它应该在尽可能多的Android设备上工作。
感谢您的回复!
你试过libyuv吗?我过去使用过它,如果您在 NEON 支持下编译它,它使用针对 ARM 处理器优化的 asm 代码,您可以从那里开始进一步优化您的特殊情况。
- 防止主数据类型C++的隐式转换
- 模板参数替换失败,并且未完成隐式转换
- 努力将整数转换为链表。不知道我在这里做错了什么
- HEX值到wchar_t字符(UTF-8)的转换
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将 Qvector<uint8_t> 转换为 QString
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中使用nlohmann从类到json的转换
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- 复制列表初始化的隐式转换的等级是多少
- 将 BGR 图像转换为 jpeg 格式的 base64 字符串
- 在 opencv 中使用 Color_YUV2BGR 从 YUV 到 BGR 的错误转换
- 使用Inrange后,从HSV转换为BGR或OPENCV中的HSV到JPEG时出错
- 移动设备上的 YUV (NV21) 到 BGR 转换(本机代码)
- 在opencv, c++中转换bgr为hsv
- 基于FFMpeg的BGR缓冲图像到YUV的快速转换