Форум программистов, компьютерный форум, киберфорум
C++: Сети
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.85/41: Рейтинг темы: голосов - 41, средняя оценка - 4.85
38 / 1 / 0
Регистрация: 09.08.2012
Сообщений: 44

Передача изображения по сети

21.03.2013, 22:45. Показов 8112. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Самое время кричать "сдаемсууу!".
Может кто нибудь сталкивался, всю голову сломал.
Нужно передать по сети картинку полученную с вебкамеры.
Именно в OpenCV полученную.
имеем кадр - frame

CvMat* mat = cvEncodeImage(".jpg", frame); //конвертируем в jpg

и вот эту структуру (mat) надо передать по сети.
может кто нибудь натолкнет на мысль как быстрее и проще это сделать?
заранее спасибо
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
21.03.2013, 22:45
Ответы с готовыми решениями:

Передача изображения по сети
Нужно передать по сети через UDPClient изображение. Проблема в том что там размер буфера ограничен на 64 Кб и нужно передать весь файл...

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

Передача фрагмента изображения по сети
И так друзья, нужна ваша помощь. Задача вот в чём, есть клиент и сервер, на сервере хранится бмп изображение, клиент же запрашивает...

12
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
22.03.2013, 08:15
вот здесь
http://alphacity.netii.net/tree/prjs-web.htm
лежат desktop preview win и ipc preview - смотрим, подпиливаем под свои нужды

Добавлено через 40 секунд
...хотя смотря что вы подразумеваете под "передать по сети". если просто передать - используйте сокеты к примеру
0
38 / 1 / 0
Регистрация: 09.08.2012
Сообщений: 44
24.03.2013, 15:24  [ТС]
не то. наверное выразился не так.
получаем картинку в формате IplImage.
и пытаемся пропихнуть ее через UDP сокет

клиент
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
for( int y=0; y<frame->height; y++ ) {
                   uchar* ptr = (uchar*) (frame->imageData + y * frame->widthStep);
                for( int x=0; x<frame->width; x++ ) {
                        // 3 канала 
                    scrin[y*frame->widthStep+x+x+x]= ptr[3*x];  
                    scrin[y*frame->widthStep+x+x+x+1]=ptr[3*x+1];
                    scrin[y*frame->widthStep+x+x+x+2]=ptr[3*x+2];
                      
                }
        }
int nSendSize = sizeof(scrin);
                 int iCurrPos = 0;
                 int nSe=4096;
                while(nSendSize >0)
                    {
                //int ret = send(sSocket, &scrin[iCurrPos], nSe, 0);
                int ret=sendto(sSocket, &scrin[iCurrPos], nSe, 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
                    if (ret == 0)
                    break;
                    else if (ret == SOCKET_ERROR)
                    {
                    // Произошла ошибка
                        cout<<"Send failed"<<endl;
                        break;
                    }
                nSendSize -= ret;
                iCurrPos += ret;
                    }
                //--конец отправки
                cout<<"scrin sended"<<endl;
                }
        }
сервер
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
char scrin[921600];
    int nSendSize=921600;
    char buf[1024];
    //тут будем принимать кадр
    while (1)
    {
        /*iSize = sizeof(clientaddr);
        int ret = recvfrom(sServerListen, buf, 1024, 0, 
            (struct sockaddr *)&clientaddr, &iSize);
        cout<<buf<<endl;*/
        int iCurrPos=0;
        int nSendSize=921600;
        while (nSendSize>0)
        {
            int ret = recv(sServerListen, &scrin[iCurrPos], nSendSize, 0);
            if (ret == 0) break;
         else if (ret == SOCKET_ERROR)
            {
            // Произошла ошибка
            cout<<"Send failed"<<endl;
            break;
            }
         nSendSize -= ret;
        iCurrPos += ret;
      }
        cout<<"cadr prinyat"<<endl;
        //переносим все из scrin в frame
        for( int y=0; y<frame->height; y++ ) {
                   uchar* ptr = (uchar*) (frame->imageData + y * frame->widthStep);
                for( int x=0; x<frame->width; x++ ) {
                        // 3 канала 
                     ptr[3*x] =(uchar)scrin[y*frame->widthStep+x+x+x];  
                    ptr[3*x+1]=(uchar)scrin[y*frame->widthStep+x+x+x+1];
                    ptr[3*x+2]=(uchar)scrin[y*frame->widthStep+x+x+x+2];
                      
                }
        }
        //выводим что там получилось
        cvShowImage("capturePR",frame);
        cvWaitKey(33);
        cout<<"vivod"<<endl;
    }
