Разработка ПО бортового микрокомпьютера БПЛА: получения и записи данных от видеокамеры, передача файлов по сети"
12.1. Цель лабораторной работы
Демонстрация процесса разработки практического приложения, позволяющего получать фотографии со встроенной фотокамеры и записывать их в заданную нами папку на внешнюю память мобильного устройства.
12.2. Инструкция по выполнению лабораторной работы
Задача видеонаблюдения естественным образом распадается на составные части (рис. 12.1). Во-первых, нам нужно уметь подключаться к Интернету с помощью GSM-модема. Во-вторых, мы должны научиться получать кадр от камеры и сохранять его в формате JPG. В-третьих, нам нужен механизм для приема данных на ЦОД. Эти подзадачи независимы друг от друга.
Одним из стандартных датчиков получения данных из внешней среды на различных мобильных устройствах - фотокамера. Сейчас такие камеры имеют миниатюрный размер, высокое разрешение фото и видео съёмки. В основном такие камеры были доступны только как встроенная опция в мобильных устройствах. В последнее, время все чаще встречаются цифровые миниатюрные фотокамеры, как самостоятельное устройство или внешнее дополнение. OC Android обладает всеми необходимыми библиотеками для работы с фотокамерами, а также, для работы с памятью куда можно записать накопленные данные.
В этой лабораторной работы мы будем использовать встроенную фотокамеру и внутреннюю память мобильного устройства, посмотрим, как подключать необходимые нам устройства в приложение и каким образом использовать нужные нам библиотеки в коде. Для этого потребуются необходимые базовые знания языка Java, знакомство c Android SDK и необходимыми методами и классами. В качестве одной из составляющих приложения будут использованы материалы лабораторной работы "Захват видеоизображения" из первой части курса. Также необходимо мобильное устройство (планшет, коммуникатор, нетбук и т.п.), работающий под управлением OC Android. Нами использовался планшет компании Intel с ОС Android 4.0.
Задача состоит из трех частей - получение кадра от камеры, сжатие кадра в формат jpeg, запись полученного кадра в памяти мобильного устройства.
Для начала работы необходимо запустить Eclipse SDK, создать новое рабочее пространство (например, android_camera), и создать новый проект Android Application Project. Для этого необходимо зайти во вкладку File и перейти в New -> Android Application Project. Далее необходимо задать название приложения, версию Android и запустить проект. Мы будем работать с уже созданным нами проектом ImageUploader. Для этого необходимо войти File -> Import -> и выбрать папку с проектом. Далее опишем, какие необходимые элементы программного кода нашего примера относятся непосредственно к работе с фотокамерой и памятью.
Для начала в проекте необходимо прописать то оборудование, которое будет задействовано в приложении и его дополнительные функции. Для этого необходимо открыть файл AndroidMonifest.xml и внести следующие строки:
1. <uses-sdk 2. android:minSdkVersion="8" 3. android:targetSdkVersion="14" /> 4. <uses-permission android:name="android.permission.CAMERA" /> 5. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 6. <uses-feature android:name="android.hardware.camera" /> 7. <uses-feature android:name="android.hardware.camera.autofocus" />
В первой, второй и третьей строчке описывается версии минимальной SDK и той, для которой предназначено приложение. Далее необходимо установить "разрешения" на использования того или иного устройства - permission. Строки 4 и 5 являются запросами на "разрешения" для использования фотокамеры и внешнего носителя. В строках 6 и 7 прописаны функции камеры. Если вы планируете, что приложение будет работать с соответствующим оборудованием и его определенными функциями, то функции указываются без дополнительных условий. Если же вы хотите чтобы ваше приложение также запускалось на устройствах, которые не имеет указанных устройств и функций, то в соответствующей строке необходимо прописать:
……………………………android:required="false" />
после указания функции. В данном примере мы хотим воспользоваться камерой и функцией автофокус.
Для того чтобы начать использовать камеру необходимо получить доступ к ней. Для этого необходимо воспользоваться Camera.open( ) . В нашем примере часть кода работы с камерой такой
1. public boolean openCam() { 2. try { 3. camera = Camera.open(); 4. Camera.Parameters parameters = camera.getParameters(); 5. parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); 6. if (focusBox.isChecked()) 7. parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); 8. else 9. parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY); 10. parameters.setJpegQuality(95); 11. List<Camera.Size> psizes = parameters.getSupportedPictureSizes(); 12. int w=0; 13. int h=0; 14. for (int i=0; i < psizes.size(); i++) { 15. if (w < psizes.get(i).width && h < psizes.get(i).height) { 16. w = psizes.get(i).width; 17. h = psizes.get(i).height; 18. } 19. } 20. log ("Picture size: "+String.format("%dx%d", w, h)); 21. parameters.setPictureSize(w,h); 22. camera.setParameters(parameters); 23. camera.setPreviewDisplay(fakeView.getHolder()); 24. } catch (Exception e) { 25. e.printStackTrace(); 26. log("Camera open fail:"+e.toString()); 27. closeCam(); 28. return false; 29. } 30. return true; 31. }
В начале, мы указывает на инициализацию и начала работы с камерой. В строках с 4 по 23 мы указываем параметры работы камеры и параметры получаемых нами данных в зависимости от того, какие данные нам необходимы. В нашем примере это: работа без вспышки, с автофокумом, данные в формате jpeg. При не правильной работе камеры или её отсутствии программа сообщает нам об этом "Camera open fail".
Далее в примере описывается еще две функции камеры - остановка работы камеры closeCam( ) и takePhoto( ). Эти классы вызываются по средством нажатия заданных ранее кнопок. Сам код такой:
1. public void closeCam() { 2. if (camera != null) { 3. camera.stopPreview(); 4. camera.release(); 5. camera = null; 6. log("Release camera"); 7. } 8. } 9. 10. private void takePhoto(){ 11. if (previewStarted) { 12. log("Skip photo, wait previous..."); 13. return; 14. } 15. if (camera == null) { 16. log("Camera not initialized..."); 17. return; 18. } 19. previewStarted = true; 20. camera.startPreview(); 21. camera.takePicture(null, null, jpegCallback); 22. }
где с 1 по 8 строку - команда остановки работы камеры, а с 9 по 22 - команда сделать фото в формате jpeg.
Далее необходимо указать, что делать с данными полученными с камеры. В нашем пример, мы конвертируем данные в формат jpeg с разными параметрами "small" и "big", даем им имена и записываем их в две разных папки. Мы делаем два размера для получения фотографий предварительного просмотра, а также для возможной их отправки через Internet.
1. PictureCallback jpegCallback = new PictureCallback() { 2. public void onPictureTaken(byte[] data, Camera camera) { 3. FileOutputStream outStream = null; 4. String filename = String.format(imageDir + File.separator + "big" + File.separator + "%d.jpg", 5. System.currentTimeMillis()/1000); 6. String filename2 = String.format(imageDir + File.separator + "small" + File.separator + "%d.jpg", 7. System.currentTimeMillis()/1000); 8. String gps = "No"; 9. try { 10. outStream = newFileOutputStream(filename); 11. outStream.write(data); 12. outStream.close(); 13. Bitmap origImage = BitmapFactory.decodeByteArray(data, 0,data.length); 14. int origHeight = origImage.getHeight(); 15. int origWidth = origImage.getWidth(); 16. double scale = (origHeight>origWidth?origHeight:origWidth)/300; 17. int newHeight = (int)(origHeight/scale); 18. int newWidth = (int)(origWidth/scale); 19. Bitmap smallImage = Bitmap.createScaledBitmap(origImage, newWidth, newHeight, false); 20. origImage.recycle(); 21. int quality = 75; 22. outStream = new FileOutputStream(filename2); 23. BufferedOutputStream bos = new BufferedOutputStream(outStream); 24. smallImage.compress(CompressFormat.JPEG, quality, bos); 25. smallImage.recycle(); 26. bos.close(); 27. };
В строках с 1 по 8 описывается место, где необходимо брать исходные данные файла "карта в битах", и каким образом формировать название файла. В строках с 9 по 27 указывается, что необходимо сделать с данными и куда их записать. В примере, исходные данные берутся с камеры, название формируется исходя из номера фотографии, и записывается на карту памяти в формате .jpg.
12.3. Задания для самостоятельной работы
- Изменить разрешение получаемого кадра в формате .jpg.
- Создать новую папку для записи кадров.
- Ввести функцию вспышки для камеры.
- Ввести функцию определения лица.
12.4. Выводы
Рассмотрен пример разработки прототипа практического приложения по захвату видеокадров, сохранению их и записи в формате .jpg на внешний носитель.