2015-09-05 7 views
8

Я пытаюсь получить изображение рамки для обработки, используя новое мобильное зрение apif.Как создать растровое изображение из изображения в виде гранулированного байтового буфера?

Итак, я создал пользовательский детектор, чтобы получить Frame и попытался вызвать метод 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); 
}} 
+0

Кадр не имеет растровых данных, поскольку он поступает непосредственно с камеры. Формат изображения с камеры - NV21: http://developer.android.com/reference/android/graphics/ImageFormat.html#NV21 – pm0733464

ответ

11

Вы, наверное, отсортированный это уже, но в случае, если кто-то натыкается на этот вопрос в будущем, вот как я ее решил:

Как @ pm0733464 указывает, по умолчанию формат изображения подходит из android.hardware.Camera является NV21, и это тот, который используется CameraSource.

This 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 изначально.

+0

Это отлично работает. Во всяком случае, я мог только обрезать лицо, а не целое изображение? – 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); 
    } 
}