上面我的博客C#共享内存方式读写数据及图像_jiugeshao的专栏-CSDN博客演示了c#往共享内存里写入图片和读取图片,接下来讲解如何用python去读取由c#写入到共享内存里的图片。
1. 创建两个文件example.h和example.cpp。(两个文件如何创建及代码中引用路径说明见下面,不要懵圈了)
example.h中代码如下:
#pragma once
#include <Python.h>
#include <iostream>
#include <string>
#include <C:\Anaconda3\Lib\site-packages\numpy\core\include\numpy\ndarrayobject.h>
#include <C:\Anaconda3\Lib\site-packages\numpy\core\include\numpy\arrayobject.h>
using namespace std;
void say_hello();
int add(int a, int b);
int sub(int a, int b);
PyObject* GetImageFromSM(const char* sharedMemoryName, int height, int width, int channel);
example.cpp中代码如下:
#include "example.h"
#include <windows.h>
void say_hello()
{
std::cout << "hello" << std::endl;
}
int add(int a, int b)
{
return(a + b);
}
int sub(int a, int b)
{
return(a - b);
}
LPCWSTR sToW(std::string src)
{
size_t srcsize = src.length() + 1;
size_t c = 0;
wchar_t *wc = new wchar_t[srcsize];
mbstowcs_s(&c, wc, srcsize, src.c_str(), _TRUNCATE);
return wc;
}
PyObject* GetImageFromSM(const char* sharedMemoryName, int height, int width, int channel)
{
//channel表示为通道数,支持1和3
Py_Initialize();
if (!Py_IsInitialized())
{
std::cout << "error";
}
std::cout << "start to get image from sharememory" << std::endl;
if (PyArray_API == NULL)
{
import_array();
}
std::string MN = sharedMemoryName;
LPCWSTR MemoryName_lpcwstr = sToW(MN);
std::cout << MN << std::endl;
std::cout << MemoryName_lpcwstr << std::endl;
HANDLE shareMemoryMap = NULL;
shareMemoryMap = ::OpenFileMappingW(FILE_MAP_ALL_ACCESS, 0, MemoryName_lpcwstr);
delete[] MemoryName_lpcwstr;
MemoryName_lpcwstr = NULL;
int DataLength = width * height * channel;
std::cout << "Data Length: " << DataLength << std::endl;
LPVOID pData = nullptr;
pData = ::MapViewOfFile(shareMemoryMap, FILE_MAP_ALL_ACCESS, 0, 0, DataLength);
if (pData != NULL)
{
std::cout << "share memory has been created" << std::endl;
}
else
{
std::cout << "error" << std::endl;
}
PyObject* numpyData = nullptr;
npy_intp nd[3] = { 0, 0, 0 };
if (channel == 1)
{
//单通道灰度图
std::cout << "channel 1" << std::endl;
nd[0] = height;
nd[1] = width;
numpyData = PyArray_SimpleNewFromData(2, nd, NPY_UBYTE, pData);
}
else
{
//三通道彩色图
std::cout << "channel 3" << std::endl;
nd[0] = height;
nd[1] = width;
nd[2] = 3;
numpyData = PyArray_SimpleNewFromData(3, nd, NPY_UBYTE, pData);
}
std::cout << "over" << std::endl;
return numpyData;
}
这两个文件你可以直接用txt文本编写,因为并不依赖vs编译器去编译生成一个什么东西(比如pyd),但txt写的话,你不容易发现你的语法错误,所以还是推荐使用vs.
example.h中引用的头文件路径是根据自己的环境所配置的,我的Anaconda3安装在C盘根目录下,所以这边根据自己的路径做相应改变。既然使用vs来编辑example.h和example.cpp文件,所以可以建立一个空的c++控制台程序,并对此工程进行环境配置,如下是我所建立的工程,进行环境配置也是为了一方面方便直接在c++里做一些测试。
2.下载swig软件,版本是4.0.1,链接如下
链接:https://pan.baidu.com/s/1E3NICbCRt-oqD0oOVZw54Q
提取码:3va1
3. 添加如下环境变量(我的文件在D盘根目录下)
D:\swigwin-4.0.1 (1)\swigwin-4.0.1
4. 编写example.i文件,此文件和example.h和example.cpp在一个目录下
%module example
%{
#define SWIG_FILE_WITH_INIT
#include "example.h"
#include <C:\Anaconda3\Lib\site-packages\numpy\core\include\numpy\ndarrayobject.h>
#include <C:\Anaconda3\Lib\site-packages\numpy\core\include\numpy\arrayobject.h>
using namespace std;
%}
%include "example.h"
#include <C:\Anaconda3\Lib\site-packages\numpy\core\include\numpy\ndarrayobject.h>
#include <C:\Anaconda3\Lib\site-packages\numpy\core\include\numpy\arrayobject.h>
5.cmd命令到example.i所在文件夹路径下,通过使用
swig -python -c++ example.i
命令行(管理员身份运行cmd)来生成对应的.cxx和.py文件
6. 编写setup.py文件,如下:
#!/usr/bin/env python
"""
setup.py file for SWIG C\+\+/Python example
"""
from distutils.core import setup, Extension
example_module = Extension('_example',
sources=['example.cpp', 'example_wrap.cxx',],
)
setup (name = 'example',
version = '0.1',
author = "www",
description = """Simple swig C\+\+/Python example""",
ext_modules = [example_module],
py_modules = ["example"],
)
6. 完毕后管理员身份运行Anaconda Prompt, 通过使用
python setup.py build_ext --inplace
命令来生成_example模块
生成完毕后,该路径下相关的文件如下
编写test_example.py(和前面生成的pyd文件一个路径)以来验证是否生成的_example模块能否被正确调用,同时验证是否可以读取c#写到共享内存中的图片
import example
from PIL import Image, ImageStat
example.say_hello()
c = example.add(3,4)
e = example.sub(4,5)
im = example.GetImageFromSM("img",375,500,3)
im = im[...,::-1]
x = Image.fromarray(im, 'RGB')
x.show()
print(c)
print(e)
7.运行上一篇博客的程序,使用c#往共享内存里写入一张彩色图像
8.运行上面的test_example.py文件,结果如下:
到这里可以看到python已经可以读取c#往共享内存里存入的一张图片了。
接下来会在我的该系列博客第5篇C#和python通过socket方法进行通信_jiugeshao的专栏-CSDN博客基础上,完善该篇博客中的程序,使得c#可以通过调用python来完成模型的训练,训练完毕后可以实时预测一张图像的结果。