Разработка ПО бортового микрокомпьютера БПЛА: получения и записи данных от видеокамеры, передача файлов по сети"
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 на внешний носитель.
