Как стать автором
Обновить
0

Образец кода Enhanced Photography для камеры Intel RealSense R200

Время на прочтение 25 мин
Количество просмотров 2.8K
Автор оригинала: Rick Blacker


В этом документе и в образце приложения я продемонстрирую использование камеры Intel RealSense R200 и функциональности Enhanced Photography, входящей в состав Intel RealSense SDK.

Требования


Требования к оборудованию

  • Процессор Intel Core 4-го поколения (на основе микроархитектуры Haswell)
  • 8 ГБ свободного места на жестком диске
  • Камера Intel RealSense R200
  • Порт USB 3.0 для подключения камеры

Требования к программному обеспечению

  • 64-разрядная версия операционной системы Microsoft * 8.1 или более поздней версии
  • Microsoft Visual Studio * 2010–2015 с последней версией пакета обновления
  • Microsoft .NET * 4.0 Framework для разработки на C#
  • Пакет Intel RealSense SDK, который можно загрузить здесь

Примечание. Этот конкретный пример проекта был создан в Visual Studio 2015 с помощью последнего выпуска .NET.

Структура проекта


В этом примере приложения я отделил функциональность Intel RealSense SDK от кода уровня графического пользовательского интерфейса, чтобы разработчикам было удобнее сосредоточиться на функциональности, относящейся к расширенным возможностям съемки Enhanced Photography камеры R200. Для этого я создал следующие классы-оболочки C#.

  • RSStreaming. Оболочка для поточной функциональности Intel RealSense SDK.
  • RSEnhancedPhotography. Оболочка для функциональности Enhanced Photography Intel RealSense SDK.

Кроме того, для простоты я создал отдельные формы WinForms для каждого типа функций Enhanced Photography. При этом образуется некоторое количество повторяющегося кода, но зато обеспечивается ясность при демонстрации каждой функции Enhanced Photography.

Структура проекта содержит и другие элементы, помимо описанных здесь. Я подробнее разберу все файлы исходного кода и их работы далее в этом документе.

Я создаю собственные события, чтобы продемонстрировать, как в наибольшей возможной степени отделить функциональность Intel RealSense SDK от исходного кода графического пользовательского интерфейса. Такое решение мне представляется более «чистым» по сравнению с передачей целой формы в класс, чтобы этот класс смог получить доступ к свойствам в форме.

Кроме того, имейте в виду, что этот пример приложения вовсе не является эталоном идеального программного кода. Проверок во время выполнения почти нет, отсутствуют блоки try/catch. Я стремился сделать простой и понятный пример с ясным кодом, поэтому старался по возможности избавить код от дополнительных конструкций.

Формы в примере приложения не слишком изящны, но вполне выполняют свою задачу: демонстрируют, как использовать Enhanced Photography.

Структура проекта Visual Studio



На приведенном выше рисунке показано решение в Visual Studio 2015. Различные папки содержат следующее.

  • Forms. Различные формы WinForms, демонстрирующие разные функции Enhanced Photography.
  • Source. Исходный код, распространяемый вместе с проектом.
  • Source\CustomEventArgs. Содержит классы, производные от собственного класса EventArgs.
  • MainForm.CS. Основная форма приложения.


Простая общая схема последовательности





При запуске примера приложения отображается форма FormMain. В этой форме можно начать поточную передачу, нажав кнопку Streaming . Когда эта кнопка нажата, приложение запускает поточную передачу, используя функциональность класса RSStreaming.

Класс RSStreaming постоянно обновляет форму FormMain, вызывая ее внутреннее событие OnNewStreamingSample. Это делается для каждого кадра, поступающего с камеры.

Можно остановить поточную передачу, нажав кнопку Stop Streaming . После этого поточная передача просто прекращается, нет никаких других доступных команд, кроме как снова включить ее. Если же нажать кнопку Photo , данные изображения сохраняются на диск и поточная передача прекращается. После остановки поточной передачи и сохранения фотографии на диске становятся активными кнопки изменения фотографии. С их помощью можно выбрать один из диалогов Enhanced Photography, демонстрирующий возможности, реализованные в этом примере приложения.

Если выбрать одно из диалоговых окон Enhanced Photo, загружается и используется пример изображения, сохраненный на диске. Более подробно это поясняется далее в документе.

Разбор кода


В следующих разделах описываются все приложение и ход его работы, приводится описание различных классов.

Формы


FormDepthEnhance. Демонстрирует использование двух разных параметров качества глубины для показа данных глубины. Пользователь может выбрать низкое или высокое качество.



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



FormDepthRefocus. В этой форме показано, как щелкнуть в любой точке изображения и сделать изображение резким в этом месте, а остальная часть изображения размывается. Можно щелкнуть в любом месте изображения; место щелчка становится новой точкой фокусировки. Можно настроить имитируемую диафрагму объектива камеры, передвигая ползунок.



FormDepthResize. Здесь показана функциональность изменения размера: можно увеличить изображение глубины до размера цветного изображения.



FormMeasure. Здесь показано, как использовать функции измерения Enhanced Photography для получения значений расстояния, точности и достоверности.



