python C# 内存共享互传 图像 以及字符串
首先用命令行调用:
public string ExecuteCommand(string command)
{
string output = string.Empty; // 用于存储命令的输出
string error = string.Empty; // 用于存储命令的错误信息
try
{
using (Process p = new Process()) // 使用Process类启动新进程
{
// 配置进程启动信息
p.StartInfo.FileName = "cmd.exe"; // 设置要启动的程序为cmd.exe
p.StartInfo.Arguments = $"/c {command}"; /c 参数表示执行完命令后关闭cmd窗口
p.StartInfo.UseShellExecute = false; // 不使用操作系统shell启动
p.StartInfo.RedirectStandardInput = true; // 重定向标准输入
p.StartInfo.RedirectStandardOutput = true; // 重定向标准输出
p.StartInfo.RedirectStandardError = true; // 重定向错误输出
// p.StartInfo.CreateNoWindow = true; // 不显示命令窗口
p.StartInfo.CreateNoWindow = false;
p.Start(); // 启动进程
// 读取命令的输出
output = p.StandardOutput.ReadToEnd();
// 读取命令的错误信息
error = p.StandardError.ReadToEnd();
p.WaitForExit(); // 等待进程结束
}
}
catch (Exception ex)
{
// 捕获异常并返回错误信息
return $"执行命令时发生错误: {ex.Message}";
}
// 如果有错误信息,返回错误信息;否则返回命令的输出
return string.IsNullOrEmpty(error) ? output : $"错误: {error}";
}
接下来 按钮事件:
private void button1_Click(object sender, EventArgs e)
{
try
{
Bitmap b = new Bitmap("test.bmp");
MemoryStream ms = new MemoryStream();
b.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
byte[] bytes = ms.GetBuffer(); //byte[] bytes= ms.ToArray();
ms.Close();
var mmf = MemoryMappedFile.CreateOrOpen("test1", bytes.Length, MemoryMappedFileAccess.ReadWrite);
var viewAccessor = mmf.CreateViewAccessor(0, bytes.Length);
viewAccessor.Write(0, bytes.Length); ;
viewAccessor.WriteArray<byte>(0, bytes, 0, bytes.Length);
// MessageBox.Show("write ok" + bytes.Length.ToString());
}
// 5013504 5014582
catch (System.Exception s)
{
// MessageBox.Show(s.Message);
}
string str = ExecuteCommand(@"python nn.py");
// label1.Text = str;
}
好了 看程序可以知道 图像已经 内存共享到 text1
接下来:nn.py
import os,sys,time
import mmap
import cv2
import numpy as np
import datetime
from matplotlib import pyplot as plt
from PIL import Image
starttime = datetime.datetime.now()
byteSize = 5014582
file_name = 'test1'
f = mmap.mmap(0, byteSize, file_name, mmap.ACCESS_READ)
img = cv2.imdecode(np.frombuffer(f, np.uint8), cv2.IMREAD_COLOR)
endtime = datetime.datetime.now()
print(endtime-starttime)
rgb_img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
print(rgb_img)
# np.ndarray转IMAGE
a = Image.fromarray(rgb_img)
print(a)
# 显示图片
a.show()
按下按钮就会 读取图像写入共享内存 并 调用python python读取并显示
接下来说一下 传字符串 :
1.Write.py
import mmap
str = 'hello!'
byte = str.encode(encoding='UTF-8')
infoSize= len(str)
file_name = 'global_share_memory'
# python写入共享内存
shmem = mmap.mmap(0, infoSize, file_name, mmap.ACCESS_WRITE)
# 共享数据写入共享内存
shmem.write(byte)
# 让其一直运行,因为进程是活的,死了的进程,共享内存也就没了
while True:
pass
Read.py
import mmap
# 定义字符串和其字节表示
str = 'hello!'
byte = str.encode()
infoSize = len(str) # 字符串的字节长度
file_name = 'global_share_memory' # 共享内存的名称
# 打开共享内存(假设共享内存已经存在)
try:
# 使用 ACCESS_READ 模式打开共享内存
shmem = mmap.mmap(0, infoSize, file_name, mmap.ACCESS_READ)
# 从共享内存读取数据
data = shmem.read(infoSize).decode("utf-8")
print(data)
shmem.close()
except Exception as e:
print(f"Error: {e}")
import os
os.system("pause")
C#读取:
private void button3_Click(object sender, EventArgs e)
{
long capacity = 16;
var mmf = MemoryMappedFile.OpenExisting("global_share_memory");
using (MemoryMappedViewAccessor viewAccessor = mmf.CreateViewAccessor(0, capacity))
{
// 创建一个字节数组来存储读取的数据
byte[] bytes = new byte[capacity];
// 逐字节读取数据
for (int i = 0; i < capacity; i++)
{
bytes[i] = viewAccessor.ReadByte(i);
}
// 将字节数组转换为字符串(假设数据是 UTF-8 编码)
string result = Encoding.UTF8.GetString(bytes);
// 输出结果
Console.WriteLine("字符串内容: " + result);
label1.Text = result;
}
}
嗯 现在说一下python共享内存传给C#
先python自己写自己读试试:
python写:
import mmap
import numpy as np
from PIL import Image
import os
import struct
def write_image_to_shared_memory(image_path, shared_memory_name):
# 读取图像并转换为字节流
image = Image.open(image_path)
image_bytes = np.array(image).tobytes()
width, height = image.size # 获取图像的宽度和高度
# 将图像尺寸信息附加到字节流
header = struct.pack("ii", width, height) # 4 字节宽度 + 4 字节高度
data = header + image_bytes
# 创建共享内存文件并写入数据
with open(shared_memory_name, "wb") as f:
f.write(b'\0' * len(data)) # 初始化文件大小
with open(shared_memory_name, "r+b") as f:
mm = mmap.mmap(f.fileno(), 0)
mm.write(data) # 写入数据
mm.close()
print(f"图像已写入共享内存:{shared_memory_name}")
if __name__ == "__main__":
image_path = "lena.jpg" # 替换为你的图像路径
shared_memory_name = "shared_image_memory"
write_image_to_shared_memory(image_path, shared_memory_name)
while True:
pass
一定要让程序阻塞 停了数据就没有了。
读:
import mmap
import numpy as np
from PIL import Image
import os
import struct
def read_image_from_shared_memory(shared_memory_name):
try:
# 打开共享内存文件
with open(shared_memory_name, "r+b") as f:
mm = mmap.mmap(f.fileno(), 0) # 映射整个文件
data = mm.read() # 读取全部字节
mm.close() # 关闭映射
# 解析图像尺寸信息
width, height = struct.unpack("ii", data[:8]) # 前 8 字节是宽度和高度
image_bytes = data[8:] # 剩余部分是图像数据
# 将字节流转换为图像
image = Image.frombytes("RGB", (width, height), image_bytes)
print(f"图像已从共享内存 {shared_memory_name} 成功读取。")
return image
except Exception as e:
print(f"从共享内存读取图像时发生错误:{e}")
return None
if __name__ == "__main__":
shared_memory_name = "shared_image_memory" # 共享内存文件名
image = read_image_from_shared_memory(shared_memory_name)
if image:
image.show() # 显示图像
image.save("oopppp.jpg")
C#读
private void button3_Click(object sender, EventArgs e)
{
string sharedMemoryName = "shared_image_memory"; // 共享内存文件名
// 打开共享内存文件
using (FileStream fs = new FileStream(sharedMemoryName, FileMode.Open, FileAccess.Read))
{
byte[] data = new byte[fs.Length];
fs.Read(data, 0, data.Length);
// 解析图像尺寸信息
int width = BitConverter.ToInt32(data, 0); // 前 4 字节是宽度
int height = BitConverter.ToInt32(data, 4); // 接下来的 4 字节是高度
byte[] imageBytes = new byte[data.Length - 8];
Array.Copy(data, 8, imageBytes, 0, imageBytes.Length);
// 创建 Bitmap 对象
Bitmap bitmap = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
// 将原始像素数据复制到 Bitmap 对象
System.Drawing.Imaging.BitmapData bitmapData = bitmap.LockBits(
new Rectangle(0, 0, width, height),
System.Drawing.Imaging.ImageLockMode.WriteOnly,
System.Drawing.Imaging.PixelFormat.Format24bppRgb
);
IntPtr ptr = bitmapData.Scan0;
int bytesPerPixel = 3; // 24 bits per pixel
int stride = bitmapData.Stride; // 每行的字节数
// 复制数据
for (int y = 0; y < height; y++)
{
int rowStart = y * width * bytesPerPixel;
IntPtr rowPtr = new IntPtr(ptr.ToInt64() + y * stride);
System.Runtime.InteropServices.Marshal.Copy(imageBytes, rowStart, rowPtr, width * bytesPerPixel);
}
bitmap.UnlockBits(bitmapData);
// 保存为 BMP 文件
bitmap.Save("output_image.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
Console.WriteLine("图像已从共享内存读取并保存为 BMP 文件。");
}
// 删除共享内存文件
// File.Delete(sharedMemoryName);
}
这时RGB是取反的 不想改了。RGB转BGR就可以。
下来直接上完整程序:
C#
using System;
using System.IO;
using System.Drawing;
using System.IO.MemoryMappedFiles;
using System.Diagnostics;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
private Label label1;
private Button button3;
public Form1()
{
InitializeComponent();
}
public string _CMD(string strInput)
{
string strOuput;
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";//设置要启动的应用程序
p.StartInfo.UseShellExecute = false;//是否使用操作系统shell启动
p.StartInfo.RedirectStandardInput = true;// 接受来自调用程序的输入信息
p.StartInfo.RedirectStandardOutput = true;//输出信息
p.StartInfo.RedirectStandardError = true;// 输出错误
p.StartInfo.CreateNoWindow = true;//不显示程序窗口
// p.StartInfo.CreateNoWindow = false; //显示程序窗口
p.Start();//启动程序
p.StandardInput.WriteLine("@echo off");
p.StandardInput.WriteLine(strInput + "&exit");//向cmd窗口发送输入信息
p.StandardInput.AutoFlush = true;
strOuput = p.StandardOutput.ReadToEnd(); //获取输出信息
p.WaitForExit(); //等待程序执行完退出进程
p.Close();
return strOuput;
}
public string ExecuteCommand(string command)
{
string output = string.Empty; // 用于存储命令的输出
string error = string.Empty; // 用于存储命令的错误信息
try
{
using (Process p = new Process()) // 使用Process类启动新进程
{
// 配置进程启动信息
p.StartInfo.FileName = "cmd.exe"; // 设置要启动的程序为cmd.exe
p.StartInfo.Arguments = $"/c {command}"; /c 参数表示执行完命令后关闭cmd窗口
p.StartInfo.UseShellExecute = false; // 不使用操作系统shell启动
p.StartInfo.RedirectStandardInput = true; // 重定向标准输入
p.StartInfo.RedirectStandardOutput = true; // 重定向标准输出
p.StartInfo.RedirectStandardError = true; // 重定向错误输出
p.StartInfo.CreateNoWindow = true; // 不显示命令窗口
// p.StartInfo.CreateNoWindow = false;
p.Start(); // 启动进程
// 读取命令的输出
output = p.StandardOutput.ReadToEnd();
// 读取命令的错误信息
error = p.StandardError.ReadToEnd();
p.WaitForExit(); // 等待进程结束
}
}
catch (Exception ex)
{
// 捕获异常并返回错误信息
return $"执行命令时发生错误: {ex.Message}";
}
// 如果有错误信息,返回错误信息;否则返回命令的输出
return string.IsNullOrEmpty(error) ? output : $"错误: {error}";
}
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.button3 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(186, 296);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(76, 21);
this.label1.TabIndex = 3;
this.label1.Text = "label1";
//
// button3
//
this.button3.Location = new System.Drawing.Point(122, 132);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(228, 123);
this.button3.TabIndex = 6;
this.button3.Text = "button3";
this.button3.UseVisualStyleBackColor = true;
this.button3.Click += new System.EventHandler(this.button3_Click);
//
// Form1
//
this.ClientSize = new System.Drawing.Size(1125, 625);
this.Controls.Add(this.button3);
this.Controls.Add(this.label1);
this.Name = "Form1";
this.ResumeLayout(false);
this.PerformLayout();
}
private void button3_Click(object sender, EventArgs e)
{
try
{
Bitmap b = new Bitmap("lena.jpg");
MemoryStream ms = new MemoryStream();
b.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
byte[] bytes = ms.GetBuffer(); //byte[] bytes= ms.ToArray();
ms.Close();
var mmf = MemoryMappedFile.CreateOrOpen("test1", bytes.Length, MemoryMappedFileAccess.ReadWrite);
var viewAccessor = mmf.CreateViewAccessor(0, bytes.Length);
viewAccessor.Write(0, bytes.Length); ;
viewAccessor.WriteArray<byte>(0, bytes, 0, bytes.Length);
// MessageBox.Show("write ok" + bytes.Length.ToString());
}
// 5013504 5014582
catch (System.Exception s)
{
// MessageBox.Show(s.Message);
}
string str = ExecuteCommand(@"python nn.py");
// 我希望通过命令行 把 高度 宽度 bytes.Length 传输
label1.Text = str;
string sharedMemoryName = "shared_image_memory"; // 共享内存文件名
// 打开共享内存文件
using (FileStream fs = new FileStream(sharedMemoryName, FileMode.Open, FileAccess.Read))
{
byte[] data = new byte[fs.Length];
fs.Read(data, 0, data.Length);
// 解析图像尺寸信息
int width = BitConverter.ToInt32(data, 0); // 前 4 字节是宽度
int height = BitConverter.ToInt32(data, 4); // 接下来的 4 字节是高度
byte[] imageBytes = new byte[data.Length - 8];
Array.Copy(data, 8, imageBytes, 0, imageBytes.Length);
// 创建 Bitmap 对象
Bitmap bitmap = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
// 将原始像素数据复制到 Bitmap 对象
System.Drawing.Imaging.BitmapData bitmapData = bitmap.LockBits(
new Rectangle(0, 0, width, height),
System.Drawing.Imaging.ImageLockMode.WriteOnly,
System.Drawing.Imaging.PixelFormat.Format24bppRgb
);
IntPtr ptr = bitmapData.Scan0;
int bytesPerPixel = 3; // 24 bits per pixel
int stride = bitmapData.Stride; // 每行的字节数
// 复制数据
for (int y = 0; y < height; y++)
{
int rowStart = y * width * bytesPerPixel;
IntPtr rowPtr = new IntPtr(ptr.ToInt64() + y * stride);
System.Runtime.InteropServices.Marshal.Copy(imageBytes, rowStart, rowPtr, width * bytesPerPixel);
}
bitmap.UnlockBits(bitmapData);
// 保存为 BMP 文件
bitmap.Save("output_image.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
Console.WriteLine("图像已从共享内存读取并保存为 BMP 文件。");
}
// 删除共享内存文件
//File.Delete(sharedMemoryName);
}
}
}
python nn.py
import os,sys,time
import mmap
import cv2
import numpy as np
import datetime
from matplotlib import pyplot as plt
from PIL import Image
import struct
starttime = datetime.datetime.now()
byteSize = 480054
file_name = 'test1'
f = mmap.mmap(0, byteSize, file_name, mmap.ACCESS_READ)
img = cv2.imdecode(np.frombuffer(f, np.uint8), cv2.IMREAD_COLOR)
endtime = datetime.datetime.now()
print(endtime-starttime)
rgb_img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
#print(rgb_img)
# np.ndarray转IMAGE
a = Image.fromarray(rgb_img)
#print(a)
# 显示图片
#a.show()
def write_image_to_shared_memory(img, shared_memory_name):
image= Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
image_bytes = np.array(image).tobytes()
width, height = image.size # 获取图像的宽度和高度
# 将图像尺寸信息附加到字节流
header = struct.pack("ii", width, height) # 4 字节宽度 + 4 字节高度
data = header + image_bytes
# 创建共享内存文件并写入数据
with open(shared_memory_name, "wb") as f:
f.write(b'\0' * len(data)) # 初始化文件大小
with open(shared_memory_name, "r+b") as f:
mm = mmap.mmap(f.fileno(), 0)
mm.write(data) # 写入数据
mm.close()
#print(f"图像已写入共享内存:{shared_memory_name}")
if __name__ == "__main__":
shared_memory_name = "shared_image_memory"
write_image_to_shared_memory(rgb_img, shared_memory_name)
endtime = datetime.datetime.now()
print(endtime-starttime)
虽然写在一起没有做成函数 已经可以实现基本功能 C#> python[这里可以写图像处理] >C#
下次 移到VM脚本里面试试 。