Санкт-Петербургский государственный университет
Опубликован: 14.07.2013 | Доступ: свободный | Студентов: 510 / 180 | Длительность: 06:03:00
Специальности: Программист
Самостоятельная работа 6:

Разработка ПО бортового микрокомпьютера БПЛА: получения и записи данных от видеокамеры, передача файлов по сети"

< Лекция 6 || Самостоятельная работа 6
Аннотация: Демонстрация процесса разработки практического приложения, позволяющего получать фотографии со встроенной фотокамеры и записывать их в заданную нами папку на внешнюю память мобильного устройства.

12.1. Цель лабораторной работы

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

12.2. Инструкция по выполнению лабораторной работы

Задача видеонаблюдения естественным образом распадается на составные части (рис. 12.1). Во-первых, нам нужно уметь подключаться к Интернету с помощью GSM-модема. Во-вторых, мы должны научиться получать кадр от камеры и сохранять его в формате JPG. В-третьих, нам нужен механизм для приема данных на ЦОД. Эти подзадачи независимы друг от друга.


Рис. 12.1.

Одним из стандартных датчиков получения данных из внешней среды на различных мобильных устройствах - фотокамера. Сейчас такие камеры имеют миниатюрный размер, высокое разрешение фото и видео съёмки. В основном такие камеры были доступны только как встроенная опция в мобильных устройствах. В последнее, время все чаще встречаются цифровые миниатюрные фотокамеры, как самостоятельное устройство или внешнее дополнение. 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. Задания для самостоятельной работы

  1. Изменить разрешение получаемого кадра в формате .jpg.
  2. Создать новую папку для записи кадров.
  3. Ввести функцию вспышки для камеры.
  4. Ввести функцию определения лица.

12.4. Выводы

Рассмотрен пример разработки прототипа практического приложения по захвату видеокадров, сохранению их и записи в формате .jpg на внешний носитель.

< Лекция 6 || Самостоятельная работа 6