FormMain. Это основная форма приложения. В ней пользователь может включить поточную передачу данных с камеры Intel RealSense, остановить поточную передачу и сделать снимок. Затем к полученному снимку можно применять различные функции Enhanced Photography.



Исходный код


RSEnhancedPhotography.CS. Это класс-оболочка, в который заключена вся функциональность Enhanced Photography камер Intel RealSense. Назначение этого класса в том, чтобы отделить как можно больше функций камеры Intel RealSense от уровня графического пользовательского интерфейса. Этот класс использует настраиваемые события для публикации данных в клиентском приложении. Класс RSEnhancedImageArg получает новое изображение, которое необходимо показать.

RSPaintUtil.CS. Это статический вспомогательный класс, использующийся для отрисовки точек щелчков мыши и линий в элементах управления PictureBox на C#.

RSPoints.CS. Этот вспомогательный класс заключает объекты точек PXCMPointI32 и создает функциональность для сохранения точек, проверки данных точек и передачи данных о точках, которые должны отображаться на экране.

RSStreaming.CS. Это класс-оболочка потока данных с камеры Intel RealSense. Он передает поток данных и публикует событие для клиента. Событие использует класс RSSampleArg для хранения данных, которые будут использоваться клиентом.

RSUtility.CS. Это статический класс, содержащий исходный код. Реализованная в нем функциональность не принадлежит ни к одному определенному классу.

Код Source\CustomEventArgs


RSEnhancedImageArg. Расширяет EventArgs, содержит объект PXCMImage. Этот объект будет содержать изображение, измененное с помощью функциональности Enhanced Photography в составе Intel RealSense SDK. Это изображение отображается в отдельных элементах управления PictureBox WinForms.

RSMeasureArg.CS. Расширяет EventArgs, содержит данные измерения, возвращенные функциональностью Enhanced Photography. Эти данные используются в форме WinForm FormMeasure, чтобы сообщить пользователю данные измерений.

RSSampleArg.CS. Расширяет EventArgs, содержит объект PXCMCapture.Sample. Этот объект содержит последний кадр, снятый камерой. Он используется для поточной передачи данных и для их отображения в форме WinForm FormMain.

Подробный анализ


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

RSStreaming


RSStreaming — класс-оболочка для поточной передачи Intel RealSense SDK. Этот класс не слишком сложный. Задача — привести простой пример поточной передачи данных с камеры Intel RealSense. Она может передавать поток изображения, а также сделать снимок и передать и то, и другое в клиент с помощью событий.

public event EventHandler<RSSampleArg> OnNewStreamingSample;

Как уже было сказано выше в этом документе, я использую события, чтобы отправлять данные клиентскому приложению (в формы). RSStreaming отправляет данные клиенту (в данном случае — в FormMain) с помощью события OnNewStreamingSample. Оно берет один параметр, RSSampleArg, который будет содержать самую последнюю выборку с камеры.

public bool Initialized

Флаг простого метода получения, указывающий, был ли инициализирован класс.

public bool IsStreaming

Простой флаг получения указывает, что класс в настоящее время ведет поточную передачу данных.

public void StartStreaming( )

Общая функция, которую клиент использует для запуска поточной передачи данных с камеры. Проверяет, был ли класс инициализирован должным образом. Если да, то вызывает функцию InitCamera() для инициализации камеры.

Хотелось бы отметить, что я использую одну функцию, которую обычно оставляют без внимания. Как вы, возможно, заметили, во множестве примеров поточной передачи обычно используются цикл while и функция AcquireAccess с каким-либо механизмом остановки передачи при помощи логического флага. В этом примере используется другой подход.

Мой подход отличается: я использую функцию StreamFrames в PXCMSenseManager. Она заставляет SenseManager запускать свой собственный внутренний поток и отправлять данные с помощью обработки событий. Это осуществляется путем назначения объекта PXCMSenseManager.Handler функции. Подробнее об этом — ниже в описании функции InitCamera().

private void InitCamera( )

InitCamera — закрытая функция, инициализирующая камеру и поточную передачу. Сначала мы создаем объекты PXCMSenseManager и PXCMSession. Затем нам нужна информация об устройстве (камере), которую мы получаем с помощью статической функции RSUtility GetDeviceByType(), передавая ей сеанс и нужный тип камеры.

Затем я создаю два объекта PXCMVideoModule.DataDesc, один — для потока цветного изображения, другой — для потока глубины. Затем я настраиваю каждый поток. После настройки потоков я даю PXCMSenseManager команду включить потоки.

Как было сказано в описании функции StartStreaming(), я использую подход на основе событий для управления передачей и получением данных. Для этого я создаю и инициализирую объект обработчика событий PXCMSenseManager.Handler и назначаю его функции OnNewSample. Каждый раз, когда камера снимает новый кадр, вызывается обработчик событий OnNewSample.

Затем я инициализирую SenseManager, отправляю его в объекте обработчика и даю команду использовать этот объект и его обработчик событий.

private pxcmStatus OnNewSample( int mid, PXCMCapture.Sample sample )

