Передача видео потока по UDP

Аватара пользователя
IvanLis

Activity Professionalism Tutorials Gold Man of the year 2012
Автор
professor
professor
Сообщения: 4947
Зарегистрирован: 02 дек 2009, 17:44
Награды: 7
Репутация: 0
Версия LabVIEW: 2015, 2016
Откуда: СССР

Re: Передача видео потока по UDP

Сообщение IvanLis »

AndreyDmitriev писал(а):А это приводит к тому, что на самом деле в выходной файл запишется несколько не то, что изначально содержалось в строке (там будет не три байта, а четыре). При загрузке происходит обратная конвертация, но не для любого набора данных она будет происходить правильно. А правильно пользоваться парой Write Binary File / Read Binary File (именно для строки) - тогда проблем не будет


Мне их сохранять нет необходимости.
А при передаче по сети (UDP протокол), строка не искажается?
По идее она как бинарные данные должна передаваться :dntknw:

И еще вопрос, Вы пробовали открыть сжатый Jpeg файл.
На скрине открыт несжатый файл. Попробовать смогу только в понедельник, а интересно.

AndreyDmitriev

Activity Professionalism Tutorials Gold Black
VIP
VIP
Сообщения: 1225
Зарегистрирован: 03 фев 2010, 00:42
Награды: 6
Репутация: 0
Версия LabVIEW: 6.1 - 2016
Откуда: Германия
Контактная информация:

Re: Передача видео потока по UDP

Сообщение AndreyDmitriev »

Ладно, давайте разберёмся - там сложного на самом деле ничего нет.

IvanLis писал(а):Чудеса....


За постулат примем то, что чудес на свете не бывает - в компьютере только биты да байты плюс нехитрые операции, он делает ровно то, о чём его просят.

IvanLis писал(а):Так как обратного преобразования, я решил использовать обычное преобразование String->Image. И самое удивительное, что заработало.

Удивительного ничего нет - пара IMAQ Flatten / Unflatten совместима между собой. А то, что я выше писал про невозможность Unflatten для JPEG потока относится только к случаю, когда мы имеем чистый JPEG (например полученный при помощи IMAQ Write String, либо при непосредственном чтении JPEG файла). В данном случае строка помимо JPEG данных уже содержит необходимый IMAQ заголовок, так что плясок с бубном не требуется.
Заметьте также, что для Unflatten требуется только константа - IMAQ Create вызывать не нужно, тип, имя, размер - всё это не требуется, так как эта информация уже содержится во входной строке.

Вот типичные грабли, на которые наступают, когда используют эту пару:

snippet01.png


На первый взгляд кажется, что интенсивность на выходе IMAQ Histogram будет 100, однако она будет равна 50, поскольку в третьем фрейме Unflatten перезаписывает картинку с именем Untitled (мы хорошо помним, что картинки передаются по ссылке). Возможных выходов тут два - либо делать копию перед вызовом IMAQ Flatten либо поставить флаг Flatten with Process-Unique Name (этот флаг доступен только начиная с десятой версии Vision), тогда Unflatten создаст новую картинку с именем типа "remote image 0000000005625484 @ 00-FF-FF-FD-55-8E pid 000016B8" Всё это нужно только в том случае, когда Flatten / Unflatten используются в одном контексте. Если они разнесены в разные процессы, обменивающиеся строкой данных, то имена роли естественно не играют.

IvanLis писал(а):Попробовал сохранить кадр Image -> Jpeg String в текстовый файл. Вроде открывается, но уже с искажениями.

Искажения могут быть связаны только с JPEG компрессией - она портит качество изображения. Степень потерь зависит от степени компрессии, разумеется. В свете того, что выше двоичные данные сохранялись как текстовые строки, можно получить искажения совсем другого рода, но они будут связаны с тем, что данные просто порушены.

IvanLis писал(а):При работе по сети. Видно, что кадр принимается нормально. Преобразование Jpeg String -> Image производится без ошибок. Но при этом на индикаторе Image ничего не отображается

