使用 OpenCV 从 android Camera2 将 YUV 转换为 RGB ImageReader 时出现问题,输出图像为灰度
Posted
技术标签:
【中文标题】使用 OpenCV 从 android Camera2 将 YUV 转换为 RGB ImageReader 时出现问题,输出图像为灰度【英文标题】:Problem converting YUV to RGB ImageReader from android Camera2 using OpenCV, output image is in grayscale 【发布时间】:2019-08-28 05:27:25 【问题描述】:我正在尝试在 java 中的 onImageAvailable 方法中将图像从 YUV 转换为 RGB。
我正在使用 openCV 进行转换。 我不能使用 android Camera2 的 RGB 格式来避免丢帧。
我无法选择最佳的转换格式。
Image.Plane Y = image.getPlanes()[0];
Image.Plane U = image.getPlanes()[1];
Image.Plane V = image.getPlanes()[2];
Y.getBuffer().position(0);
U.getBuffer().position(0);
V.getBuffer().position(0);
int Yb = Y.getBuffer().remaining();
int Ub = U.getBuffer().remaining();
int Vb = V.getBuffer().remaining();
ByteBuffer buffer = ByteBuffer.allocateDirect( Yb + Ub + Vb);
buffer.put(Y.getBuffer());
buffer.put(U.getBuffer());
buffer.put(V.getBuffer());
// Image is 640 x 480
Mat yuvMat = new Mat(960, 640, CvType.CV_8UC1);
yuvMat.put(0, 0, buffer.array());
// I don't know what is the correct format
Mat rgbMat = new Mat(yuvMat.rows, yuvMat.cols, CvType.CV_8UC4);
Imgproc.cvtColor(yuvMat, rgbMat, Imgproc.COLOR_YUV420sp2RGBA);
final Bitmap bit = Bitmap.createBitmap(rgbMat.cols(), rgbMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(rgbMat, bit);
其实我得到的只是裁剪后的灰度图
【问题讨论】:
解决坦克到answers.opencv.org/question/61628/… 【参考方案1】:试试这个功能:
void decodeYUV420SP( byte[] rgb, byte[] yuv420sp, int width, int height )
final int frameSize = width * height;
for (int j = 0, yp = 0; j < height; j++)
int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
for (int i = 0; i < width; i++, yp++)
int y = (0xff & ((int) yuv420sp[yp])) - 16;
if (y < 0)
y = 0;
if ((i & 1) == 0)
v = (0xff & yuv420sp[uvp++]) - 128;
u = (0xff & yuv420sp[uvp++]) - 128;
int y1192 = 1192 * y;
int r = (y1192 + 1634 * v);
int g = (y1192 - 833 * v - 400 * u);
int b = (y1192 + 2066 * u);
if (r < 0) r = 0; else if (r > 262143)
r = 262143;
if (g < 0) g = 0; else if (g > 262143)
g = 262143;
if (b < 0) b = 0; else if (b > 262143)
b = 262143;
//rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);
int nIdx = ((width - i - 1) * height + height - j - 1) * 3;//device
//int nIdx = (i * height + j) * 3;//nox
rgb[nIdx] = (byte) (((r << 6) & 0xff0000)>>16);
rgb[nIdx+1] = (byte) (((g >> 2) & 0xff00)>>8);
rgb[nIdx+2] = (byte) ((b >> 10) & 0xff);
使用:decodeYUV420SP(rgb, camData, nWidth234, nHeight234);
可以得到RGB字节数组;
如果你需要从字节数组中获取图片,试试这个。
public boolean convertYunToJpeg(byte[] data, int width, int height)
YuvImage image = new YuvImage(data, ImageFormat.NV21, width, height, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int quailty = 20;
image.compressToJpeg(new Rect(0,0, width, height), quailty, baos);
byte[] jpegByteArray = baos.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(jpegByteArray, 0, jpegByteArray.length);
Matrix matrix = new Matrix();
matrix.postRotate(-90);
Bitmap lastbitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
try
File file = new File(BaseApplication.DIRECTORY + mCode + ".png");
if(!file.exists())
RandomAccessFile me = new RandomAccessFile(BaseApplication.DIRECTORY + mCode + ".png", "rw");
me.writeInt(5);
me.close();
file = new File(BaseApplication.DIRECTORY + mCode + ".png");
FileOutputStream fos = new FileOutputStream(file);
lastbitmap.compress(Bitmap.CompressFormat.PNG, quailty, fos);
catch (IOException e)
e.printStackTrace();
return false;
return true;
【讨论】:
这是旧版相机引擎,而不是 camera2以上是关于使用 OpenCV 从 android Camera2 将 YUV 转换为 RGB ImageReader 时出现问题,输出图像为灰度的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 OpenCV 从 C++ 程序制作 Android 应用程序
使用 OpenCV Python 从 Android 智能手机捕获视频
Android - 从图像中裁剪文本(使用 openCV 或其他任何东西)
OpenCV,Android:从图像中检测对象而不是实时检测