質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

UDP

UDP(User Datagram Protocol)とは、トランスポート層のプロトコルであり、コネクション型のデータサービスです。IPネットワーク上の別のホストにコンピュータのアプリケーションがメッセージを送ることができ、転送チャンネルやデータ経路を設定する必要はありません。TCPに比べて高速であるが、信頼性が薄いという特徴があります。

Q&A

0回答

2595閲覧

UDP通信から画像処理を行う

mmmw

総合スコア23

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

UDP

UDP(User Datagram Protocol)とは、トランスポート層のプロトコルであり、コネクション型のデータサービスです。IPネットワーク上の別のホストにコンピュータのアプリケーションがメッセージを送ることができ、転送チャンネルやデータ経路を設定する必要はありません。TCPに比べて高速であるが、信頼性が薄いという特徴があります。

0グッド

1クリップ

投稿2019/11/14 10:16

前提・実現したいこと

UDP通信で連続データとして数値データを受信し,画像処理をリアルタイムで行いたい。
送信プログラムはあるセンサのサンプルプログラムにUDP通信プログラムを組み込んでいる。

送信側は、100ms間隔でパケットを送信する。
受信側は、パケットを受信後にもろもろの処理(計算、描画等)を行う。その時,随時データを受信している。

発生している問題・エラーメッセージ

受信側のデータが0と表示され,画像処理に数値データが影響されていない。 送信プログラムのpPno[5]というfloat型のデータを連続的に送信したいが受信側では0になってしまう。

該当のソースコード

C++

1//送信側 2 3VOID DisplayFrame( PBYTE pBuf, DWORD dwSize ) 4{ 5 6 //UDP 7 8 WSAData wsaData; 9 10 SOCKET sock; 11 struct sockaddr_in addr; 12 13 WSAStartup(MAKEWORD(2, 0), &wsaData); 14 15 sock = socket(AF_INET, SOCK_DGRAM, 0); 16 17 addr.sin_family = AF_INET; 18 addr.sin_port = htons(12345); 19 addr.sin_addr.S_un.S_addr = inet_addr("10.184.177.121"); 20 21 TCHAR szFrame[200]; 22 DWORD i = 0; 23 24 while ( i<dwSize) 25 { 26 BYTE ucSensor = pBuf[i+2]; 27 SHORT shSize = pBuf[i+6]; 28 29 // skip rest of header 30 i += 8; 31 32 PDWORD pFC = (PDWORD)(&pBuf[i]); 33 PFLOAT pPno = (PFLOAT)(&pBuf[i+4]); 34 35 _sntprintf( szFrame, _countof(szFrame), _T("%2d %d %+011.6f %+011.6f %+011.6f %+011.6f %+011.6f %+011.6ff\r"), 36 ucSensor, *pFC, pPno[0], pPno[1], pPno[2], pPno[3], pPno[4], pPno[5] ); //pPno[5]のデータを送信したい 37 tstring sF = tstring(szFrame); 38 if (g_bScroll) 39 sF += tstring(_T("\n")); 40 41 42 //UDP 43 44 char buf[256]; 45 snprintf(buf, 256, "%+011.6f", pPno[5]); //送信対象であるpPno[5]をstring型に変換 46 47 sendto(sock, buf, 5, 0, (struct sockaddr *)&addr, sizeof(addr)); 48 49 50 51 52 53 AddMsg( sF ); 54 55 i += shSize; 56 } 57 58 59 closesocket(sock); 60 61 WSACleanup(); 62 63 64} 65

C++

