例程使用(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
例程使用(1-4)共享内存 存图片+vector容器教程的更多相关文章
- vector存入共享内存(了解)
昨天在上篇blog里描写了如何把STL容器放到共享内存里去,不过由于好久不写blog,发觉词汇组织能力差了很多,不少想写的东西写的很零散,今天刚好翻看自己的书签,看到一篇挺老的文章,不过从共享内存到S ...
- Linux共享内存(一)
inux系统编程我一直看 <GNU/LINUX编程指南>,只是讲的太简单了,通常是书和网络上的资料结合着来掌握才比较全面 .在掌握了书上的内容后,再来都其他资料 . 原文链接 http:/ ...
- 进程间通信机制(管道、信号、共享内存/信号量/消息队列)、线程间通信机制(互斥锁、条件变量、posix匿名信号量)
注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料如<linux内核完全剖析>.<linux c 编程一站式学习>等,只是为了更好 ...
- Linux进程间通信—共享内存
五.共享内存(shared memory) 共享内存映射为一段可以被其他进程访问的内存.该共享内存由一个进程所创建,然后其他进程可以挂载到该共享内存中.共享内存是最快的IPC机制,但由于linux本身 ...
- <转>UNIX 共享内存应用中的问题及解决方法
http://www.ibm.com/developerworks/cn/aix/library/au-cn-sharemem/ 共享内存是一种非常重要且常用的进程间通信方式,相对于其它IPC机制,因 ...
- Linux学习笔记(14)-进程通信|共享内存
在Linux中,共享内存是允许两个不相关的进程访问同一个逻辑内存的进程间通信方法,是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式. 不同进程之间共享的内存通常安排为同一段物理内存.进程可 ...
- mmap和shm共享内存的区别和联系
共享内存的创建 根据理论: 1. 共享内存允许两个或多个进程共享一给定的存储区,因为数据不需要来回复制,所以是最快的一种进程间通信机制.共享内存可以通过mmap()映射普通文件(特殊情况下还可以采用匿 ...
- linux进程间通信-共享内存
转载:http://www.cnblogs.com/fangshenghui/p/4039720.html 一 共享内存介绍 共享内存可以从字面上去理解,就把一片逻辑内存共享出来,让不同的进程去访问它 ...
- Linux IPC POSIX 共享内存
模型 #include <unistd.h> //for fstat() #include <sys/types.h> //for fstat() #include <s ...
随机推荐
- AntDesign vue学习笔记(四)使用组件切换
同样实现上一篇功能, 改为使用组件切换,实现方法如下 1.修改MainFrm中的<router-view/>如下代码 2.注册局部组件 export default { name: 'Ma ...
- js实现对上传图片的路径转成base64编码,并且对图片进行压缩,实现预览功能1
参考 https://blog.csdn.net/qq_31965515/article/details/82975381 https://www.cnblogs.com/zhangdiIT/p/78 ...
- AQS工作原理分析
AQS工作原理分析 一.大致介绍1.前面章节讲解了一下CAS,简单讲就是cmpxchg+lock的原子操作:2.而在谈到并发操作里面,我们不得不谈到AQS,JDK的源码里面好多并发的类都是通过Sy ...
- seleium 之 EC 的用法
场景 Expected Conditions的使用场景有2种 直接在断言中使用 与WebDriverWait配合使用,动态等待页面上元素出现或者消失 方法注释 先翻译一下这些方法的用法 title_i ...
- MySQL一主二从复制环境切换主从库
假设有一个一主二从的环境,当主库M出现故障时,需要将其中一个从库S1切换为主库,同时将S2指向新的主库S1,如果可能,需要将故障的主库M修复并重置为新的从库. 搭建一主二从复制环境可参考:mysql5 ...
- Sass和Less的区别?
这篇文章主要解答以下几个问题,供前端开发者的新手参考. 1.什么是Sass和Less? 2.为什么要使用CSS预处理器? 3.Sass和Less的比较 4.为什么选择使用Sass而不是Less? 什么 ...
- 《微信小程序项目开发实战:用WePY、mpvue、Taro打造高效的小程序》(笔记1)WePY开发环境的安装
WePY的安装或更新都通过npm进行,全局安装或更新WePY命令行工具,使用以下命令: npm install wepy-cli -g 稍等片刻,成功安装后,即可创建WePY项目. 注意:如果npm安 ...
- Spring Boot加载application.properties配置文件顺序规则
SpringApplication会从以下路径加载所有的application.properties文件: 1.file:./config/(当前目录下的config文件夹) 2.file:./(当前 ...
- react的事件处理为什么要bind this 改变this的指向?
react的事件处理会丢失this,所以需要绑定,为什么会丢失this? 首先来看摘自官方的一句话: You have to be careful about the meaning of this ...
- 使用代码获得Hybris Commerce里显示的产品图片
使用下面这个API去取Hybris Commerce系统里产品主数据的明细信息: https://:9002/rest/v2/electronics/products/300938?fields=FU ...