OnNewSample — обработчик событий для объекта PXCMSenseManager.Handler.

Параметры

  • Mid. Идентификатор потока. Если с помощью функции EnableVideoStream[s] запрошено несколько потоков, то это PXCCapture.CUID+0 или PXCCapture.CUID+1...
  • PXCMCapture.Sample. Образец изображения с камеры.

Когда эта функция вызывается, я получаю изображение из аргумента Sample и помещаю его в новый объект RSSampleArg, затем вызываю событие OnNewStreamingSample для этого класса. После этого событие уведомляет клиент FormMain о том, что новое изображение готово к показу.
Высвобождаем кадр и возвращаем нужный pxcmStatus, который в данном случае не используется.

public void StopStreaming( )

Прекращает поточную передачу, закрывая потоки и вызывая Dispose().

private void Dispose( )

Высвобождает ресурсы для сборки мусора.

RSEnhancedPhotography


Класс RSEnhancedPhotography был создан с целью заключить всю функциональность Enhanced Photography в один удобный для использования класс. Он работает по принципу событий. После обработки изображения создается событие, возвращающее только что созданное изображение или данные измерения клиентскому приложению или классу.

public RSEnhancedPhotography( PXCMPhoto photo )

Конструктор инициализирует некоторые глобальные переменные, используемые в классе. Единственный входной параметр — исходная фотография, снятая в главной форме. Он полностью инициализирован с данными изображения и используется для инициализации локального объекта _colorPhoto.

public void Dispose( )

Высвобождает память для сборщика мусора.

public void SendOriginalImage( )

Возвращает исходное изображение вызывающему приложению с помощью события OnImageProcessed.

public void MeasurePoints( RSPoints points )

MeasurePoints получает заполненный объект RSPoints. Сначала я проверяю, что в этом объекте действительно есть две точки: начальная и конечная. После этой проверки создается объект MeasureData, который отравляется в объекты PXCMEnhancedPhoto функции MeasureDistance.

Затем я беру данные из наполненного объекта measureData и наполняю объект RSMeasureArg. Обратите внимание на параметр (mesaureData.distance/10), преобразующий значение в сантиметры. После наполнения объекта arg я отправляю его клиенту посредством события OnImageMeasured.

public void RefocusOnPoint( RSPoints point, float aperture = 50 )

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

RefocusOnPoint работает точно так же. Эта функция дает возможность менять точку фокусировки на изображении.

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

RefocusOnPoint использует функцию DepthRefocus класса PXCMEnhancedPhotos для создания нового изображения с новым фокусом глубины, используя исходную цветную фотографию, точку, в которой зафиксирован щелчок пользователя, и значение диафрагмы. Получив PXCMPhoto, я получаю исходное изображение, вызвав QueryReferenceImage() и предоставив PXCMImage экземпляру RSEnahncedImageArg. После этого нужно лишь передать его обратно клиентскому приложению с помощью события OnImageProcessed.

public void DepthEnhancement( PXCMEnhancedPhoto.DepthFillQuality quality )

Улучшает или изменяет качество глубины изображения между двумя значениями: высоким или низким. Качество указывается параметром DepthFillQuality.

Сначала нужно инициализировать локальное изображение PXCMPhoto, вызвав функцию EnhanceDepth в PXCMEnhancedPhoto, предоставив исходное изображение PXCMPhoto и нужное качество.

Затем, чтобы инициализировать PXCMImage, я использую QueryDepthImage в enhancedPhoto, чтобы получить только что созданное изображение глубины.

После этого я создаю новый объект RSEnhancedImageArg для отправки клиенту с помощью OnImageProcessed.

public void DepthResize( )

Это упрощенный способ изменения размера изображения глубины. В данном случае размер изображения глубины становится таким же, как у цветного изображения в исходном объекте PXCMPhoto, созданном в конструкторе.

Сначала мне нужна информация о размере с цветной фотографии. Для этого я запрашиваю исходный объект PXCMPhoto, указанный в конструкторе. Затем я создаю экземпляр объекта PhotoUtils, содержащего функцию DepthResize. Получив размер исходного изображения, я сохраняю значения ширины и высоты в требуемом объекте PXCMSizeI32.

Далее следует несложный процесс: нужно дать PXCMEnhancedPhoto команду на изменение размера изображения, вызвав функцию DepthResize и указав объект PXCMPhoto и нужный размер.
После изменения размера все происходит обычным образом. Создаем изображение, опросив enhancedPhoto, наполняем RSEnhancedArg и отправляем его клиенту с помощью OnImageProcessed.

public void PastOnPlane( RSPoints points )

Эта функция показывает, как можно вставить изображение PXCMPhoto на плоскую поверхность. При этом вставляемое изображение адаптируется к окружающей обстановке. Например, если вставить изображение на стену, оно будет выглядеть вертикальным и находиться под одним и тем же углом. Если вставить изображение на поверхность стола, оно будет выглядеть так, как будто лежит на столе.

