如何从灰度字节缓冲图像创建位图?

9

我正在尝试使用新的Android人脸检测移动视觉API获取框架图像以进行处理。

因此,我创建了自定义检测器来获取框架并尝试调用getBitmap()方法,但它为null,因此我访问了框架的灰度数据。是否有一种方法可以从中创建位图或类似的图像持有者类?

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);
}}

该帧没有位图数据,因为它直接来自相机。相机的图像格式为NV21:http://developer.android.com/reference/android/graphics/ImageFormat.html#NV21 - pm0733464
2个回答

12
< p >< em >你可能已经解决了这个问题,但以防未来某个时候有人偶然遇到这个问题,下面是我解决它的方法:

正如 @pm0733464 所指出的那样,android.hardware.Camera 的默认图像格式是 NV21,这也是 CameraSource 使用的格式。

这个 stackoverflow 答案提供了答案:

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的位图是相同的。

这个很好用。不过我能否只裁剪出脸而不是整张图片? - Andro

0

只需添加一些额外的内容,为检测区域的每个边设置一个300像素的框。顺便说一句,如果您在从元数据中获取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);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接