例程使用(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 ...
随机推荐
- Apache Kafka使用默认配置执行一些负载测试来完成性能测试和基准测试
Kafka是一种分布式,分区,复制的提交日志服务.它提供了消息传递系统的功能. 我们先来看看它的消息传递术语: Kafka在称为主题的类别中维护消息的提要. 我们将调用向Kafka主题生成器发布消 ...
- HUT 排序训练赛 G - Clock
Clock Time Limit: 1000MS Memory Limit: 32768KB 64bit IO Format: %I64d & %I64u [Submit] [Go ...
- python面试导航
python面试题库 python基础 等待更新中 函数 等待更新中 面向对象 等待更新中 高级编程 等待更新中 数据库 等待更新中 前端&django 等待更新中 crm 等待更新中 drf ...
- 【题解】与查询 [51nod1406]
[题解]与查询 [51nod1406] 传送门:与查询 \([51nod1406]\) [题目描述] 给出 \(n\) 个整数,对于 \(x \in [0,1000000]\),分别求出在这 \(n\ ...
- -Shell 教程 Bash 脚本 基础语法 MD
目录 目录 Shell 简介 Shell 脚本 Shell 环境 第一个shell脚本 Shell 变量 定义变量 使用变量 只读变量 删除变量 Shell 字符串 单引号 双引号 字符串基本操作 S ...
- Codility MinMaxDivision
最近发现了一个刷题网站:https://app.codility.com/programmers/lessons 这个网站做题目时候的界面让我惊艳到了 首先这是题目界面: 然后点击start, 出来的 ...
- person类与其子类在使用中的内存情况(含java的改写和c#的屏蔽)
JAVA 普通person类及调用代码: public class Person { public String xm; public int nl; public void setme(String ...
- ElasticSearch 中文分词搜索环境搭建
ElasticSearch 是强大的搜索工具,并且是ELK套件的重要组成部分 好记性不如乱笔头,这次是在windows环境下搭建es中文分词搜索测试环境,步骤如下 1.安装jdk1.8,配置好环境变量 ...
- 【转载】C#中AddRange方法往ArrayList集合末尾添加另一个集合
ArrayList集合是C#中的一个非泛型的集合类,是弱数据类型的集合类,可以使用ArrayList集合变量来存储集合元素信息,任何数据类型的变量都可加入到同一个ArrayList集合中,如果需要往一 ...
- JS 中类型和类型转换
类型 首先明确一点,Js中的类型是针对值来说,而不是针对变量,值就是所谓的42, 'abc', false 等能用js 操作的数据.在js 中说某某某是什么数据类型,其实是说的这些值是什么类型.值呢? ...