Сначала нужно убедиться в наличии двух допустимых точек, это необходимо для функциональности.
Затем загружаем изображение, которое нужно вставить, с помощью функции LoadBitmap в RSUtility.
Основным объектом для этого является класс PXCMEnhancedPhoto.Paster. Это новый класс в выпуске R5. В классе Paster есть функция PasteOnPlane, которая раньше была в классе PXCMEnhancedPhoto, а теперь перемещена в этот новый класс.

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

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

RSUtility


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

public static PXCMCapture.DeviceInfo GetDeviceByType(PXCMSession session, PXCMCapture.DeviceModel deviceType)

Это вспомогательная функция, предназначенная для получения подробной информации об устройстве, в данном случае — о камере R200. Эта функциональность продемонстрирована во множестве примеров RealSense.

Сначала мы задаем фильтр, указав, что нам нужен датчик в качестве основной группы, затем в качестве подгруппы мы указываем датчик видеозаписи.

В одной системе может быть несколько устройств, поэтому необходимо последовательно пройти все возможные устройства. Для каждой итерации я наполняю текущие данные PXCMSession.ImplDesc в объекте currentGroup. Если нет ошибки, переходим к следующему шагу, на котором наполняем объект PXCMCapture.

Подготовив объект PXCMCapture, я перебираю различные устройства, подключенные к этому объекту. Проверяю, совпадает ли информация о текущем устройстве с нужной нам камерой. Если да, цикл прерывается. Если нет, переходим к информации о следующем устройстве, подключенном к PXCMCapture, пока не будут проверены все устройства.

Когда устройство найдено, мы возвращаем его клиенту, которым в данном случае является объект RSStreaming.

public static Bitmap ToRGBBitmap( PXCMCapture.Sample sample )

Полиморфная функция просто вызывает ToRGBBitmap(изображение PXCMImage), передавая ему изображение примера аргумента.

public static Bitmap ToRGBBitmap( PXCMImage image )

Простая функция, использующая функциональность объектов PXCMImage для получения растровых данных с помощью объекта PXCMImage.ImageData. Данные извлекаются, сохраняются в растровом объекте .NET и возвращаются клиенту.

public static PXCMImage LoadBitmap( PXCMSession session )

Эта функция используется для поддержки PasteOnPlanes. Она загружает заранее заданный растровый рисунок в объект PXCMImage и возвращает его клиенту.

Сначала она получает путь к файлу и проверяет наличие файла. Если его нет, она возвращает значение null. Если файл существует, она создает новый растровый объект .NET, загружая его из файла.

Объект PXCMImage.ImageInfo используется для хранения базовой информации о растровом рисунке. Он используется при создании объекта PXCMImage. Это спецификации изображения, которое мы создадим.
Затем нам нужен объект PXCMImage.ImageData, содержащий данные фактического растрового рисунка. Объект .NET BitmapData создается и инициализируется с данными, описывающими формат и структуру нужных нам данных.

Дополнительные сведения о работе Bitmap.Lockbits см. здесь. Объект PXCMImage высвобождает доступ к данным изображения, чтобы освободить использованную память; растровое изображение разблокируется, PXCMImage возвращается клиенту.

public static int GetDepthAtClickPoint( PXCMPhoto photo, PXCMPointI32 point )

Эта функция принимает PXCMPhoto и PXCMPointI32.

public static bool SavePhoto( PXCMSession session, PXCMCapture.Sample sample )

Сохраняет фотографию на диск. Использует этот сеанс для создания нового объекта PXCMPhoto с функциональностью сохранения на диск. Объект PXCMPhoto использует импорт из примера предварительного просмотра, чтобы импортировать данные изображения в себя. Узнает, существует ли файл; если да, то удаляет его и сохраняет файл.

public static PXCMPhoto OpenPhoto( PXCMSession session )

Простая функция: проверяет, существует ли фотография XDM на жестком диске; если да, использует объект PXCMSession для создания PXCMPhoto. Затем объект photo загружает XDM-файл. Затем функция возвращает PXCMPhoto клиенту.

RSPaintUtil


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

Это удобная отправная точка. Если есть, создает новый объект .NET Point, указывая значения x, y начальной точки.

Вызывает функцию DrawCircle, чтобы нарисовать круг вокруг точки щелчка.

static public void DrawTwoPointsAndLine( RSPoints points, PaintEventArgs e )

Проверяет, что обе точки действительны, и создает два новых объекта .NET Point. Эта функция рисует круги в этих точках, вызывая DrawCircle для каждой точки. Затем между ними рисуется линия с помощью DrawLine.

static private void DrawCircle( Point p, PaintEventArgs e )

Эта функция рисует круг вокруг объекта .Net Point с координатами x, y. Это осуществляется путем создания нового объекта Pen. Чтобы нарисовать круг, нужен прямоугольник. Он определяет размер круга, который необходимо нарисовать. Для этого я создал функцию, которая рисует ограничивающий прямоугольник. После создания прямоугольника я использую функцию DrawEllipse и аргументы события рисования, чтобы нарисовать круг размером с прямоугольник.

static private void DrawLine( Point pointA, Point pointB, PaintEventArgs e )

