Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;通过套接字发送OpenCV图像_C++_Sockets_Opencv_Streaming_Mat - Fatal编程技术网

C++ C++;通过套接字发送OpenCV图像

C++ C++;通过套接字发送OpenCV图像,c++,sockets,opencv,streaming,mat,C++,Sockets,Opencv,Streaming,Mat,我正在尝试使用OpenCV和套接字实现流媒体服务。服务器端加载给定的映像并将其发送给客户端,客户端通过套接字接收并显示该映像。但是,我遇到了很多麻烦,发送图像的数据并在客户端重建它。这是我迄今为止编写的代码: 图像发送者: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #inclu

我正在尝试使用OpenCV和套接字实现流媒体服务。服务器端加载给定的映像并将其发送给客户端,客户端通过套接字接收并显示该映像。但是,我遇到了很多麻烦,发送图像的数据并在客户端重建它。这是我迄今为止编写的代码:

图像发送者:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> 
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

using namespace cv;
using namespace std;

void error(const char *msg)
{
    perror(msg);
    exit(0);
}

int main(int argc, char *argv[])
{
    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;

    char buffer[256];
    if (argc < 3) {
       fprintf(stderr,"usage %s hostname port\n", argv[0]);
       exit(0);
    }
    portno = atoi(argv[2]);
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) 
        error("ERROR opening socket");
    server = gethostbyname(argv[1]);
    if (server == NULL) {
        fprintf(stderr,"ERROR, no such host\n");
        exit(0);
    }
    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    bcopy((char *)server->h_addr, 
         (char *)&serv_addr.sin_addr.s_addr,
         server->h_length);
    serv_addr.sin_port = htons(portno);
    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) 
        error("ERROR connecting");

    Mat image;
    image = imread(argv[3], CV_LOAD_IMAGE_COLOR);
    if(! image.data )                              // Check for invalid input
    {
        cout <<  "Could not open or find the image" << std::endl ;
        return -1;
    }

    n = write(sockfd,image.data,image.total()*image.channels());
    if (n < 0) 
         error("ERROR writing to socket");
    close(sockfd);

    namedWindow( "Client", CV_WINDOW_AUTOSIZE );// Create a window for display.
    imshow( "Client", image );  
    waitKey(0);
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间cv;
使用名称空间std;
无效错误(常量字符*消息)
{
佩罗尔(味精);
出口(0);
}
int main(int argc,char*argv[])
{
int sockfd,端口号,n;
服务地址中的结构sockaddr\u;
结构主机*服务器;
字符缓冲区[256];
如果(argc<3){
fprintf(stderr,“使用%s主机名端口,\n”,argv[0]);
出口(0);
}
portno=atoi(argv[2]);
sockfd=套接字(AF_INET,SOCK_STREAM,0);
if(sockfd<0)
错误(“打开套接字时出错”);
server=gethostbyname(argv[1]);
如果(服务器==NULL){
fprintf(stderr,“错误,没有这样的主机\n”);
出口(0);
}
bzero((char*)&serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
b复制((字符*)服务器->h_地址,
(char*)和serv_addr.sin_addr.s_addr,
服务器->h_长度);
serv_addr.sin_port=htons(端口号);
if(connect(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0)
错误(“连接错误”);
Mat图像;
image=imread(argv[3],CV\u LOAD\u image\u COLOR);
if(!image.data)//检查输入是否无效
{

cout缓冲区溢出。我不确定图像的格式和大小是否相同->你应该诚实地序列化你的Mat,什么的。

获取
Mat.data
并直接发送到套接字,数据顺序是BGR BGR BGR…在接收端,假设你知道图像的大小。接收后,只分配接收到的缓冲区(BGR BGR…阵列)到
Mat

客户端:-

Mat frame;
frame = (frame.reshape(0,1)); // to make it continuous

int  imgSize = frame.total()*frame.elemSize();

// Send data here
bytes = send(clientSock, frame.data, imgSize, 0))
Mat  img = Mat::zeros( height,width, CV_8UC3);
int  imgSize = img.total()*img.elemSize();
uchar sockData[imgSize];

//Receive data here

for (int i = 0; i < imgSize; i += bytes) {
    if ((bytes = recv(connectSock, sockData +i, imgSize  - i, 0)) == -1)  {
        quit("recv failed", 1);
    }
}

// Assign pixel value to img
int ptr=0;
for (int i = 0;  i < img.rows; i++) {
    for (int j = 0; j < img.cols; j++) {                                     
       img.at<cv::Vec3b>(i,j) = cv::Vec3b(sockData[ptr+ 0],sockData[ptr+1],sockData[ptr+2]);
       ptr=ptr+3;
    }
}
服务器:-

Mat frame;
frame = (frame.reshape(0,1)); // to make it continuous

int  imgSize = frame.total()*frame.elemSize();

// Send data here
bytes = send(clientSock, frame.data, imgSize, 0))
Mat  img = Mat::zeros( height,width, CV_8UC3);
int  imgSize = img.total()*img.elemSize();
uchar sockData[imgSize];

//Receive data here

for (int i = 0; i < imgSize; i += bytes) {
    if ((bytes = recv(connectSock, sockData +i, imgSize  - i, 0)) == -1)  {
        quit("recv failed", 1);
    }
}

// Assign pixel value to img
int ptr=0;
for (int i = 0;  i < img.rows; i++) {
    for (int j = 0; j < img.cols; j++) {                                     
       img.at<cv::Vec3b>(i,j) = cv::Vec3b(sockData[ptr+ 0],sockData[ptr+1],sockData[ptr+2]);
       ptr=ptr+3;
    }
}
Mat img=Mat::零(高度、宽度、CV_8UC3);
int imgSize=img.total()*img.elemSize();
uchar sockData[imgSize];
//在这里接收数据
for(int i=0;i
此语句在Visual Studio 12中出现错误。它说。。 错误:“uchar*”类型的参数与“const char*”类型的参数不兼容
在“frame.data”中,

Haris的回答是正确的,对我来说很有用。但是,除了服务器代码(从uchar数据构建图像)之外,您还可以使用较短的格式:

int  imgSize = img.total()*img.elemSize();
uchar sockData[imgSize];

for (int i = 0; i < imgSize; i += bytes) {
    if ((bytes = recv(connectSock, sockData +i, imgSize  - i, 0)) == -1)
        quit("recv failed", 1);
}

// change the last loop to below statement
Mat img(Size(HEIGHT, WIDTH), CV_8UC3, socketData);
int imgSize=img.total()*img.elemSize();
uchar sockData[imgSize];
for(int i=0;i
在Microsoft Visual Studio 2012中,我在sockData[imgSize]中的imgSize下有一条红线,表示表达式必须有一个常量值。然后我将int-imgSize更改为const-int-imgSize。它仍然显示相同的问题

 Mat img = Mat::zeros(100,100, CV_8UC3);
 const int imgSize = img.total()*img.elemSize();
 uchar sockData[imgSize];

1024还不够?或者你的意思是在发送方?那么我应该放什么?9999999?这节省了我的时间。非常感谢,现在可以很好地工作了。不过最后一个问题。在服务器端,我必须初始化“字节”到某个值。我只是在接收循环数据之前添加了int bytes=0。对吗?我的意思是,它可以工作,但我不知道它是否正确。再次感谢:您可以用0初始化,这不是问题。实际上,字节用于检查recv()调用是否成功。成功完成后,recv()应返回以字节为单位读取的消息长度。如果没有可接收的消息,且对等方已执行有序关机,则recv()应返回0。否则,应返回-1。我强烈建议在通过套接字发送之前将数据编码到
JPEG
PNG
。它可以显著减小大小(JPEG 10%,PNG 25%),因此最好编码到PNG,不是吗?如果编码,是否仍应进行重新整形?