Russian Qt Forum

Qt => Общие вопросы => Тема начата: merke от Апрель 28, 2012, 16:27



Название: Передать объект OpenCV - IplImage по сокету
Отправлено: 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);


Название: Re: Передать объект OpenCV - IplImage по сокету
Отправлено: navrocky от Апрель 28, 2012, 16:37
Хм. Нет слов.

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

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

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


Название: Re: Передать объект OpenCV - IplImage по сокету
Отправлено: alexis031182 от Апрель 28, 2012, 16:59
Хм. Нет слов.
...
В статусе у тебя написано что Программист, 575 постов...
Ну зря Вы так, +100500 постов можно и в Говорилке настрогать :) А так конечно нельзя не согласиться, что имеет смысл подправить код


Название: Re: Передать объект OpenCV - IplImage по сокету
Отправлено: Bepec от Апрель 28, 2012, 17:00
Навроки не накидывайся на человека. Нет всезнающих программистов. В области анализа сейсмо сигналов по оптопаре - ты 99% нуб ;)

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


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

1) структуру надо упаковывать.
2) передавать char - нехорошо.
3) по слухам, для передачи по сети подойдёт QDataStream вроде.
4) Навроки сказал что-то про структуру :) Я не понял. Я нуб ;)


Название: Re: Передать объект OpenCV - IplImage по сокету
Отправлено: V1KT0P от Апрель 28, 2012, 17:04
4) Навроки сказал что-то про структуру :) Я не понял. Я нуб ;)
Он сказал что надо сериализовать структуру(IplImage). Я с ним согласен, может принимающей стороне вообще не нужен OpenCV, а только картинка.


Название: Re: Передать объект OpenCV - IplImage по сокету
Отправлено: Bepec от Апрель 28, 2012, 17:11
Виктор, богом прошу - выскажи своё мнение по всем пунктам ;) Возможно и мне пригодится когда нить.

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


Название: Re: Передать объект OpenCV - IplImage по сокету
Отправлено: V1KT0P от Апрель 28, 2012, 17:20
Виктор, богом прошу - выскажи своё мнение по всем пунктам ;) Возможно и мне пригодится когда нить.

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

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


Название: Re: Передать объект OpenCV - IplImage по сокету
Отправлено: navrocky от Апрель 28, 2012, 17:21
Прошу прощения, меня выморозили в соседней ветки, моя толерантность исчерпалась :D

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

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

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

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

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


Название: Re: Передать объект OpenCV - IplImage по сокету
Отправлено: alexis031182 от Апрель 28, 2012, 17:22
Это похоже продолжение этой (http://www.prog.org.ru/topic_21759_0.html) темы.

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

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

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


Название: Re: Передать объект OpenCV - IplImage по сокету
Отправлено: navrocky от Апрель 28, 2012, 17:30
Кстати, а Phonon как-нить можно заставить заниматься захватом?

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


Название: Re: Передать объект OpenCV - IplImage по сокету
Отправлено: alexis031182 от Апрель 28, 2012, 17:35
В пятом Qt появились QCamera (https://qt-project.org/doc/qt-5.0/qcamera.html) и сопровождающие.


Название: Re: Передать объект OpenCV - IplImage по сокету
Отправлено: navrocky от Апрель 28, 2012, 17:37
Ну вот, топикстартеру нужно немного подождать )