Как и в случае с кругом, нужно создать объект .NET Pen, выбрать режим его работы и нарисовать линию между начальной и конечной точками, используя функцию DrawLine и аргументы события.

static public Rectangle BuildBoundingRectangle( Point p )

Создает объект прямоугольника .NET, центром которого является точка с координатами x, y в p. Для этого создается новый объект Rectangle. Я хотел, чтобы ограничительная рамка имела размер 10 x 10 пикселей. Значение 10 x 10 я выбрал произвольно.

RSPoints


RSPoints — простая оболочка для управления двумя разными возможными точками. Точки показывают место, где пользователь щелкнул фотографию PXCMPhoto, которая отображается в элементе управления .NET PictureBox.

Он использует два объекта PXCMPointI32, которые представляют начальную и конечную точки. В некоторых случаях экземпляру RSPoints потребуется только начальная точка, например для функциональности RefocusOnPoint. В других случаях две действительные точки необходимы для различных функций, таких как MeasurePoints, где нужны начальная и конечная точка.

Этот класс работает в двух режимах: в режиме одной точки, если осуществляются действия, для которых достаточно только одной допустимой точки, или в многоточечном режиме, если требуются доступные начальная и конечная точка, например для MeasurePoints.

public RSPoints( )

Конструктор включает режим одной точки, затем вызывает ResetPoints, чтобы обнулить все значения x, y.

public void AddPoint( int x, int y )

Это приблизительно то же самое, что добавить объект в массив или в список. Тем не менее, как видите, здесь нет ни массива, ни списка. Всего две точки. Я решил сделать этот класс подобным списку, поэтому решил добавить массив для точек. Хорошо ли продуман этот класс? Возможно, не очень, но пока меня это не слишком тревожит: это всего лишь поддерживающий класс, он делает то, что мне требуется, а прочее не столь важно.

В режиме одной точки AddPoints всегда заменяет начальную точку. Это осуществляется с помощью объекта ResetPoints.

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

RSSampleArg


RSSAmpleArg наследует от EventArgs. Этот класс предназначен для использования с RSStreaming. Когда RSStreaming ведет поточную передачу, экземпляр этого класса будет создаваться с каждым новым кадром и наполняться данными из камеры, затем передаваться клиенту с помощью класса событий.

public RSSampleArg( PXCMCapture.Sample sample )

Конструктор инициализирует локальный объект PXCMCapture.Sample _sample класса с этим параметром.

public PXCMCapture.Sample Sample

Простой метод получения возвращает локальный объект PXCMCapture.Sample.

RSEnhancedImageArg


RSEnhancedImageArg наследует от EventArgs. Этот класс предназначен для использования с RSEnhancedPhotography. После того как RSEnhancedPhotography завершает изменение изображения, создается экземпляр RSEnhancedImageArg, он наполняется только что созданным изображением и отправляется клиенту посредством класса событий, на которые подписан клиент.

public RSEnhancedImageArg( PXCMImage image )

Конструктор форм инициализирует единственную переменную в этом классе — объект PXCMImage.

public PXCMImage EnhancedImage

Простой метод получения возвращает экземпляр PXCMImage.

RSMeasureArg


RSMeasureArg наследует от EventArgs. Это событие используется в функции MeasurePoints классов RSEnhancedPhotography. После вычисления расстояния функцией MeasurePoints я использую экземпляр этого класса для сохранения в нем возвращаемых данных расстояния, достоверности и точности. После наполнения этого объекта он используется с объектом Event для отправки данных клиентскому приложению.

public RSMeasureArg(float distance, float confidence, float precision)

Параметры

  • Число с плавающей запятой. Измеренное расстояние между двумя точками.
  • Число с плавающей запятой. Уровень достоверности измерения в SDK.
  • Число с плавающей запятой. Уровень точности в SDK.

Конструктор наполняет локальные данные параметрами ввода.

public float Distance

Простой метод получения возвращает расстояние между двумя точками.

public float Confidence

Простой метод получения возвращает уровень достоверности, вычисленный при обработке расстояния между двумя точками в SDK.

public float Precision

Простой метод получения возвращает уровень точности, вычисленный при обработке расстояния между двумя точками в SDK.

FormMain


FormMain — это основная форма приложения. С ее помощью пользователь может включить и остановить поточную передачу, а также сделать снимок, который будет использован другими формами для различных функций Enhanced Photography.

В этой форме используется объект RSStreamingRGB для поточной передачи данных с камеры. После этого данные отображаются в элементе управления .NET PictureBox с помощью вспомогательного объекта Intel RealSense SDK под названием D2D1Render.

Форма получает обновления от RSStreamingRGB путем подписки на событие OnNewStreamingSample RSStreaming.

public MainForm( )

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

private void rsRGBStream_NewSample( object sender, RSSampleArg sampleArg )

Обработчик событий для объекта RSStreamingRGB. Проверяет, нужно ли просматривать цветное изображение и передает в объект _render соответствующую выборку.

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

private void btnStream_Click( object sender, EventArgs e )