А вот тут может быть несколько причин. Прежде всего, надо, конечно быть уверенным, что принимающая сторона строку принимает без искажений.
Важно также, чтобы версии Vision совпадали на обоих компьютерах (поскольку совместимость картинки в виде Flattened String между различными версиями вообще говоря не гарантируется)
Бывали случаи, когда Vision Run-Time ставился криво и не добавлял необходимые файлы в Shared папку. Косвенные симптомы этого - отсутствующие инструменты (лупа, указатель, ROI) слева от Vision Display.
вообще говоря проще всего поставить LabVIEW на оба компьютера - резко облегчает отладку.
Вот ещё типичные грабли, на которые наступают при отображении постоянно меняющейся картинки:
snippet02.png

Кажется, что интенсивность изображения будет 100 (разумеется я имею в виду интенсивность, показываемую в статусной строке Vision Display), однако она будет 50 (впрочем, воспроизводимость эффекта зависит от скорости компьютера).
Дело в том, что Vision Display не показывает картинку немедленно. Она обновляется в отдельном UI потоке. И в данном случае изображение начинает обновляться при следующей итерации While цикла (во время Wait функции). Ну а поскольку изображения передаются по ссылке, мы видим вовсе не то, что записали в Vision Display, а то, что в данный момент находится в картинке, ссылка на которую хранится в контроле. Самый простой способ - сделать буферизацию - перед записью в Vision Display сделать копию картинки (IMAQ Copy) и использовать для отображения копию. Теоретически этот случай может иметь место и Vision Display перехлёстывается с Unflatten. Можно также вызвать метод Refresh Image, что запустит немедленное обновление, но и в этом случае надо будет дать время на обновление. Но я бы порекомендовал использовать буфер - будет значительно лучше, если данные в окне Vision Display не будут меняться извне.

IvanLis писал(а):А при передаче по сети (UDP протокол), строка не искажается?
По идее она как бинарные данные должна передаваться

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

IvanLis писал(а):И еще вопрос, Вы пробовали открыть сжатый Jpeg файл.

Пробовал, но там данные порушены. Дело в том, что если в исходной строке уже была комбинация 0x0D 0x0A, то она остаётся неизменной в текстовом файле. При обратном чтении она заменяется на 0x0A - и данные рушатся.
Последний раз редактировалось AndreyDmitriev 17 дек 2011, 21:32, всего редактировалось 1 раз.

Аватара пользователя
IvanLis

Activity Professionalism Tutorials Gold Man of the year 2012
Автор
professor
professor
Сообщения: 4947
Зарегистрирован: 02 дек 2009, 17:44
Награды: 7
Репутация: 0
Версия LabVIEW: 2015, 2016
Откуда: СССР

Re: Передача видео потока по UDP

Сообщение IvanLis »

:thank:
Огромное спасибо за разъяснения и комментарии.
Да и просто приятно послушать человека, особенно когда он в этой области чувствует себя "как рыба в воде"!
AndreyDmitriev писал(а):Я уж почти пятнадцать лет как учу роботов видеть, ну и сам кое-чему с ними научился...

и других теперь поучить можно :super:

AndreyDmitriev писал(а):Важно также, чтобы версии Vision совпадали на обоих компьютерах (поскольку совместимость картинки в виде Flattened String между различными версиями вообще говоря не гарантируется).

Это мой вариант!
Писал я программу на 2010, потом пересохранил для 8.6. На приемной стороне все крутилось на 8.6 а передающая 2010.
Можно сказать, что благополучное стечение обстоятельств, способствовало скорейшему поиску коллизии.
Иначе я бы еще долго бился. Надо будет попробовать еще и первоначальный вариант, там видимо аналогичная проблема.

AndreyDmitriev писал(а):Пробовал, но там данные порушены. Дело в том, что если в исходной строке уже была комбинация 0x0D 0x0A, то она остаётся неизменной в текстовом файле. При обратном чтении она заменяется на 0x0A - и данные рушатся.

У меня нормально отображалась первые 15..20% изображения, потом структура разрушалась.

Еще раз спасибо! Очень познавательно, особенно с практической точки зрения.
Результаты сообщу в понедельник вечером.

Думаю будет полезно почитать не только мне, но и всем работающим с Vision.


p.s. Визильтер этого не писал :wink:

AndreyDmitriev

Activity Professionalism Tutorials Gold Black
VIP
VIP
Сообщения: 1225
Зарегистрирован: 03 фев 2010, 00:42
Награды: 6
Репутация: 0
Версия LabVIEW: 6.1 - 2016
Откуда: Германия
Контактная информация:

Re: Передача видео потока по UDP

Сообщение AndreyDmitriev »

IvanLis писал(а)::thank:
Огромное спасибо за разъяснения и комментарии.

