如何从灰度字节缓冲区图像创建位图?
How to create Bitmap from grayscaled byte buffer image?
我正在尝试在使用新的 Android 人脸检测移动视觉 api 时获取帧图像进行处理 api。
所以我创建了自定义检测器来获取 Frame 并尝试调用 getBitmap() 方法但它为空,所以我访问了帧的灰度数据。有没有办法从它或类似的图像持有者创建位图 class?
public class CustomFaceDetector extends Detector<Face> {
private Detector<Face> mDelegate;
public CustomFaceDetector(Detector<Face> delegate) {
mDelegate = delegate;
}
public SparseArray<Face> detect(Frame frame) {
ByteBuffer byteBuffer = frame.getGrayscaleImageData();
byte[] bytes = byteBuffer.array();
int w = frame.getMetadata().getWidth();
int h = frame.getMetadata().getHeight();
// Byte array to Bitmap here
return mDelegate.detect(frame);
}
public boolean isOperational() {
return mDelegate.isOperational();
}
public boolean setFocus(int id) {
return mDelegate.setFocus(id);
}}
你可能已经解决了这个问题,但如果将来有人偶然发现这个问题,我是这样解决的:
正如@pm0733464 所指出的,android.hardware.Camera
的默认图像格式是 NV21,CameraSource.
使用的是 NV21
This Whosebug 答案提供了答案:
YuvImage yuvimage=new YuvImage(byteBuffer, ImageFormat.NV21, w, h, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvimage.compressToJpeg(new Rect(0, 0, w, h), 100, baos); // Where 100 is the quality of the generated jpeg
byte[] jpegArray = baos.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(jpegArray, 0, jpegArray.length);
虽然 frame.getGrayscaleImageData()
建议 bitmap
将是原始图像的灰度版本,但根据我的经验,情况并非如此。事实上,位图与本机提供给 SurfaceHolder
的位图相同。
只需添加一些额外的内容即可在检测区域的每一侧设置一个 300px 的框。顺便说一句,如果您不从元数据中将帧高度和宽度放入 getGrayscaleImageData() 中,您会得到奇怪的损坏位图。
public SparseArray<Barcode> detect(Frame frame) {
// *** crop the frame here
int boxx = 300;
int width = frame.getMetadata().getWidth();
int height = frame.getMetadata().getHeight();
int ay = (width/2) + (boxx/2);
int by = (width/2) - (boxx/2);
int ax = (height/2) + (boxx/2);
int bx = (height/2) - (boxx/2);
YuvImage yuvimage=new YuvImage(frame.getGrayscaleImageData().array(), ImageFormat.NV21, frame.getMetadata().getWidth(), frame.getMetadata().getHeight(), null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvimage.compressToJpeg(new Rect(by, bx, ay, ax), 100, baos); // Where 100 is the quality of the generated jpeg
byte[] jpegArray = baos.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(jpegArray, 0, jpegArray.length);
Frame outputFrame = new Frame.Builder().setBitmap(bitmap).build();
return mDelegate.detect(outputFrame);
}
public boolean isOperational() {
return mDelegate.isOperational();
}
public boolean setFocus(int id) {
return mDelegate.setFocus(id);
}
}
我正在尝试在使用新的 Android 人脸检测移动视觉 api 时获取帧图像进行处理 api。
所以我创建了自定义检测器来获取 Frame 并尝试调用 getBitmap() 方法但它为空,所以我访问了帧的灰度数据。有没有办法从它或类似的图像持有者创建位图 class?
public class CustomFaceDetector extends Detector<Face> {
private Detector<Face> mDelegate;
public CustomFaceDetector(Detector<Face> delegate) {
mDelegate = delegate;
}
public SparseArray<Face> detect(Frame frame) {
ByteBuffer byteBuffer = frame.getGrayscaleImageData();
byte[] bytes = byteBuffer.array();
int w = frame.getMetadata().getWidth();
int h = frame.getMetadata().getHeight();
// Byte array to Bitmap here
return mDelegate.detect(frame);
}
public boolean isOperational() {
return mDelegate.isOperational();
}
public boolean setFocus(int id) {
return mDelegate.setFocus(id);
}}
你可能已经解决了这个问题,但如果将来有人偶然发现这个问题,我是这样解决的:
正如@pm0733464 所指出的,android.hardware.Camera
的默认图像格式是 NV21,CameraSource.
This Whosebug 答案提供了答案:
YuvImage yuvimage=new YuvImage(byteBuffer, ImageFormat.NV21, w, h, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvimage.compressToJpeg(new Rect(0, 0, w, h), 100, baos); // Where 100 is the quality of the generated jpeg
byte[] jpegArray = baos.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(jpegArray, 0, jpegArray.length);
虽然 frame.getGrayscaleImageData()
建议 bitmap
将是原始图像的灰度版本,但根据我的经验,情况并非如此。事实上,位图与本机提供给 SurfaceHolder
的位图相同。
只需添加一些额外的内容即可在检测区域的每一侧设置一个 300px 的框。顺便说一句,如果您不从元数据中将帧高度和宽度放入 getGrayscaleImageData() 中,您会得到奇怪的损坏位图。
public SparseArray<Barcode> detect(Frame frame) {
// *** crop the frame here
int boxx = 300;
int width = frame.getMetadata().getWidth();
int height = frame.getMetadata().getHeight();
int ay = (width/2) + (boxx/2);
int by = (width/2) - (boxx/2);
int ax = (height/2) + (boxx/2);
int bx = (height/2) - (boxx/2);
YuvImage yuvimage=new YuvImage(frame.getGrayscaleImageData().array(), ImageFormat.NV21, frame.getMetadata().getWidth(), frame.getMetadata().getHeight(), null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvimage.compressToJpeg(new Rect(by, bx, ay, ax), 100, baos); // Where 100 is the quality of the generated jpeg
byte[] jpegArray = baos.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(jpegArray, 0, jpegArray.length);
Frame outputFrame = new Frame.Builder().setBitmap(bitmap).build();
return mDelegate.detect(outputFrame);
}
public boolean isOperational() {
return mDelegate.isOperational();
}
public boolean setFocus(int id) {
return mDelegate.setFocus(id);
}
}