Обработчик событий при нажатии кнопки Stream. Дает объекту RSStreamingRGB команду на начало поточной передачи, задает кнопки согласно состоянию приложения.

private void btnStopStream_Click( object sender, EventArgs e )

Обработчик событий кнопки Stop Streaming вызывает функцию StopStreaming.

private void btnTakeDepthPhoto_Click( object sender, EventArgs e )

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

private void EnableEnhancedPhotoButtons( bool enable )

Устанавливает кнопки в соответствии с состоянием приложения с помощью значения включения.
Возможно, эта функция вызовет у вас удивление, поскольку нет никакой многопоточной обработки. Не создано ни одного дополнительного потока. Зачем же я использую многопоточный синтаксис для обновления кнопок? Причина состоит в том, что хотя форма не запускает никакие потоки (как и RSStreamingRGB), но при этом есть еще один поток, выполняющийся отдельно.

Внутри функции StartStreaming в RSStreaming вы увидите строку кода.

_senseManager.StreamFrames( false );

Эта строка кода (встроенного в Intel RealSense SDK) на самом деле образует новый поток. Из-за этого нужно выразить эту функциональность с помощью многопоточного синтаксиса.

Сначала нужно проверить, требуется ли вызвать поле группы, окружающее различные кнопки улучшений. Это необходимо для работы с элементами управления Windows в многопоточных приложениях. Если это нужно, то следует создать новый делегат. В данном случае я создаю экземпляр делегата EnableEnhancedButtons, созданного в верхней части этого файла исходного кода. При создании экземпляра делегата необходимо указать имя функции, которую нужно вызвать. В данном случае это та же самая функция EnableEnhancedPhotobuttons. После создания делегата мы даем форме команду его вызвать и отправляем исходное логическое значение.

Когда делегат вызывает функцию, она на этот раз не пройдет тест InvokeRequired и попадет в инструкцию else, включающую поле группы вокруг кнопок улучшения изображения. Поле группы будет либо включено, либо отключено в зависимости от значения в логической переменной.

private void EnableStreamButtons( bool enable )

Это работает так же, как EnableEnhancedPhotoButtons, но с одним отличием: для включения и отключения используются разные элементы управления.

private void StopStreaming( )

Проверяет, что объект RSStreaming правильно инициализирован. Если да, вызывает функцию остановки поточной передачи. При этом прекращается поток данных с камеры и закрывается созданный ранее поток ЦП.

Затем я соответствующим образом задаю кнопки.

private void btnExit_Click( object sender, EventArgs e )

Обработчик событий нажатия кнопки Exit. Вызывает функцию Close() формы.

private void Form1_FormClosing(object sender, FormClosingEventArgs e)

Обрабатывает событие форм FormClosing. Проверяет, что объект RSStreaming правильно инициализирован. Если да, останавливает поточную передачу.

private void btnDepthResize_Click( object sender, EventArgs e )
private void btnDepthEnhance_Click( object sender, EventArgs e )
private void btnRefocus_Click( object sender, EventArgs e )
private void btnPasteOnPlane_Click( object sender, EventArgs e )
private void btnBlending_Click( object sender, EventArgs e )

Я сгруппировал все эти функции с одним пояснением. Они все делают одно и то же, за исключением того, что каждая функция инициализирует разную форму. В каждой функции я создаю новый объект сеанса, необходимый для функции RSUtility.OpenPhoto. Функция OpenPhoto открывает изображение, которое было создано и сохранено на диске. После получения фотографии я создаю новый объект формы, передаю ему фотографию, затем отображаю форму. Все достаточно просто.

private void btn_MouseEnter( object sender, EventArgs e )

Обработчик событий наведения указателя мыши на кнопки Start Streaming, Take Photo или Stop Streaming. Я получаю кнопку, на которую был наведен указатель, затем изучаю ее поле Tag. Определив, на какую кнопку был наведен указатель, я задаю значение текста полосы инструментов, чтобы указать назначение каждой кнопки.

private void btn_MouseLeave( object sender, EventArgs e )

Задает пустую строку в качестве текста полосы.

FormMeasure


FormMeasure демонстрирует, как использовать возможности измерения в Enhanced Photography. Экземпляр RSEnhancedPhotography обменивается данными с функциями Enhanced Photography в Intel RealSense SDK.

public FormMeasure( PXCMPhoto photo )

Конструктор форм. Принимает объект PXCMPhoto, содержащий изображение для измерения. Конструктор инициализирует все глобальные переменные в классе и регистрирует обработчик событий OnImageMeasured.

private void InitStatStrip( )

Создает записи по умолчанию для полосы состояния. Задает значения пустым строкам и 0, 0 для положений x, y.

private void rsEnhanced_OnImageMeasured(object sender, RSMeasureArg e)

Обработчик событий для события OnImageMeasured объекта RSEnhancedPhotography. Принимает RSMeasuredArg, содержащий информацию об измерении. Обновляет текстовые значения полосы состояния.

private void pictureBox1_MouseClick( object sender, MouseEventArgs e )

