例程使用(1-4)共享内存 存图片+vector容器教程

2019/07/27 18:13
阅读数 20

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

  

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部