1 2//UDP受信側 3 4while(flag == 7) 5 { 6 //眼球測定装置の画面出力 7 cap1 >> capture; 8 cv::flip(capture,capture,1);//反転させる 9 cv::rectangle(capture, cv::Point(0,0), cv::Point(640,80), cv::Scalar(255,255,255), -1, CV_AA); 10 cv::rectangle(capture, cv::Point(0,0), cv::Point(150,480), cv::Scalar(255,255,255), -1, CV_AA); 11 cv::rectangle(capture, cv::Point(0,400), cv::Point(640, 480), cv::Scalar(255,255,255), -1, CV_AA); 12 13 //グレイ画像にする 14 cvtColor(capture, gray, CV_BGR2GRAY); 15 16 // 二値化 17 cv::threshold(gray, r, thres, 255, CV_THRESH_BINARY ); 18 //namedWindow("二値化画像"); 19 //imshow("二値化画像",img_dst); 20 21 //cvtColor(capture, hsv, CV_BGR2HSV); // 画像をRGBからHSVに変換 22 //inRange(hsv, Scalar(0, 0, 0), Scalar(179, 128, 100), r); // 色検出でマスク画像の作成 23 GaussianBlur( r, r, Size(9, 9), 2, 2 ); 24//円検出 25 if (memory_sta = 2){ 26 std::vector<cv::Vec3f> circles; 27 cv::HoughCircles(r, circles, CV_HOUGH_GRADIENT, 1, 275, 20, 40, 1, 200); 28 std::vector<cv::Vec3f>::iterator it = circles.begin(); 29 for(; it!=circles.end(); ++it) { 30 cv::Point center(cv::saturate_cast<int>((*it)[0]), cv::saturate_cast<int>((*it)[1])); 31 int radius = cv::saturate_cast<int>((*it)[2]); 32 cv::circle(capture, center, radius, cv::Scalar(0,0,255), 2); 33 mother = matX.at<float>(6,0)*center.x + matX.at<float>(7,0)*center.y + 1; 34 uv_y[0] =Point(ceil((matX.at<float>(0,0)*center.x + matX.at<float>(1,0)*center.y + matX.at<float>(2,0))/mother+anker[0].x),ceil((matX.at<float>(3,0)*center.x + matX.at<float>(4,0)*center.y + matX.at<float>(5,0))/mother)+anker[0].y); 35 36//拡大補正 37 if(uv_y[0].x <= quadrant[1].x && uv_y[0].y <= quadrant[1].y){ 38 uv_y[0] = Point(ratioX[0]*(uv_y[0].x-dst[2].x)+dst[2].x,ratioY[0]*(uv_y[0].y-dst[2].y)+dst[2].y); 39 } 40 else if(uv_y[0].x <= quadrant[2].x && uv_y[0].y > quadrant[2].y){ 41 uv_y[0] = Point(ratioX[1]*(uv_y[0].x-dst[2].x)+dst[2].x,ratioY[1]*(uv_y[0].y-dst[2].y)+dst[2].y); 42 } 43 else if(uv_y[0].x > quadrant[3].x && uv_y[0].y >= quadrant[3].y){ 44 uv_y[0] = Point(ratioX[3]*(uv_y[0].x-dst[2].x)+dst[2].x,ratioY[3]*(uv_y[0].y-dst[2].y)+dst[2].y); 45 } 46 else if(uv_y[0].x > quadrant[4].x && uv_y[0].y < quadrant[4].y){ 47 uv_y[0] = Point(ratioX[4]*(uv_y[0].x-dst[2].x)+dst[2].x,ratioY[4]*(uv_y[0].y-dst[2].y)+dst[2].y); 48 } 49 memory_sta = 0; 50 } 51 52 //UDP受信側 53 54 WSAData wsaData; 55 56 SOCKET sock; 57 struct sockaddr_in addr; 58 59 char buf[256]; 60 61 WSAStartup(MAKEWORD(2,0), &wsaData); 62 63 sock = socket(AF_INET, SOCK_DGRAM, 0); 64 65 addr.sin_family = AF_INET; 66 addr.sin_port = htons(12345); 67 addr.sin_addr.S_un.S_addr = INADDR_ANY; 68 69 bind(sock, (struct sockaddr *)&addr, sizeof(addr)); 70 71 memset(buf, 0, sizeof(buf)); 72 recv(sock, buf, sizeof(buf), 0); 73 74 z = atof(buf); //受信データをFLOAT型に変換 75 //snprintf(buf, 256, "%+011.6f", z); 76 77 printf("%+011.6f\n", z); //ここで受信データを表示させているが0になってしまう。 78 79 80 while(count1 < 1){ //初期値リセット 81 start1 = z; 82 count1++; 83 } 84 85 reset = z - start1; 86 hosei = 3.96 * reset; 87 88 z = 0; 89 90 91 92 memory_sta++; 93 count++; 94 cap >> im; 95 96 circle(im, Point(uv_y[0].x - (int)hosei , uv_y[0].y), size+10, Scalar(0,255,255), -1, CV_AA); 97 98 count = fprintf(fp,"%d %d\n",uv_y[0]); 99 100 imshow("Camera", capture); // カメラ映像の表示 101 imshow("結果", im); 102 103 104 if(GetAsyncKeyState(VK_SPACE)){ 105 fclose(fp); //ファイルクローズ 106 FILE *fp; 107 sprintf(filename,"Num%d.txt",set); 108 fp = fopen(filename, "a"); 109 set++; 110 } 111 112 113 if(GetAsyncKeyState(VK_END)){ 114 fclose(fp); //ファイルクローズ 115 break;// 任意のキー入力があれば終了 116 } 117 int key = cv::waitKey(1); 118 if(key == 113){ // 任意のキー入力があれば終了 119 break; 120 }//消すと止まるので保持 121 } 122 time_now = timeGetTime(); 123 if (time_now - time_start >= 1000){ 124 fps = (float)(count * 1000 +0.0)/(float)(time_now - time_start + 0.0); 125 time_start = timeGetTime(); 126 count = 0; 127 128 } 129 130 131 132 }

試してみたこと

受信側で、「受信->処理->受信待ち」が100ms以上掛かる場合、受信待ちのパケットがどんどん溜まっていく。
それでも、受信側は送信された順番に順次パケットを取得・処理していく。
結果、リアルタイムな通信処理はできなくなる。

と考えている。

補足情報(FW/ツールのバージョン)

送信データのサンプリングレートは60Hz

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2019/11/14 11:56

失礼ながら以前のご質問と回答以来、コード上の問題点が改善されていないように見受けられます。(sendtoの実行結果チェックとか、recvの受信結果チェックとか)その辺を先に解決すべきです。それに加えて、そもそもUDPによる送受信は途中のデータが欠落する場合もあるし、順序性も確実ではないので不適切です。(送った画像データが欠落する場合もあるので、受信側でもとに戻らなくても仕方が無い)TCPを使うべきでしょう。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問