Обработчик событий щелчка мыши в поле с изображением. Обработчик событий сначала пытается определить, сколько щелчков мыши выбрано. Если нет начальной точки, мы знаем, что пользователь впервые щелкнул поле изображения/фотографии. В этом случае следует добавить точку щелчка. Если есть допустимая начальная точка, нужно проверить существование конечной точки. Если она не существует, добавьте ее.

После определения начальной и конечной точек я обновляют точки в полосе состояния, вызвав UpdatePointsStatus.

Получив допустимые точки (начальную и конечную), можно вызвать их в функцию MeasurePoints(…) в RSEnhancedPhoto, передав объект точек. Больше эти точки не нужны, поэтому я очищаю их, вызвав функцию ResetPoints() объекта RSPoint.

После этого я вызываю invalidate для picturebox, чтобы нарисовать точки на экране. Помните, что эта функция будет вызвана вне зависимости от измерения. Это дает возможность всегда видеть место щелчка.

private void UpdatePointStatus( )

Обновляет текстовые значения двух точек полосы состояния; в полосе состояния отображаются координаты щелчка изображения.

private void pictureBox1_MouseMove( object sender, MouseEventArgs e )

Обработчик событий движения мыши; просто отслеживает положение указателя мыши, когда он перемещается по изображению. Обновляет значения x, y мыши полосы состояния.

private void pictureBox1_Paint( object sender, PaintEventArgs e )

Обработчик событий рисования в элементе управления picturebox. Он отвечает за рисование двух кнопок и линии между ними на изображении.

Проверяет наличие двух действительных точек, при их наличии рисует обе точки и линию. Если есть только начальная точка, он рисует на изображении только маркер начальной точки.

private void Cleanup( )

Очищает ресурсы.

private void btnExit_Click( object sender, EventArgs e )

Обработчик событий нажатия кнопки Exit вызывает закрытие формы.

private void FormMeasure_FormClosing( object sender, FormClosingEventArgs e )

Обработчик события закрытия форм. Очистка вызовов для высвобождения ресурсов.

FormDepthEnhance


В этой форме показано, как можно улучшить изображение глубины; в элементе управления picturebox отображается улучшенное изображение. Он может показывать изображение с низким качеством или с высоким качеством.

public FormDepthEnhance( PXCMPhoto photo )

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

private void rdo_Click( object sender, System.EventArgs e )

Обработчик событий выбора одной из двух кнопок переключателя. Вызывает функцию DepthEnhancement(…) в RSEnhancedPhoto, передавая значение, указывающее высокое или низкое качество.

private void _rsEnhanced_OnImageProcessed( object sender, RSEnhancedImageArg e )

Обработчик событий OnImageProcessed, когда RSEnhancedPhotography отправляет событие. Обновляет элемент управления picturebox с помощью вспомогательного объекта renderer.

private void btnExit_Click( object sender, System.EventArgs e )

Обработчик событий нажатия кнопки Exit вызывает закрытие формы.

private void Cleanup( )

Обнулите объекты, чтобы задействовать сборку мусора.

private void FormDepthScaling_FormClosing( object sender, FormClosingEventArgs e )

Обработчик события закрытия формы. Принудительно очищает переменные.

FormDepthResize


Эта форма демонстрирует изменение размера изображения глубины. В этом случае его размер изменяется до размера цветного изображения из объекта PXCMPhoto.

public FormDepthResize( PXCMPhoto photo )

Конструктор форм. Как и другие конструкторы форм, инициализирует переменные, используемые формой, и задает обработчик событий OnImageProcessed.

private void btnResize_Click( object sender, System.EventArgs e )

Обработчик событий изменения размера кнопки вызывает функцию DepthResize(…) в RSEnahancedPhoto.

private void _rsEnhanced_OnImageProcessed( object sender, RSEnhancedImageArg e )

Обработчик событий OnImageProcessed изменяет размер picturebox и обновляет изображение, отображаемое с помощью вспомогательного объекта renderer.

private void btnExit_Click( object sender, System.EventArgs e )

Обработчик событий нажатия кнопки Exit. Закрытие формы.

private void Cleanup( )

Обнуляет объекты, чтобы их смог убрать сборщик мусора.

private void FormDepthResize_FormClosing( object sender, FormClosingEventArgs e )

Обработчик события закрытия формы вызывает Cleanup.

FormDepthRefocus


FormDepthRefocus демонстрирует возможности изменения фокусировки с помощью Enhanced Photography в Intel RealSense SDK. Когда пользователь щелкает изображение в произвольном месте, место щелчка становится точкой фокусировки изображения: в этой точке изображение становится резким, а в остальной части теряет фокусировку.

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

public FormDepthRefocus( PXCMPhoto photo )

Конструктор форм инициализирует переменные, используемые формой. Регистрирует объекты OnImageProcessed для функции и задает элемент управления picturebox.

private void pictureBox1_MouseClick( object sender, MouseEventArgs e )

Обработчик событий щелчка для элемента управления picturebox. Задает начальной точке объектов точек координаты щелчка мыши, вызывает RefocusOnPoint(…). RSPoints ResPoints() удаляет значения начальной точки и производит сброс объекта.

