zoukankan      html  css  js  c++  java
  • 例程使用(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
    

      

  • 相关阅读:
    (Java实现) 洛谷 P1106 删数问题
    (Java实现) 洛谷 P1603 斯诺登的密码
    (Java实现) 洛谷 P1036 选数
    (Java实现) 洛谷 P1012 拼数
    (Java实现) 洛谷 P1028 数的计算
    (Java实现) 洛谷 P1553 数字反转(升级版)
    (Java实现) 洛谷 P1051 谁拿了最多奖学金
    (Java实现) 洛谷 P1051 谁拿了最多奖学金
    (Java实现) 洛谷 P1106 删数问题
    目测ZIP的压缩率
  • 原文地址:https://www.cnblogs.com/kekeoutlook/p/11256163.html
Copyright © 2011-2022 走看看