Думаю будет полезно почитать не только мне, но и всем работающим с Vision.[/b]

p.s. Визильтер этого не писал :wink:

На здоровье!

А Визильтер (если имеется в виду книга "Обработка и анализ цифровых изображений с примерами на LabVIEW IMAQ Vision") ещё много о чём не написал. А в некоторых местах написал много, но плохо понимая о чём. Вообще книга "на троечку". По блок-диаграммам можно вообще учить "как не надо делать". И самое главное - книгу неинтересно читать, она совершенно не учит думать, да и материал изложен не последовательно. Впрочем, определённые зёрна там имеются, а объять необъятное, как известно — весьма непросто.

Аватара пользователя
mark
beginner
beginner
Сообщения: 39
Зарегистрирован: 18 ноя 2010, 21:35
Репутация: 0
Версия LabVIEW: 2015

Re: Передача видео потока по UDP

Сообщение mark »

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

Могу добавить про Flatten Image To String. Как правильно заметил Андрей Дмитриев, у функции есть опция - Делать Flatten с уникальными именами. Насколько я понимаю (возможно, ошибаюсь), функция Unflatten каждый раз будет создавать копию изображения в изображение "remote image 0000...", что может привести к утечке памяти на принимающей стороне. Потому что каждый раз нужно будет создавать изображение с уникальным именем "remote image 0000...".

При передачи по сети я использую небольшой кольцевой буфер изображений. Полученное изображение копирую в одно из изображений кольцевого буфера, другой цикл это изображение подвергает Flatten'у c jpeg и передает по сети. На стороне клиента также я делаю принудительное копирование в специально созданное изображение после Unflatten. Таким образом можно немного отойти от негативных эффектов, связанных с localhost.

Для передачи несжатых изображений можно использовать и простой двумерный массив, получаемый, например из функции IMAQdx Get Image Data или конвертировать из Image в двумерный массив IMAQ ImageToArray.

AndreyDmitriev

Activity Professionalism Tutorials Gold Black
VIP
VIP
Сообщения: 1225
Зарегистрирован: 03 фев 2010, 00:42
Награды: 6
Репутация: 0
Версия LabVIEW: 6.1 - 2016
Откуда: Германия
Контактная информация:

Re: Передача видео потока по UDP

Сообщение AndreyDmitriev »

mark писал(а):Могу добавить про Flatten Image To String. Как правильно заметил Андрей Дмитриев, у функции есть опция - Делать Flatten с уникальными именами. Насколько я понимаю (возможно, ошибаюсь), функция Unflatten каждый раз будет создавать копию изображения в изображение "remote image 0000...", что может привести к утечке памяти на принимающей стороне. Потому что каждый раз нужно будет создавать изображение с уникальным именем "remote image 0000...".


Это справедливое замечание. Если flatten делается с этим флагом, то мы легко можем получить утечки памяти. С другой стороны делать Dispose каждый раз после вызова нет необходимости, если понять как это имя образуется. Там на самом деле три меняющиеся части - первая часть - это шестнадцать байт, следующих после строки "remote image". Они (возможно не все, а только последние восемь байт) генерируются на основе исходного имени. Например, для "untitled" это будет 0000000005626194, для "img" - "000000000FD38BEC" и так далее. Способ генерации не очень интересен, важно, что для этот идентификатор зависит от имени. Следующий параметр после значка "@" - это MAC адрес одной из сетевых карт. У меня "00-FF-FF-FD-55-8E"- А последний параметр - это идентификатор процесса, откуда функция была вызвана. Так что если функция на передающей стороне вызывается в цикле, то она возвращает всегда одно и то же имя, и это легко проверить:

snippet3.png


Но если процесс (LabVIEW или приложение) будет перезапущен, или будет запущен на другой машине, то идентификатор поменяется. В любом случае принять меры для предотвращения утечек, конечно придётся. Самый простой способ - запоминать имя и ссылку на изображение в сдвиговом регистре и делать Dispose в случае, если оно меняется (я вообще стараюсь не использовать Dispose до тех пор, пока это действительно не будет необходимо).

Кстати, есть несложный способ контролировать подобные утечки памяти - достаточно воспользоваться инструментом IMAQ Status
(расположен в %Program Files%\National Instruments\LabVIEW x.x\vi.lib\vision\Compatibility.llb\IMAQ Status). Этот инструмент выводит список всех созданных изображений.