private void tbAperture_Scroll( object sender, System.EventArgs e )

Обработчик событий прокрутки. Получает значение прокрутки, задает текстовое значение формы, представляющее значение прокрутки, затем вызывает функцию RefocusOnPoint, передавая ему на этот раз второй параметр: значение диафрагмы.

private void _rsEnhanced_OnImageProcessed( object sender, RSEnhancedImageArg e )

Обработчик событий для события OnImageProcessed RSEnhancedObjects. Использует вспомогательный класс renderer для обновления элемента управления picturebox.

private void btnExit_Click( object sender, System.EventArgs e )

Обработчик событий нажатия кнопки Exit. Закрытие формы.

private void Cleanup( )

Обнуляет объекты, чтобы их смог убрать сборщик мусора.

private void FormDepthResize_FormClosing( object sender, FormClosingEventArgs e )

Обработчик события закрытия формы вызывает Cleanup.

FormDepthPasteOnPlane


В этой форме демонстрируется следующая возможность: пользователь может щелкнуть плоскую поверхность на изображении, и второе изображение появится на этой плоскости. Пользователь щелкает две точки на плоской поверхности. Если функциональность Intel RealSense SDK может определить поверхность, то на эту поверхность вставляется внешнее изображение.

public FormDepthPasteOnPlane( PXCMPhoto photo )

Конструктор форм инициализирует переменные, используемые формой. Регистрирует объекты OnImageProcessed для функции и задает элемент управления picturebox.

private void _rsEnhanced_OnImageProcessed( object sender, RSEnhancedImageArg e )

Обработчик событий для события OnImageProcessed RSEnhancedObjects. Использует вспомогательный класс renderer для обновления элемента управления picturebox.

private void pictureBox1_MouseClick( object sender, MouseEventArgs e )

Обработчик событий щелчка мыши в поле с изображением. Обработчик событий сначала пытается определить, сколько щелчков мыши выбрано. Если нет начальной точки, мы знаем, что пользователь впервые щелкнул поле изображения/фотографии. В этом случае следует добавить точку щелчка. После добавления точки нужно обнулить элемент управления picturebox, чтобы на изображении можно было нарисовать точку щелчка.
Если есть допустимая начальная точка, нужно проверить существование конечной точки. Если она не существует, добавьте ее.

Получив допустимые точки (начальную и конечную), можно вызвать их в функцию MeasurePasteOnPlane(…) в RSEnhancedPhoto, передав объект точек. Больше эти точки не нужны, поэтому я очищаю их, вызвав функцию ResetPoints() объекта RSPoint.

private void btnExit_Click( object sender, System.EventArgs e )

Обработчик событий нажатия кнопки Exit. Закрытие формы.

private void Cleanup( )

Обнуляет объекты, чтобы их смог убрать сборщик мусора.

private void FormDepthPasteOnPlane_FormClosing( object sender, FormClosingEventArgs e )

Обработчик события закрытия формы вызывает Cleanup.

FormDepthBlending


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

public FormDepthBlending( PXCMPhoto photo )

Конструктор форм инициализирует переменные, используемые формой. Регистрирует объекты OnImageProcessed для функции и задает элемент управления picturebox.

private void pictureBox1_MouseClick( object sender, MouseEventArgs e )

Обработчик событий для щелчков мышью элемента управления picturebox. Проверяет, что в объекте точек есть всего одна точка — начальная точка. Это единственная точка, необходимая для этой функциональности. Я записываю точки, а затем вызываю Blend(), чтобы смешать внешнее изображение с PXCMPhoto.

private void Blend( )

Получает значения с каждого ползунка, создает нужный массив поворота, затем вызывает функцию DepthBlend в составе RSEnhancedPhotograpy и передает ей все параметры.

private void tbBlend_Scroll( object sender, EventArgs e )

Обработчик событий для полос прокрутки. Вызывает Blend().

private void _rsEnhanced_OnImageProcessed( object sender, RSEnhancedImageArg e )

Обработчик событий для события OnImageProcessed RSEnhancedObjects. Использует вспомогательный класс renderer для обновления элемента управления picturebox.

private void btnExit_Click( object sender, System.EventArgs e )

Обработчик событий нажатия кнопки Exit. Закрытие формы.

private void Cleanup( )

Обнуляет объекты, чтобы их смог убрать сборщик мусора.

private void FormDepthBlending_FormClosing( object sender, FormClosingEventArgs e )

Обработчик события закрытия формы вызывает Cleanup.

Заключение


В этом документе и в примере приложения я показал, как реализовать некоторые функции Enhanced Photography, предоставляемые камерой и пакетом SDK. Надеюсь, эта статья вам понравилась и пригодилась. Спасибо за внимание.
Теги:
Хабы:
+13
Комментарии 2
Комментарии Комментарии 2

Публикации

Информация

Сайт
www.intel.ru
Дата регистрации
Дата основания
Численность
5 001–10 000 человек
Местоположение
США
Представитель
Анастасия Казантаева

Истории