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


    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
    

      

  • 相关阅读:
    博客阅读计数优化
    博客阅读简单计数
    博客后台富文本编辑
    博客分类统计
    Django关联关系查询
    上下篇博客,按月归档
    浅谈闭包以及常见面试题
    浅谈前端缓存(转至大佬)
    post请求头的常见类型
    浅谈RegExp 对象的方法
  • 原文地址:https://www.cnblogs.com/kekeoutlook/p/11256163.html
Copyright © 2020-2023  润新知