Обработка кадров с камеры Android в режиме реального времени

#android #image-processing #camera

#Android #обработка изображений #камера

Вопрос:

Я пытаюсь создать приложение для Android, которое будет обрабатывать кадры с камеры в режиме реального времени. Для начала я просто хочу отобразить версию того, что видит камера, в оттенках серого. Мне удалось извлечь соответствующие значения из массива байтов в onPreviewFrame методе. Ниже приведен лишь фрагмент моего кода:

 byte[] pic;
int pic_size;
Bitmap picframe;
public void onPreviewFrame(byte[] frame, Camera c)
{
    pic_size = mCamera.getParameters().getPreviewSize().height * mCamera.getParameters().getPreviewSize().width;
    pic = new byte[pic_size];
    for(int i = 0; i < pic_size; i  )
    {
        pic[i] = frame[i];
    }
    picframe = BitmapFactory.decodeByteArray(pic, 0, pic_size);
}
  

Первыми [width*height] значениями byte[] массива кадров являются значения яркости (оттенки серого). Как мне отобразить их на экране в виде изображения после их извлечения? Это также не 2D-массив, так как же мне указать ширину и высоту?

Ответ №1:

Вы можете получить подробные рекомендации из OpenCV4Android SDK. Ознакомьтесь с их доступными примерами, в частности Tutorial 1 Basic. 0 Android Camera

Но, как и в моем случае, при интенсивной обработке изображений это будет происходить медленнее, чем приемлемо для приложения для обработки изображений в режиме реального времени. Хорошая замена их onPreviewFrame преобразованию массива байтов в YuvImage:

YuvImage yuvImage = new YuvImage(frame, ImageFormat.NV21, width, height, null);

Создайте прямоугольник того же размера, что и изображение.

Создайте ByteArrayOutputStream и передайте это, прямоугольник и значение сжатия в compressToJpeg():

ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvimage.compressToJpeg(imageSizeRectangle, 100, baos);

byte [] imageData = baos.toByteArray();

Bitmap previewBitmap = BitmapFactory.decodeByteArray(imageData , 0, imageData .length);

Рендеринг этих кадров предварительного просмотра на поверхности и использование лучших практик — это новое измерение. =)

Комментарии:

1. Происходит ли это для преобразования YUV-изображения в растровое изображение с промежуточным JPEG? Вряд ли это осуществимое решение в режиме реального времени

2. Я бы настоятельно не советовал этого делать. OpenCV на Android усложнит проект, а также потребует встроенных библиотек размером около 10 мб. Android обладает всеми возможностями для выполнения того, что требуется для операционной системы. OpenCV — отличная библиотека, но в данной ситуации она излишня.

Ответ №2:

Теперь это очень старое сообщение привлекло мое внимание.

API, доступный в ’11, был гораздо более ограниченным. Сегодня можно использовать SurfaceTexture (см. пример) для предварительного просмотра потока с камеры после (некоторых) манипуляций.

Ответ №3:

Это непростая задача при наличии текущих инструментов / API для Android. В целом, обработку изображений в реальном времени лучше выполнять на уровне NDK. Чтобы просто отображать черно-белое изображение, вы все равно можете сделать это на Java. Массив байтов, содержащий данные кадра, представлен в формате YUV, где плоскость Y стоит первой. Итак, если вы получаете только плоскость Y (первые байты ширины x высоты), это уже дает вам черно-белое изображение.

Я добился этого благодаря обширной работе и испытаниям. Вы можете просмотреть приложение в Google: https://play.google.com/store/apps/details?id=com.nm.camerafx