ну это если вкратце.
и в результате приходит что то отдаленно напоминающее (местами) изначальное фото.
но результат не удовлетворительный.
нужно типо своего протокола делать..
может кто нибудь занимался похожим?
0
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
25.03.2013, 09:08
UDP не гарантирует приема пакетов в той очередности в которой они отправлялись. и вообще не гарантирует их приема. попробуйте через TCP. ну, или шлите через UDP с ответом на каждый пакет или снабжайте пакеты индексом части для корректной сборки (в любом случае придется городить "протокол" для инициации передачи и ее корректного завершения).
0
38 / 1 / 0
Регистрация: 09.08.2012
Сообщений: 44
25.03.2013, 19:11  [ТС]
ладно, я пробую организовать сборку на другом конце
без оповещения о приеме пакетов (ну что то потеряется в пути - не страшно)
C++
1
2
3
4
5
6
7
for (int y=0;y<480;y++){
                  unsigned char stroka[1922]; //640x3 и 2 байта на номер строки
                  if (y>255) {stroka[0]=1; stroka[1]=y-255;}
                  else {stroka[0]=0; stroka[1]=y;}
                  memcpy(&stroka[2],&scrin[y*480],640*3);
                  sendto(sSocket, reinterpret_cast<char*>(stroka), 1922, 0, (struct sockaddr *)&servaddr,   sizeof(servaddr));
              }
может подскажете как отправить uchar строку
а то при преобразовании происходят необратимые изменения...
0
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
26.03.2013, 08:39
не знаю что там у вас за необратимость. думаю не нужно сходить с ума с reinterpret_cast<char*>. достаточно просто (char *). а вообще - может не в этом дело.
0
38 / 1 / 0
Регистрация: 09.08.2012
Сообщений: 44
26.03.2013, 19:50  [ТС]
алилуйя!! оно работает!
мало ли кому пригодится.
делал для OpenCV.
полностью готовый рабочий пример пересылки IplImage по сети

клиент
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <cv.h>
#include <highgui.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <winsock2.h>
#include <windows.h>
#include <conio.h>
 
using namespace std;
 
