目录
ImageReader 直接保存图片,没成功,格式是yuv420,需要转换
读取图片,转opencvmat
在Android开发中,如果你想要将ImageReader读取的图像数据传递给C++层的OpenCV库进行处理,你需要执行以下步骤:
从ImageReader获取Image对象。
将Image对象的数据转换为适合OpenCV处理的格式,通常是Mat对象。
将转换后的数据传递给C++层。
以下是这个过程的一个简化示例:
步骤 1:从ImageReader获取图像
ImageReader imageReader = ImageReader.newInstance(WIDTH, HEIGHT, ImageFormat.YUV_420_888, 16);
Image image = imageReader.acquireLatestImage();
步骤 2:将Image转换为OpenCV的Mat
Image对象中的数据是以YUV_420_888格式存储的。你需要将它转换为OpenCV能够理解的格式,通常是RGB或BGR。以下是转换的一个示例:
// 获取YUV数据的三个平面
ByteBuffer yBuffer = image.getPlanes()[0].getBuffer();
ByteBuffer uBuffer = image.getPlanes()[1].getBuffer();
ByteBuffer vBuffer = image.getPlanes()[2].getBuffer();
// 获取对应的步长
int ySize = yBuffer.remaining();
int uSize = uBuffer.remaining();
int vSize = vBuffer.remaining();
// 将YUV数据转换为字节数组
byte[] nv21 = new byte[ySize + uSize + vSize];
// Y
yBuffer.get(nv21, 0, ySize);
// U (VU data is interleaved)
uBuffer.get(nv21, ySize, uSize);
// V
vBuffer.get(nv21, ySize + uSize, vSize);
// 用于存储转换后的RGB数据的Mat
Mat rgbMat = new Mat(HEIGHT + HEIGHT / 2, WIDTH, CvType.CV_8UC1);
rgbMat.put(0, 0, nv21);
// 将NV21转换为RGB格式
Imgproc.cvtColor(rgbMat, rgbMat, Imgproc.COLOR_YUV2RGB_NV21, 3);
ImageReader 直接保存图片,没成功,格式是yuv420,需要转换
// 创建一个ImageReader对象
ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);
reader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = null;
try {
image = reader.acquireLatestImage();
if (image != null) {
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
saveImage(bytes);
}
} finally {
if (image != null) {
image.close();
}
}
}
}, handler);
// 保存图片
private void saveImage(byte[] bytes) {
File file = new File(Environment.getExternalStorageDirectory() + "/picture.jpg");
FileOutputStream output = null;
try {
output = new FileOutputStream(file);
output.write(bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != output) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
转opencv
Image image = imageReader.acquireLatestImage();
Plane[] planes = image.getPlanes();
ByteBuffer bufferY = planes[0].getBuffer();
ByteBuffer bufferU = planes[1].getBuffer();
ByteBuffer bufferV = planes[2].getBuffer();
byte[] bytesY = new byte[bufferY.remaining()];
byte[] bytesU = new byte[bufferU.remaining()];
byte[] bytesV = new byte[bufferV.remaining()];
bufferY.get(bytesY);
bufferU.get(bytesU);
bufferV.get(bytesV);
c++部分:
cv::Mat imgY(height, width, CV_8UC1, bytesY);
cv::Mat imgU(height, width, CV_8UC1, bytesU);
cv::Mat imgV(height, width, CV_8UC1, bytesV);
c++部分:
cv::Mat imgYUV;
cv::merge(std::vector<cv::Mat>{imgY, imgU, imgV}, imgYUV);
cv::Mat imgRGB;
cv::cvtColor(imgYUV, imgRGB, cv::COLOR_YUV2RGB);
nv21保存图片,测试ok
Yuv2Rgb.nativeNV21ToARGB8888(nv21, data, width[0], height[0]);
long t2 = System.currentTimeMillis();
// 假设你已经有了一个ARGB_8888格式的图像,存储在一个名为pixels的int数组中
int width = 1920;
int height = 1080;
String file_name="/storage/emulated/0/Android/data/com.sandstar.jupiter.terminal.algor/files/"+mCameraId+"/"+frameIdx+"_b.jpg";
YuvImage yuvImage = new YuvImage(nv21, ImageFormat.NV21, width, height, null);
try {
// 创建一个输出流来保存图片
FileOutputStream outStream = new FileOutputStream(file_name);
// 将YuvImage转换为JPEG,并保存到输出流中
yuvImage.compressToJpeg(new Rect(0, 0, width, height), 100, outStream);
// 关闭输出流
outStream.close();
} catch (IOException e) {
e.printStackTrace();
}
rgb888 data保存图片:
Yuv2Rgb.nativeNV21ToARGB8888(nv21, data, width[0], height[0]);
// Create a Bitmap from the ARGB8888 data
Bitmap bitmap = Bitmap.createBitmap(data, width[0], height[0], Bitmap.Config.ARGB_8888);
// Save the Bitmap as a JPEG file
FileOutputStream fos = null;
try {
fos = new FileOutputStream("/path/to/your/file.jpg");
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}