当前位置: 首页 > article >正文

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脚本里面试试 。


http://www.kler.cn/a/542461.html

相关文章:

  • HarmonyOS 5.0应用开发——NodeContainer自定义占位节点
  • 数据分析对企业有什么价值
  • Leetcode 3448. Count Substrings Divisible By Last Digit
  • IDEA接入DeepSeek
  • 基于改进型灰狼优化算法(GWO)的无人机路径规划
  • 大模型基本原理(二)——ChatGPT的工作原理
  • 蓝桥杯 Java B 组 - 第 1 周复习总结
  • 3、k8s项目的生命周期和yaml文件
  • uniapp商城之登录模块
  • 《深度学习》——CNN卷积神经网络模型及项目实例
  • 【Prometheus】MySQL主从搭建,以及如何通过prometheus监控MySQL运行状态
  • FTP(File Transfer Protocol)-文件传输协议
  • C++引用深度详解
  • Unity做2D小游戏5------多个动画互相转换
  • docker配置国内源
  • 【unity实战】实现摄像机跟随效果
  • 【AI知识点】大模型开源的各种级别和 deepseek 的开源级别
  • Java 大视界 -- 5G 与 Java 大数据融合的行业应用与发展趋势(82)
  • ArcGIS Pro SDK (二十六)自定义配置
  • 基于 PyTorch 的树叶分类任务:从数据准备到模型训练与测试
  • 25考研电子信息复试面试常见核心问题真题汇总,电子信息考研复试没有项目怎么办?电子信息考研复试到底该如何准备?
  • 进阶版MATLAB 3D柱状图
  • 【系统架构设计师】操作系统 - 进程管理 ① ( 进程概念 | 进程组成 | 进程 与 程序 | 进程 与 线程 | 线程 可共享的资源 - ☆考点 )
  • 工具模块新增JSON格式化打印工具类
  • 什么是容器化,它有什么好处,对后端开发有什么影响?
  • 【2025-ICLR-未中】教授多模态大语言模型理解心电图图像