配置
这里采用的是 VS2017 之前写过一个Python的版本 https://blog.csdn.net/a19990412/article/details/80930725
首先得先下载一下opencv,然后简单配置一下。别担心,这个步骤操作就点击下三下鼠标就好了(但是如果是想换一个安装路径什么的,可能会多一点点的 不过基本上非常简单。)根据https://blog.csdn.net/a19990412/article/details/79768775 就可以完成配置了。如果遇到问题了,请务必在评论取留言,或者是私信我。是看不出对方是什么qq头像之类的,没必要担心,我也认不出是谁。
文章目录
配置实现代码解释解释下服务端的代码解释下客户端的代码图片和网络数据的转换工作从Mat到数据包
运行方法IP地址获取
实现
服务器代码(就是那个用有摄像头的那个电脑要运行的代码)
要把下面这个代码中的sockAddr.sin_addr.S_un.S_addr = inet_addr("192.168.199.222");192.168.199.222换成有摄像头的电脑自己的ip地址(不用担心 怎么获得ip地址,在最后,我会说了,其实非常简单的。)关闭这个文件的话,我这里只是设置了强制更新的。没有设置自己关掉的方法。
#include "opencv2/opencv.hpp"
#include
#include
#pragma comment (lib, "ws2_32.lib") //加载 ws2_32.dll
#pragma warning(disable : 4996)
//待传输图像默认大小为 640*480,可修改
#define IMG_WIDTH 640 // 需传输图像的宽
#define IMG_HEIGHT 480 // 需传输图像的高
//默认格式为CV_8UC3
#define BUFFER_SIZE IMG_WIDTH*IMG_HEIGHT*3/32
using namespace cv;
struct sentbuf{
char buf[BUFFER_SIZE];
int flag;
};
sentbuf data;
void sendMat(SOCKET sockClient, Mat image);
int main(int, char**)
{
VideoCapture cap(0); // open the default camera
if (!cap.isOpened()) // check if we succeeded
return -1;
Mat frame;
//初始化 DLL
WSADATA wsaData;
::WSAStartup(MAKEWORD(2, 0), &wsaData);
//创建套接字
SOCKET servSock = ::socket(AF_INET, SOCK_STREAM, 0);
//绑定套接字
sockaddr_in sockAddr;
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.S_un.S_addr = inet_addr("192.168.199.222");
sockAddr.sin_port = htons(1234);
::bind(servSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
//进入监听状态
listen(servSock, 5);
//接收客户端请求
SOCKADDR clntAddr;
int nSize = sizeof(SOCKADDR);
SOCKET clntSock = accept(servSock, (SOCKADDR*)&clntAddr, &nSize);
std::cout
for (int k = 0; k
int num2 = i * IMG_WIDTH * 3;
uchar* ucdata = image.ptr(i + num1);
for (int j = 0; j
char buf[BUFFER_SIZE];
int flag;
};
recvbuf data_recv;
Mat recieveMat(SOCKET sockServer);
int main() {
//初始化 DLL
WSADATA data;
WORD w = MAKEWORD(2, 0);
::WSAStartup(w, &data);
// 创建套接字
SOCKET s;
s = ::socket(AF_INET, SOCK_STREAM, 0);
// 构造ip地址
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.S_un.S_addr = inet_addr("192.168.199.222");
addr.sin_port = htons(1234);
std::cout
Mat img(IMG_HEIGHT, IMG_WIDTH, CV_8UC3, cv::Scalar(0));
int needRecv = sizeof(recvbuf);
int count = 0;
for (int i = 0; i
len0 = recv(sockServer, (char*)(&data_recv) + pos, needRecv - pos, 0);
pos += len0;
}
count = count + data_recv.flag;
int num1 = IMG_HEIGHT / 32 * i;
for (int j = 0; j
ucdata[k] = data_recv.buf[num2 + k];
}
}
if (data_recv.flag == 2) {
if (count == 33) {
return img;
}
else {
count = 0;
i = 0;
}
}
}
}
代码解释
解释下服务端的代码
服务端的代码,就是指运行在有摄像头的那个电脑的代码。一开始的三行都是导入头文件。(如果你之前配置好了opencv这里就是没有问题的)第四行,导入了一个winsock的包,这个包,是为了使用网络通信技术之后,就是定义了几个常量(IMG_WIDTH,IMG_HEIGHT,BUFFER_SIZE)就是定义了几个数而已。using namespace cv; 是使用opencv的名空间(这个意思就是说,使用什么作为关键字符,比如,之前cout,这是个关键字,但是,这个的名空间是std)之后创建一个结构体,这个你可以参照Python中的类的概念。(如果你也没学过类的话,就把这个理解为一个盒子(然后,我们在这个盒子里面放东西),以后定义新的元素的时候(像以前定义int,double之类的东西的时候,这里就直接定义一个))所以说,在定义完的下面就有一行,写着sentbuf data;。之后的话,就是写了一个函数的声明(定义放在了下面)。原因这里要跟Python区别一下。 Python的话,函数放在一个文件里,那就是可以找到的,但是c++不一样,就是必须要在函数调用之前就有了才能调用的。但是这样写就会很丑,所以我这里才会先写一个函数声明,最后再写函数定义。进入到main函数(注意到,有些时候我是写了参数的int, char**。但是实际上,没区别的。。)VideoCapture是一个摄像头类然后,来确定一下,是否是打开的,如果是打开的,就是继续。Mat(其实是一个矩阵)在这里是为了存一个图(这个矩阵不是二维的,其实是三维的,还多加了一堆东西的)之后的,什么初始化DLL之类的。没关系,反正我也记不住。但是这个,都很简单的,大致流程copy一下就好了。重点在那个换ip地址的(是的,我现在还没告诉你怎么看ip地址)accept(servSock, (SOCKADDR*)&clntAddr, &nSize); 函数,必须在,有其他ip地址来连接到这个上面之后,才会继续,否则,整个代码就会一直定在这。(所以,后面输出了那个linked 的时候,才表示连接成功了)一直到for(;;)就是创建一个无限循环,一直在读取摄像头的图片,然后用那个函数给发出去。最后的关闭什么的 都是套路,顺着来就好了。
解释下客户端的代码
就是那个看另外一个电脑摄像头信息的电脑运行的代码。讲道理,前面都是基本一模一样的。区别在于std::cout |