mark писал(а):Для передачи несжатых изображений можно использовать и простой двумерный массив, получаемый, например из функции IMAQdx Get Image Data или конвертировать из Image в двумерный массив IMAQ ImageToArray.


Да, так тоже можно сделать, но учитывая, что конвертация IMAQ Image в LabVIEW массив и обратно - довольно прожорливые операции в смысле расхода памяти и скорости. Впрочем, Flatten / Unflatten по эффективности скорее всего могут оказаться сравнимы с конвертацией в массив и обратно. Кроме того, передавая RAW данные через массив, мы теряем служебную информацию, которая уже содержится во Flattened строке - например, для смешанной передачи 8/16 бит изображений придётся дополнительно передавать информацию о глубине цвета, и т.д.

Аватара пользователя
mark
beginner
beginner
Сообщения: 39
Зарегистрирован: 18 ноя 2010, 21:35
Репутация: 0
Версия LabVIEW: 2015

Re: Передача видео потока по UDP

Сообщение mark »

AndreyDmitriev,

Что касается утечки памяти - возможна ситуация, когда она может быть существенной в некоторых случаях, как например, у меня было недавно (по незнанию). Если создать большой массив картинок и настроить IMAQ Configure Buffer скажем на 100-200 картинок, то тогда при включенной опции Unflatten with unique names возникнет точно такой же по размеру дубликат. Тогда я не исследовал этот вопрос должным образом, но благодаря Андрею мы теперь знаем, что уникальное имя для картинки - оно действительно уникальное для конкретного изображения :wink:

Аватара пользователя
IvanLis

Activity Professionalism Tutorials Gold Man of the year 2012
Автор
professor
professor
Сообщения: 4947
Зарегистрирован: 02 дек 2009, 17:44
Награды: 7
Репутация: 0
Версия LabVIEW: 2015, 2016
Откуда: СССР

Re: Передача видео потока по UDP

Сообщение IvanLis »

Самому экспериментировать некогда было, но было доложено, что самый первый вариант работает на гигабитной сети, правда коряво. :cantbe:

Да я и сам начал считать
15 fps
1000/15=66 мс
задержка на 3 мс и 40 пакетов
40*3=120 мс на передачу одного видео кадра
так что оно и теоретически не должно работать нормально


Завтра может сам попробую по 10 Mbit сетке погонять, но уже Jpeg, если LabVIEW переустановить успею.

И еще. Попробовал посмотреть Image Info (Name) по поводу создания Image и возможных утечек памяти.
Если задавать имя Image как у меня, т.е. явно через Image Create. То Image имеет именно то имя, которое я задавал при создании. Получается что утечек никаких не должно быть. :dntknw:

По результатам отпишусь.

Аватара пользователя
IvanLis

Activity Professionalism Tutorials Gold Man of the year 2012
Автор
professor
professor
Сообщения: 4947
Зарегистрирован: 02 дек 2009, 17:44
Награды: 7
Репутация: 0
Версия LabVIEW: 2015, 2016
Откуда: СССР

Re: Передача видео потока по UDP

Сообщение IvanLis »

Сегодня удалось протестировать программу.
Вариант передачи с Jpeg сжатием аналогичный этому
В сети 10Mbit работает отлично, даже при качестве картинки 1000.

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

alex2alex
beginner
beginner
Сообщения: 12
Зарегистрирован: 28 дек 2011, 12:28
Репутация: 0
Версия LabVIEW: LabVIEW 2011
Контактная информация:

Re: Передача видео потока по UDP

Сообщение alex2alex »

Уважаемые господа специалисты!
Помогите решить проблему.

Не получается корректно передать изображение с Web-камеры на другой компьютер ни по UDP ни по TCP/IP.
Для передачи использую примеры из LabVIEW (Напрмер для TCP/IP - Data Server и Data Client).
При запуске обоих vi (Data Sender, Data Client) на одном компьютере с адресом localhost - изображение на экране клиента есть. При запуске на разных компьютерах тестер показывает, что принимается картинка (image), экран дергается в такт периоду передачи, но изображения нет.

alex2alex

Аватара пользователя
IvanLis

Activity Professionalism Tutorials Gold Man of the year 2012
Автор
professor
professor
Сообщения: 4947
Зарегистрирован: 02 дек 2009, 17:44
Награды: 7
Репутация: 0
Версия LabVIEW: 2015, 2016
Откуда: СССР

