#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