int main()
{
    WSADATA wsd;
    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
       {
        cout<<"Can't load WinSock"<<endl;
        _getch();
        return 0;
        }
 
       SOCKET   sSocket;
       struct   sockaddr_in servaddr;
        char    szServerName[1024], szMessage[1024];
        struct hostent *host = NULL;
        strcpy(szServerName, "192.168.1.26");
        sSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if (sSocket == INVALID_SOCKET)
        {
            cout<<"Can't create socket"<<endl;
            _getch();
            return 0;
        }
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(6050);
        servaddr.sin_addr.s_addr = inet_addr(szServerName);
 
        if (servaddr.sin_addr.s_addr == INADDR_NONE)
        {
            host = gethostbyname(szServerName);
            if (host == NULL)
            {
                cout<<"Unable to resolve server"<<endl;
                _getch();
                return 1;
            }
            CopyMemory(&servaddr.sin_addr, host->h_addr_list[0],
                host->h_length);
        }
 
         // получаем любую подключённую камеру
        CvCapture* capture = cvCreateCameraCapture(CV_CAP_ANY); //cvCaptureFromCAM( 0 );
        assert( capture );
 
        // узнаем ширину и высоту кадра
        double width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
        double height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
        printf("[i] %.0f x %.0f\n", width, height );
 
        IplImage* frame=0;
 
        cvNamedWindow("capture", CV_WINDOW_AUTOSIZE);
 
        printf("[i] press Enter for send image and Esc for quit!\n\n");
 
        int counter=0;
        char scrin[921600];
        while(true){
                // получаем кадр
                frame = cvQueryFrame( capture );
                // показываем
                cvShowImage("capture", frame);
                char c = cvWaitKey(33);
                if (c == 27) { // нажата ESC
                        break;
                }
                else if(c == 13) { // Enter
                        for( int y=0; y<frame->height; y++ ) {
                   uchar* ptr = (uchar*) (frame->imageData + y * frame->widthStep);
                for( int x=0; x<frame->width; x++ ) {
                        // 3 канала 
                    scrin[y*frame->widthStep+x+x+x]= ptr[3*x];  
                    scrin[y*frame->widthStep+x+x+x+1]=ptr[3*x+1];
                    scrin[y*frame->widthStep+x+x+x+2]=ptr[3*x+2];
                              }
        }
             
              // отправка изображения
              for (int y=0;y<480;y++){
                  unsigned char stroka[1922]; //640x3 и 2 байта на номер строки
                  if (y>255) {stroka[0]=1; stroka[1]=y-255;}
                  else {stroka[0]=0; stroka[1]=y;}
                  memcpy(&stroka[2],&scrin[y*640*3],640*3);
                  sendto(sSocket, (char*)(stroka), 1922, 0, (struct sockaddr *)&servaddr,   sizeof(servaddr));
              }
                //--конец отправки
                cout<<"scrin sended"<<endl;
                }
        }
        // освобождаем ресурсы
        cvReleaseCapture( &capture );
        cvDestroyWindow("capture");
 
}
сервер
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <cv.h>
#include <highgui.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <winsock2.h>
#include <windows.h>
#include <conio.h>
 
using namespace std;
 
IplImage* frame=0;
SOCKET soc_client;
 
DWORD WINAPI NetThread(LPVOID lpParam)
{
    SOCKET        sServerListen;
    struct sockaddr_in localaddr, 
            clientaddr;
    int           iSize;
 
    sServerListen = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sServerListen == INVALID_SOCKET)
    {
        cout<<"Can't create socket"<<endl;
        _getch();
        return 0;
    }
    localaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    localaddr.sin_family = AF_INET;
    localaddr.sin_port = htons(6050);
 
    if (bind(sServerListen, (struct sockaddr *)&localaddr, 
            sizeof(localaddr)) == SOCKET_ERROR)
    {
        cout<<"Can't bind"<<endl;
        _getch();
        return 1;
    }
    
    cout<<"Bind OK"<<endl;
    char scrin[921600];
    int nSendSize=921600;
    char buf[1024];
    //тут будем принимать кадр
    while (1)
    {
        //принимаем кадр
        for (int y1=0;y1<480; y1++)
        {
            unsigned char stroka[1922];
            int ny=0;
            recv(sServerListen, reinterpret_cast<char*>(stroka), 1922, 0);
            if (stroka[0]==1) {ny=255+stroka[1];}
            else {ny=stroka[1];}
            uchar* ptr = (uchar*) (frame->imageData + ny * frame->widthStep);
            for( int x=0; x<frame->width; x++ ) {
                        // 3 канала 
                     ptr[3*x] =(uchar)stroka[x*3+2];  
                    ptr[3*x+1]=(uchar)stroka[x*3+3];
                    ptr[3*x+2]=(uchar)stroka[x*3+4];
                      
                }
 
        }
        //выводим что там получилось
        cvShowImage("capturePR",frame);
        cvWaitKey(33);
        cout<<"vivod"<<endl;
    }
    closesocket(sServerListen);
    return 0;
}
 
 
int main()
{
        frame=cvLoadImage("d:Image0.jpg",1);
        cvNamedWindow("capturePR", CV_WINDOW_AUTOSIZE);
        cvShowImage("capturePR",frame);
        cout<<"zagr"<<endl;
        cvWaitKey(33);
 
    //**************
    WSADATA wsd;
    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
     {
        cout<<"Can't load WinSock"<<endl;
        _getch();
       return 0;
      }
 
     HANDLE hNetThread;
      DWORD dwNetThreadId;
      hNetThread = CreateThread(NULL, 0, NetThread, 0, 0, &dwNetThreadId);
 
      cout<<"Wait incoming mail "<<endl;
     cvWaitKey(0);
     cvDestroyWindow("capturePR");
     return 0;
}
протокол UDP, поэтому некоторые полоски в изображении теряются в пути.
но их мало и при частой смене кадров проблем быть не должно.

