Russian Qt Forum
Ноябрь 26, 2024, 01:39 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Передать объект OpenCV - IplImage по сокету  (Прочитано 8979 раз)
merke
Гость
« : Апрель 28, 2012, 16:27 »

Всем привет!

Хочу решить следующую задачу, с вебкамеры снимаю кадры в объект IplImage. Далее хочу каждый кадо слать по сокету клиентам, там всё это делать писать в видео формат *.avi при помощи функции cvWriteFrame(writer, frame);

Вот вид структуры IplImage:

http://locv.ru/wiki/3.5_%D0%A1%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D0%B0_%E2%80%93_IplImage

Код:
typedef struct _IplImage {
  int                  nSize; // sizeof(IplImage)
  int                  ID; // Версия (=0)
  int                  nChannels; // Число каналов
  int                  alphaChannel; // Альфа-канал
  int                  depth; // Глубина в битах
  char                 colorModel[4]; // Не используется в OpenCV
  char                 channelSeq[4]; // Аналогично
  int                  dataOrder; // Расположение каналов
  int                  origin; // Начало координат
  int                  align; // Выравнивание строк изображения (OpenCV использует widthStep)
  int                  width; // Ширина
  int                  height; // Высота
  struct _IplROI*      roi; // ROI
  struct _IplImage*    maskROI; // =0
  void*                imageId; //
  struct _IplTileInfo* tileInfo; //
  int                  imageSize; // Память выделенная под изображение
  char*                imageData; // Данные изображения
  int                  widthStep; // Число байт в одной строке изображения
  int                  BorderMode[4]; // Не используется в OpenCV
  int                  BorderConst[4]; // Аналогично
  char*                imageDataOrigin; // Используется для правльного освобождения памяти
} IplImage;

Ни как не получается передать всё это дело по сокету(

Делаю следующим образом, отправка:

Код:
 IplImage *frame;

  frame = cvQueryFrame(camera);

  cvwidget->putImage (frame);

  cvWriteFrame(writer, frame);

  this->sock->write (reinterpret_cast<char*>(frame));

Приёмка:

Код:
  IplImage* img;
 
  img = cvCreateImage(cvSize(320, 240), IPL_DEPTH_8U, 1);

  int  imgsize = img->imageSize;
  char sockdata[imgsize];
  int  i, j, k, bytes;

  QByteArray arr = sock->readAll ();

  img = reinterpret_cast<IplImage*>(arr.data ());

  cvwidget->putImage (img);
Записан
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #1 : Апрель 28, 2012, 16:37 »

Хм. Нет слов.

Код
C++ (Qt)
this->sock->write (reinterpret_cast<char*>(frame));
 

В статусе у тебя написано что Программист, 575 постов...

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

Гугль в помощь
alexis031182
Гость
« Ответ #2 : Апрель 28, 2012, 16:59 »

Хм. Нет слов.
...
В статусе у тебя написано что Программист, 575 постов...
Ну зря Вы так, +100500 постов можно и в Говорилке настрогать Улыбающийся А так конечно нельзя не согласиться, что имеет смысл подправить код
Записан
Bepec
Гость
« Ответ #3 : Апрель 28, 2012, 17:00 »

Навроки не накидывайся на человека. Нет всезнающих программистов. В области анализа сейсмо сигналов по оптопаре - ты 99% нуб Подмигивающий

Начал изучать он сокеты - знаешь, подскажи. Незнаешь - скажи что незнаешь. Троллить надо, когда человек или тролль, или ленивец.


Проще говоря перевожу что сказал Навроки (сам пока к сети не лез)

1) структуру надо упаковывать.
2) передавать char - нехорошо.
3) по слухам, для передачи по сети подойдёт QDataStream вроде.
4) Навроки сказал что-то про структуру Улыбающийся Я не понял. Я нуб Подмигивающий
Записан
V1KT0P
Гость
« Ответ #4 : Апрель 28, 2012, 17:04 »

4) Навроки сказал что-то про структуру Улыбающийся Я не понял. Я нуб Подмигивающий
Он сказал что надо сериализовать структуру(IplImage). Я с ним согласен, может принимающей стороне вообще не нужен OpenCV, а только картинка.
Записан
Bepec
Гость
« Ответ #5 : Апрель 28, 2012, 17:11 »

Виктор, богом прошу - выскажи своё мнение по всем пунктам Подмигивающий Возможно и мне пригодится когда нить.

1) передавать лучше в чём?
2) сериализовать это как (понятие сериализации знаю, но в openCV всяком я нуб)
Записан
V1KT0P
Гость
« Ответ #6 : Апрель 28, 2012, 17:20 »

Виктор, богом прошу - выскажи своё мнение по всем пунктам Подмигивающий Возможно и мне пригодится когда нить.

1) передавать лучше в чём?
2) сериализовать это как (понятие сериализации знаю, но в openCV всяком я нуб)

1) Передавать как набор байт.
2) Это значить впихнуть данные в массив байт.
Как уже было сказано проще всего отправить ширину, высоту, формат(RGB, RGBA и т.д.) и сырые данные изображения.
Записан
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #7 : Апрель 28, 2012, 17:21 »

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

Верес, для передачи и сериализации QDataStream подходит, это ты правильно сказал. Он для этого специально предназначен.

Чтобы передать картинку в OpenCV надо уложить все нужные поля вышеуказанной структуры в QDataStream

Код
C++ (Qt)
QDataStream s;
s << frame.nChannels << frame.alphaChannel << frame.depth << ... << QByteArray(frame.imageData, frame.imageSize) << ...
 

На обратном конце разобрать в таком-же порядке.

Но предварительно надо для себя решить в каком виде передавать картинку. Если нужно просто отображать ее на виджете, то лучше на сервере осуществить конвертацию в QImage и передать по сети его. Если надо продолжать обрабатывать фрейм на стороне клиента с помощью OpenCV, то тогда нужно аккуратно передать все без исключения поля структуры, и на клиенте восстановить этот фрейм.
Записан

Гугль в помощь
alexis031182
Гость
« Ответ #8 : Апрель 28, 2012, 17:22 »

Это похоже продолжение этой темы.

OpenCV оперирует несжатым видео, поскольку он предназначен не для захвата и воспроизведения. Встроенный захват - это всего лишь для удобства пользования, но никак не прямое назначение. Для захвата лучше конечно что-то другое использовать, если не предполагается какой-либо обработки видео перед отправкой (например, детекция движения и т.п.).

Для виндовса можно обратиться к DirectShow, а на Linux и FFMpeg'а хватит (а то и еще с десяток вариантов на выбор).

Далее... Перед отправкой видео на сервер, данные необходимо конвертировать в формат, подходящий для передачи по сети (хотя бы просто если судить о размере данных). Например, flv. Сжимать по-кадрово - низкий КПД, лучше весь поток. FFMpeg в этом деле - идеальное решение.
Записан
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #9 : Апрель 28, 2012, 17:30 »

Кстати, а Phonon как-нить можно заставить заниматься захватом?

http://wiki.videolan.org/SoC_2010_Phonon_Capture_API - работы в этом направлении проводились. Однако в кутэшной доке вообще ничего не сказано про захват.
Записан

Гугль в помощь
alexis031182
Гость
« Ответ #10 : Апрель 28, 2012, 17:35 »

В пятом Qt появились QCamera и сопровождающие.
Записан
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #11 : Апрель 28, 2012, 17:37 »

Ну вот, топикстартеру нужно немного подождать )
Записан

Гугль в помощь
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.088 секунд. Запросов: 23.