Re: Передача видео потока по UDP

Сообщение IvanLis »

alex2alex писал(а):Не получается корректно передать изображение с Web-камеры на другой компьютер ни по UDP ни по TCP/IP.
Для передачи использую примеры из LabVIEW (Напрмер для TCP/IP - Data Server и Data Client).
При запуске обоих vi (Data Sender, Data Client) на одном компьютере с адресом localhost - изображение на экране клиента есть. При запуске на разных компьютерах тестер показывает, что принимается картинка (image), экран дергается в такт периоду передачи, но изображения нет.


1. Возникает ли ошибка при преобразовании String -> Image? какая?
2. Вы пробовали запускать пример, который выложен в данной теме (с использованием Jpeg сжатия)?
3. Как Вы считаете, возможно ли помочь если Вы не выложили программу?

alex2alex
beginner
beginner
Сообщения: 12
Зарегистрирован: 28 дек 2011, 12:28
Репутация: 0
Версия LabVIEW: LabVIEW 2011
Контактная информация:

Re: Передача видео потока по UDP

Сообщение alex2alex »

Спасибо за ответ.

1. Ошитбки при преобразовании String -> Image не возникает.

2. Пример пока не пробовал. Сейчас поищу, но хотелось бы понять и проблемы своего проекта.

3. Прилагаю скрин трех vi, входящих в проект (camera, server, client) и сам проект.

С Новым годом!
Вложения
video_tcpip.zip
(50.14 КБ) 201 скачивание
video_tcp_ip.jpg

Аватара пользователя
mark
beginner
beginner
Сообщения: 39
Зарегистрирован: 18 ноя 2010, 21:35
Репутация: 0
Версия LabVIEW: 2015

Re: Передача видео потока по UDP

Сообщение mark »

alex2alex,

При запуске обоих vi (Data Sender, Data Client) на одном компьютере с адресом localhost - изображение на экране клиента есть.


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

Попробуйте при передаче использовать рекомендуемые инструменты:
1) На стороне сервера вызываете IMAQ Flatten Image To string.
2) На стороне клиента вызываете Unflatten. На вход Unflatten, указывающий тип данных, подавайте константу типа Image.

Обратите внимание на сообщение viewtopic.php?f=129&t=4226&start=15#p35914 и ниже.

AndreyDmitriev

Activity Professionalism Tutorials Gold Black
VIP
VIP
Сообщения: 1225
Зарегистрирован: 03 фев 2010, 00:42
Награды: 6
Репутация: 0
Версия LabVIEW: 6.1 - 2016
Откуда: Германия
Контактная информация:

Re: Передача видео потока по UDP

Сообщение AndreyDmitriev »

alex2alex писал(а):Спасибо за ответ.
1. Ошитбки при преобразовании String -> Image не возникает.
2. Пример пока не пробовал. Сейчас поищу, но хотелось бы понять и проблемы своего проекта.
3. Прилагаю скрин трех vi, входящих в проект (camera, server, client) и сам проект.


Коллега, есть принципиальная разница между TypeCast и FlattenToString. Фактически преобразование типов не записывает в строку содержимое картинки, а пишет лишь её имя. Обратное преобразование возвращает ссылку на картинку с таким именем, поэтому это будет работать лишь до тех пор, пока и клиент и сервер находятся в одном адресном пространстве, и никогда не будет работать между двумя приложениями.
Почувствуйте разницу:

snippet01a.png


Кстати, для потоковой передачи картинок по сети в последних версиях есть замечательная штука, которая называется Network Stream. Этот метод работает с IMAQ изображениями и позволяет осуществить передачу безо всяких преобразований.

Using Network Streams With IMAQ

Код не идеален, но даёт общее представление об идее:

На стороне сервера
Изображение

На стороне клиента:
Изображение

alex2alex
beginner
beginner
Сообщения: 12
Зарегистрирован: 28 дек 2011, 12:28
Репутация: 0
Версия LabVIEW: LabVIEW 2011
Контактная информация:

Re: Передача видео потока по UDP

Сообщение alex2alex »

Сударь!

Спасибо за подробный и развернутый ответ.
Теперь постараюсь разобраться.

Еще раз - с Новым годом! Всех благ!

Ответить

Вернуться в «Vision / IMAQ»