1传输的数据
1-1数据格式说明
1 两路视频图像Mat
图像 图像数据(Mat)+图像头信息(ImgInf)
//图像的宽、高、类型信息
typedef struct
{
int width; //4个字节
int height;
int type;
}ImgInf;
2 单个TrackBox
(假设单个目标检测框)
typedef struct
{
int x;
int y;
int width;
int height;
int flag;
}TrackBox; //20个字节
3 每路视频得 vector<TrackBox> VTrackBox; (所有目标检测框集合)
1-2数据分配位置
//--------------------------------共享内存大小确定--------------------------------------
//1-1为BOX分配的空间
#define BOX_SIZE sizeof(TrackBox) // TrackBox结构体大小
//1-2为BOX数组分配
#define MAT_BOXVEC_NUMBER 2 //几路视频就有多少对应的检测数组
#define MAT_BOX_NUMBER 100 // 一个容器里假设最大有100个TrackBox(20个字节) 2000个字节
#define MAT_BOX_VECTOR MAT_BOX_NUMBER*BOX_SIZE
//1-3为图片分配的空间
#define FRAME_NUMBER 2 // 图像输入路数
#define FRAME_W_H 1920*1080 // 图像分辨率
#define FRAME_SIZE FRAME_W_H*sizeof(unsigned char)*3+sizeof(ImgInf) // 图像彩色图(三通道)+ 图像信息结构体
//--------------------------------共享内存位置分配--------------------------------------
//各路图像所在共享内存位置
#define MAT_DATA1 FRAME_SIZE*0 //存MAT_DATA1 pBuf+FRAME_SIZE*1 - pBuf+FRAME_SIZE*1+sizeof(Mat)
#define MAT_DATA2 FRAME_SIZE*1 //存MAT_DATA1 pBuf+FRAME_SIZE*2 - pBuf+FRAME_SIZE*1+sizeof(Mat)
#define MAT_DATA1_BOX FRAME_SIZE*2
#define MAT_DATA2_BOX FRAME_SIZE*2+MAT_BOX_VECTOR
//BOX_DATA所在共享内存位置
#define BOX_DATA FRAME_SIZE*FRAME_NUMBER + MAT_BOX_VECTOR*MAT_BOXVEC_NUMBER //数据存储的起始位置 存BOX_DATA pBuf+FRAME_SIZE*0 - pBuf+FRAME_SIZE*0+sizeof(TrackBox)
//总空间大小
#define MEMORY_SIZE FRAME_SIZE*FRAME_NUMBER+MAT_BOX_VECTOR*MAT_BOXVEC_NUMBER+BOX_SIZE
缺陷,没有加入标志位,用来同步两个节点的存取
2工程文件
2-1发送端
main.cpp
#pragma once
#ifndef MAIN
#define MAIN
/* 1包含文件 */
//1.1 系统 必选
#include<iostream>
#include<Windows.h>
#include "../Include/ShareMemray.h"
//1.2 opencv 可选
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
TrackBox BOX1;
vector<TrackBox> VTrackBox1;
/* 4 测试 鼠标点击输出 x y 存入共享内存 */
//4.1 鼠标事件
void onMouse(int event, int x, int y, int flags, void* param)
{
//cout << "flag =" << flag << endl;
Mat *im = reinterpret_cast<Mat*>(param);
switch (event)
{
case CV_EVENT_LBUTTONDOWN: //鼠标左键按下响应:返回坐标和灰度
BOX1.x = x;
BOX1.y = y;
BOX1.flag = flags;
break;
}
}
// 4.2 读取视频
int imge_test(SHAREDMEMORY sharesend) {
VideoCapture capture(0);
if (!capture.isOpened())
{
return -1;
}
Mat frame;
capture.set(CV_CAP_PROP_FRAME_WIDTH, 1920);
capture.set(CV_CAP_PROP_FRAME_HEIGHT, 1080);
bool stop = false;
while (1)
{
//flag = 0;
capture >> frame;
cvNamedWindow("当前视频", 0);
resize(frame, frame, Size(1920, 1080));
//Sleep(10);
cvSetMouseCallback("当前视频", onMouse, &frame);
imshow("当前视频", frame);
waitKey(1);
if (BOX1.flag == 1)
{
// 1发送单个BOX1
sharesend.SendBox(BOX1);
cout << "at(" << BOX1.x << "," << BOX1.y << ")" << "flag =" << BOX1.flag <<" h "<< BOX1.height<< " w "<< BOX1.width << endl;
// 2发送多个BOX(容器)
VTrackBox1.clear();
// 不能加resize 否则不出图
for (int i = 0; i <MAT_BOX_NUMBER; i++)
{
BOX1.width = i;
BOX1.height = i;
VTrackBox1.push_back(BOX1);
}
sharesend.SendVectorBox(VTrackBox1);
BOX1.flag = 0;
}
// 3发送图片
sharesend.SendMat(frame,MAT_DATA1);
}
}
int main()
{
//共享内存初始化
SHAREDMEMORY sharesend;
sharesend.intShareroom();
//共享内存发送信息
imge_test(sharesend);
//共享内存释放
sharesend.stop();
return 0;
}
#endif
2-2接收端
#include <windows.h>
#include<iostream>
#include "../Include/ShareMemray.h"
using namespace std;
TrackBox recBOX;
void main() {
SHAREDMEMORY sharerec;
sharerec.intShareroom();
while (true)
{
//1 接收单个box
sharerec.RecBox(recBOX);
if (recBOX.flag != 0) // 标志位判断数据是否有效
{
//2 接受多个box(容器)
vector<TrackBox> VTrackBoxrec;
// 必须resize 否则没有空间无法储存
VTrackBoxrec.resize(MAT_BOX_NUMBER);
sharerec.RecieveVectorBox(VTrackBoxrec);
for (auto &i : VTrackBoxrec)
{
cout << "x " << i.x << " y " << i.y << " h " << i.height << " w " << i.width << endl;
}
}
Mat frame=sharerec.RecieveMat(MAT_DATA1);
if (!frame.empty())
{
namedWindow("show", 0);
imshow("show", frame);
waitKey(1);
}
}
sharerec.stop();
}
2-2接收端
#include <windows.h>
#include<iostream>
#include "../Include/ShareMemray.h"
using namespace std;
TrackBox recBOX;
void main() {
SHAREDMEMORY sharerec;
sharerec.intShareroom();
while (true)
{
//1 接收单个box
sharerec.RecBox(recBOX);
if (recBOX.flag != 0) // 标志位判断数据是否有效
{
//2 接受多个box(容器)
vector<TrackBox> VTrackBoxrec;
// 必须resize 否则没有空间无法储存
VTrackBoxrec.resize(MAT_BOX_NUMBER);
sharerec.RecieveVectorBox(VTrackBoxrec);
for (auto &i : VTrackBoxrec)
{
cout << "x " << i.x << " y " << i.y << " h " << i.height << " w " << i.width << endl;
}
}
Mat frame=sharerec.RecieveMat(MAT_DATA1);
if (!frame.empty())
{
namedWindow("show", 0);
imshow("show", frame);
waitKey(1);
}
}
sharerec.stop();
}
2-3 共享内存文件
使用过程
配置过程
0-0工程包含这个两个文件
0-1给共享内存取个名字
0-2根据发送的数据,开辟总空间大小,分配各个数据在总空间得存储位置
1 共享内存初始化
SHAREDMEMORY sharesend;
sharesend.intShareroom();
2 发送和接收数据,给例程给了三种数据的收发
3 应该加入同步策略,通过一个标志位来决定什么时候收发。
4 最后释放共享内内存
工程文件
ShareMemray.h
#pragma once
#ifndef ShareMemray_H
#define ShareMemray_H
#include<iostream>
#include<Windows.h>
#include <stdio.h>
#include <cstdio>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
//--------------------------------共享内存数据类型--------------------------------------
//目标检测的上下顶点;
typedef struct
{
int x;
int y;
int width;
int height;
int flag;
}TrackBox; //20个字节
//图像的宽、高、类型信息
typedef struct
{
int width; //4个字节
int height;
int type;
}ImgInf;
//图像的数据信息 单通道和三通道
//Mat
//--------------------------------共享内存大小确定--------------------------------------
//1-1为BOX分配的空间
#define BOX_SIZE sizeof(TrackBox) // TrackBox结构体大小
//1-2为BOX数组分配
#define MAT_BOXVEC_NUMBER 2 //几路视频就有多少对应的检测数组
#define MAT_BOX_NUMBER 100 // 一个容器里假设最大有100个TrackBox(20个字节) 2000个字节
#define MAT_BOX_VECTOR MAT_BOX_NUMBER*BOX_SIZE
//1-3为图片分配的空间
#define FRAME_NUMBER 2 // 图像输入路数
#define FRAME_W_H 1920*1080 // 图像分辨率
#define FRAME_SIZE FRAME_W_H*sizeof(unsigned char)*3+sizeof(ImgInf) // 图像彩色图(三通道)+ 图像信息结构体
//--------------------------------共享内存位置分配--------------------------------------
//各路图像所在共享内存位置
#define MAT_DATA1 FRAME_SIZE*0 //存MAT_DATA1 pBuf+FRAME_SIZE*1 - pBuf+FRAME_SIZE*1+sizeof(Mat)
#define MAT_DATA2 FRAME_SIZE*1 //存MAT_DATA1 pBuf+FRAME_SIZE*2 - pBuf+FRAME_SIZE*1+sizeof(Mat)
#define MAT_DATA1_BOX FRAME_SIZE*2
#define MAT_DATA2_BOX FRAME_SIZE*2+MAT_BOX_VECTOR
//BOX_DATA所在共享内存位置
#define BOX_DATA FRAME_SIZE*FRAME_NUMBER + MAT_BOX_VECTOR*MAT_BOXVEC_NUMBER //数据存储的起始位置 存BOX_DATA pBuf+FRAME_SIZE*0 - pBuf+FRAME_SIZE*0+sizeof(TrackBox)
//总空间大小
#define MEMORY_SIZE FRAME_SIZE*FRAME_NUMBER+MAT_BOX_VECTOR*MAT_BOXVEC_NUMBER+BOX_SIZE
class SHAREDMEMORY {
public:
HANDLE hMapFile;
LPCTSTR pBuf;
TCHAR szName[30] = TEXT("Local\\FHY_SYSTEM_0"); //指向同一块共享内存的名字
//TrackBox BOX;
//vector<TrackBox> VTrackBox; //为了共享内存传输,必须开始初始化最大
public:
//1 初始化
int intShareroom();
void SendBox(TrackBox &BOX);
void RecBox(TrackBox &BOX);
void SendVectorBox(vector<TrackBox> &VTrackBox);
void RecieveVectorBox(vector<TrackBox> &VTrackBox);
void SendMat(cv::Mat img, char indexAddress);
Mat RecieveMat(char indexAddress);
void stop();
};
#endif //SHAREDMEMORY_HPP
ShareMemray.cpp
#pragma once
#ifndef ShareMemray_CPP
#define ShareMemray_CPP
#include "ShareMemray.h"
//3.2 初始化
int SHAREDMEMORY::intShareroom() {
hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MEMORY_SIZE ,szName);
if (hMapFile == NULL)
{
cout <<"Could not create file mapping object" << GetLastError() << endl;
return 1;
}
pBuf = (LPTSTR)MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
MEMORY_SIZE);
if (pBuf == NULL)
{
cout << "Could not map view of file" << GetLastError() << endl;
CloseHandle(hMapFile);
return 1;
}
// 容器初始化
//VTrackBox.resize(MAT_BOX_NUMBER);
}
/**************************************************
功能: 发送单个结构体
输入:
TrackBox &BOX 1结构体
(char*)pBuf+ BOX_DATA 2结构体存在的位置
sizeof(TrackBox) 3结构体大小()
***************************************************/
void SHAREDMEMORY::SendBox(TrackBox &BOX) {
memcpy((char*)pBuf+ BOX_DATA, &BOX, sizeof(TrackBox));
}
/**************************************************
功能: 接收单个结构体
输入:
TrackBox &BOX 1结构体
(char*)pBuf+ BOX_DATA 2结构体存在的位置
sizeof(TrackBox) 3结构体大小()
***************************************************/
void SHAREDMEMORY::RecBox(TrackBox &BOX) {
memcpy(&BOX, (char*)pBuf+ BOX_DATA, sizeof(TrackBox));
}
/**************************************************
*name :void SendVectorBox(vector<TrackBox> VTrackBox)
*function :发送容器,结构体序列序列
输入:
vector<TrackBox> VTrackBox 1要存得容器
(char*)pBuf + MAT_DATA1_BOX 2结构体序列得起始位置
number*sizeof(TrackBox) 3每一个结构体依次往后递增存储位置
sizeof(TrackBox) 4单个结构体大小
输出: 无
说明:
1每次调用前清空容器
2采用auto &i : VTrackBox 访问容器,确保容器提前resize足够固定空间,否则无法存 VTrackBox.resize(MAT_BOX_NUMBER);
即使这样,循环访问索引还是会出错,最好固定数目MAT_BOX_NUMBER 而非用 VTrackBox.size()
正确 for (int i = 0; i <100; i++)
出问题 for (int i = 0; i <VTrackBox.size(); i++)
**************************************************/
void SHAREDMEMORY::SendVectorBox(vector<TrackBox> &VTrackBox) {
int number = 0;
for (auto &i : VTrackBox) {
//cout << number << " "<< i.x <<endl;
memcpy((char*)pBuf + MAT_DATA1_BOX + number*sizeof(TrackBox), &i, sizeof(TrackBox));
number++;
}
//VTrackBox.clear();
//VTrackBox.resize(MAT_BOX_NUMBER);
}
/**************************************************
*name :void RecieveVectorBox(vector<TrackBox> VTrackBox)
*function :接受容器序列
输入:
vector<TrackBox> VTrackBox 要接受的容器
输出: 无
**************************************************/
void SHAREDMEMORY::RecieveVectorBox(vector<TrackBox> &VTrackBox)
{
//VTrackBox.clear();
//VTrackBox.resize(MAT_BOX_NUMBER);
int number = 0;
for (auto &i : VTrackBox) {
memcpy(&i ,(char*)pBuf + MAT_DATA1_BOX + number*sizeof(TrackBox), sizeof(TrackBox));
number++;
}
}
/**************************************************
*name :int SharedMemory::sendMat(Mat img, int index)
*function :发送Mat图像
输入:
Mat img 要存得图像
char indexAddress 图像要存得位置
输出: 无
**************************************************/
void SHAREDMEMORY::SendMat(cv::Mat img, char indexAddress)
{
ImgInf ImgHead;
ImgHead.width = img.cols;
ImgHead.height = img.rows;
ImgHead.type = img.type();
if (ImgHead.type == CV_64FC1)
{
memcpy((char*)pBuf + indexAddress, &ImgHead, sizeof(ImgInf));
memcpy((char*)pBuf + indexAddress + sizeof(ImgInf), img.data, img.cols * img.rows * img.channels() * sizeof(double));
}
else
{
memcpy((char*)pBuf + indexAddress, &ImgHead, sizeof(ImgInf));
memcpy((char*)pBuf + indexAddress + sizeof(ImgInf), img.data, img.cols * img.rows * img.channels());
}
}
/**************************************************
*name :int SharedMemory::recieveMat(int index)
*function :接收Mat图像
*参数:
输入:char indexAddress 要取得图像首地址
输出: Mat 类型图像
**************************************************/
cv::Mat SHAREDMEMORY::RecieveMat(char indexAddress)
{
ImgInf ImgHead;
cv::Mat img;
memcpy(&ImgHead, (char*)pBuf+indexAddress, sizeof(ImgInf));
img.create(ImgHead.height, ImgHead.width, ImgHead.type);
if (ImgHead.type == CV_64FC1)
{
memcpy(img.data, (char*)pBuf+indexAddress + sizeof(ImgInf), img.cols * img.rows * img.channels() * sizeof(double));
}
else
{
memcpy(img.data, (char*)pBuf+indexAddress + sizeof(ImgInf), img.cols * img.rows * img.channels());
}
return img;
}
void SHAREDMEMORY::stop() {
UnmapViewOfFile(pBuf); //释放;
CloseHandle(hMapFile);
}
#endif