на диске Д должен лежать файлик с картинкой с такими же параметрами которые будут приниматься (ну лень было организовывать еще и передачу параметров)
картинка стандартная с вебкамеры 640х480.
0
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
27.03.2013, 08:45
Цитата Сообщение от Denissimo Посмотреть сообщение
640х480
любопытно, что в начале программа вроде как пытается оперировать с фактическими размерами изображения (получает высоту и ширину, проходит по ним), а вот потом скатывается на железно вбитый размер буфера и разрешение... зачем так жестоко?
0
38 / 1 / 0
Регистрация: 09.08.2012
Сообщений: 44
28.03.2013, 23:10  [ТС]
размеры..да, ну чуть слентяйничал. это не главное.
тут другая проблема организовалась.
при реалтайм передаче (по локалке по вайфаю)
потери нарастают в геометрической прогрессии..
причем чем ближе к концу кадра - тем чаще пакет теряется.
в итоге верх картинки передается более менее, а низ...
такое ощущение что картинка с марса идет

теперь вопрос.
кто нибудь может подсказать как это дело устранить?
если через 2 порта буду передавать - быстрее дело пойдет?
или навстречу по ТСП передавать номера принятых строк?
0
Модератор
 Аватар для vxg
3406 / 2177 / 354
Регистрация: 13.01.2012
Сообщений: 8,444
29.03.2013, 09:40
тупо передавайте все через tcp и будет счастье
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
29.03.2013, 12:04
Цитата Сообщение от Denissimo Посмотреть сообщение
кто нибудь может подсказать как это дело устранить?
Сократить объем передаваемых данных (в чем резон отдавать raw картинку?). Убрать фрагментацию (Ваши 1922 это слишком много для 100Мб сетей) , не пытаться лить на максимальной скорости, увеличить буфера сокета (особенно актуально для принимающей стороны). Взять готовый протокол поддерживающий подтверждения и перепосылку (например UDT).
1
38 / 1 / 0
Регистрация: 09.08.2012
Сообщений: 44
29.03.2013, 21:31  [ТС]
Цитата Сообщение от g_u_e_s_t Посмотреть сообщение
Сократить объем передаваемых данных (в чем резон отдавать raw картинку?). Убрать фрагментацию (Ваши 1922 это слишком много для 100Мб сетей) , не пытаться лить на максимальной скорости, увеличить буфера сокета (особенно актуально для принимающей стороны). Взять готовый протокол поддерживающий подтверждения и перепосылку (например UDT).
вот тут можно чутка поподробнее, пожалуйста. или хотя бы пару ссылок где почитать. (про увеличить буфер сокета я вообще первый раз слышу, сорри новичек) про UDT ща погуглю, спасибо!
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
30.03.2013, 08:45
Цитата Сообщение от Denissimo Посмотреть сообщение
пожалуйста. или хотя бы пару ссылок где почитать. (про увеличить буфер сокета я вообще первый раз слышу
Почитать, наверное на MSDN про setsockopt(, SOL_SOCKET, SO_SNDBUF, ,);
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
30.03.2013, 08:45
Помогаю со студенческими работами здесь

Передача матрицы изображения по сети
Нужно передать картинку с телефона на сервер. Для телефона пиши на Java(Android Studio), а для сервера пишу на C#(Visusl Studio 2010). В...

Передача изображения по локальной сети
Здравствуйте! Пишу сюда, потому-что уже не знаю что делать... Проблема такова - не получается передать картинку через сокеты. А если...

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

Изобретение велосипеда, как тренировка студента. Передача видео или изображения рабочего стола по сети
Собственно, есть задание и коротко оно звучит так: &quot;написать то, что будет передавать видео или изображения рабочего стола на другой...

Передача изображения
Здравствуйте. Есть клиент и сервер (clientsocket и serversocket) как передать изображение из Image1 с клиента на сервер? Добавлено...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru