首先说一下遇到的需求,想要做个展示camera的demo,输出的图像有 YUV 格式的 和 16位深度图。显示画面用opengl渲染到glSurfaceView上,得先把图像都转换成 RGB 格式,然后才能作为贴图渲染。
这种处理用 OpenCV 就能轻易实现了,对刚接触的人来说,只是要注意颜色格式等等的设置。
下面是把 yuv 转换成 rgb 的步骤:
cv::Mat rawMat = cv::Mat((height + (height >> 1)), width, CV_8UC1, rgbRawData);
cv::Mat rgbMat = cv::Mat(height,width,CV_8UC3);
cv::cvtColor(rawMat, rgbMat, CV_YUV2RGB_NV12);
这里 CV_8UC1, CV_8UC3 是指定颜色存储格式。
CV_8UC1 表示颜色通道是1,每个颜色用8位数据,高度指定为1.5倍,是因为 yuv420 格式有 H*W 个Y数据,另外还有一半存UV数据。
CV_8UC3 更好理解些,每个像素有3通道,分别是R,G,B,每个颜色用8位数据表示,宽高也就是图像真实的宽高。
最后执行颜色转换的时候,这里对应指定了 CV_YUV2RGB_NV12,其他格式还有很多。
处理深度图像的步骤:
dptMat = cv::Mat(depthH, depthW, CV_16UC1, depthRawData);
dptMat.convertTo(dptMat, CV_8U, 255.0 / 3840);
cv::applyColorMap(dptMat, dptMat, cv::COLORMAP_RAINBOW);
首先构建原始的cvMat,因为是16位单通道的,对应指定格式为 CV_16UC1。
因为16位数据无法进行颜色映射,先转为普通的8位数据,使用的函数是:
/** @brief Converts an array to another data type with optional scaling.
The method converts source pixel values to the target data type. saturate_cast\<\> is applied at
the end to avoid possible overflows:
\f[m(x,y) = saturate \_ cast( \alpha (*this)(x,y) + \beta )\f]
@param m output matrix; if it does not have a proper size or type before the operation, it is
reallocated.
@param rtype desired output matrix type or, rather, the depth since the number of channels are the
same as the input has; if rtype is negative, the output matrix will have the same type as the input.
@param alpha optional scale factor.
@param beta optional delta added to the scaled values.
*/
void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;
这里 scale 值的设置并不一定,可以调整。
映射颜色的时候,有多种预定义的模式可选,参考如下: