我正在尝试使用Camera 2 API将从ImageReader收到的Image转换为OpenCV矩阵,并使用CameraBridgeViewBase中的deliverAndDrawFrame函数在屏幕上显示它。读取器的ImageFormat为YUV_420_888,据我所知,它具有每个像素的灰度值的Y平面和每4个像素中具有U / V的U平面。然而,当我尝试显示这个图像时,它似乎重复出现并且旋转了90度。下面的代码旨在将YUV数据放入OpenCV矩阵中(目前仅为灰度,不是rgba):
这是我为OpenCV框架编写的代码:
接收并绘制帧的代码:
注意:
以下是使用上述代码的图像:https://istack.dev59.com/lcdzf.webp 这是在
我们可以看到数据在Y帧中重复出现,不知何故这给出了一个实际上好看的图像。
/**
* Takes an {@link Image} in the {@link ImageFormat#YUV_420_888} and puts it into a provided {@link Mat} in rgba format.
*
* @param yuvImage {@link Image} in the {@link ImageFormat#YUV_420_888} format.
*/
public static void yuv420888imageToRgbaMat(final Image yuvImage, final Mat rgbaMat) {
final Image.Plane
Yp = yuvImage.getPlanes()[0],
UandVp = yuvImage.getPlanes()[1];
final ByteBuffer
Ybb = Yp .getBuffer(),
UandVbb = UandVp.getBuffer();
Ybb .get(mYdata , 0, 480*640 );
UandVbb.get(mUandVData, 0, 480*640 / 2 - 8);
for (int i = 0; i < 640*480; i++) {
for (int j = 0; j < 4; j++) {
mRawRGBAFrameData[i + 640*480*j] = mYdata[i];
}
mRawRGBAFrameData[i*4 ] = mYdata[i];
mRawRGBAFrameData[i*4+1] = mYdata[i];
mRawRGBAFrameData[i*4+2] = mYdata[i];
mRawRGBAFrameData[i*4+3] = -1;
}
}
这是我为OpenCV框架编写的代码:
private class CameraFrame implements CvCameraViewFrame {
private Mat mRgba;
@Override
public Mat gray() {
return null;
}
@Override
public Mat rgba() {
mRgbaMat.put(0, 0, mRawRGBAFrameData);
return mRgba;
}
public CameraFrame(final Mat rgba) {
super();
mRgba = rgba;
}
}
接收并绘制帧的代码:
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
final Image yuvImage = reader.acquireLatestImage();
yuv420888imageToRgbaMat(yuvImage, mRgbaMat);
deliverAndDrawFrame(mFrame);
yuvImage.close();
}
};
这是制作图像读取器的代码:
mRgbaMat = new Mat(mFrameHeight, mFrameWidth, CvType.CV_8UC4);
mFrame = new CameraFrame(mRgbaMat);
mImageReader = ImageReader.newInstance(mFrameWidth, mFrameHeight, ImageFormat.YUV_420_888, 1);
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);
AllocateCache();
这是数组的初始化:
protected static byte[] mRawRGBAFrameData = new byte[640*480*4], mYdata = new byte[640*480], mUandVData = new byte[640*480 / 2];
注意:
mFrameWidth
为480,mFrameHeight
为640。奇怪的是,ImageReader
的高度和宽度以及从中接收到的Image
具有倒置的尺寸。以下是使用上述代码的图像:https://istack.dev59.com/lcdzf.webp 这是在
yuv420888imageToRgbaMat
中使用此代码的图像: https://istack.dev59.com/T2MOI.webp
for (int i = 0; i < 640*480; i++) {
mRawRGBAFrameData[i] = mYdata[i];
}
我们可以看到数据在Y帧中重复出现,不知何故这给出了一个实际上好看的图像。
Core.flip(m_BGRMat, m_BGRMat, 0);
存在问题,图像看起来是倒置的,所以我将其更改为Core.flip(m_BGRMat, m_BGRMat, 1);
,同时将COLOR_YUV420p2BGR
更改为COLOR_YUV420p2RGB
以进行JPEG转换。 - sercanturkmen