C# 和Python通过共享内存块test1实现
C#
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());
}
catch (System.Exception s)
{
MessageBox.Show(s.Message);
}
}

Python
byteSize 通过上面的C#图像显示框得到
import mmap
import cv2
import numpy as np
byteSize = 1921078
file_name = 'test1'
import struct
import matplotlib.pyplot as plt
# python读取共享内存
f = mmap.mmap(0, byteSize, file_name, mmap.ACCESS_READ)
#print(f.read(byteSize))
f_type=str(f.read(2)) #这个就可以用来读取 文件类型 需要读取2个字节
file_size_byte=f.read(4)# 这个可以用来读取文件的大小 需要读取4个字节
f.seek(f.tell()+4) # 跳过中间无用的四个字节
file_ofset_byte=f.read(4) # 读取位图数据的偏移量
f.seek(f.tell()+4) # 跳过无用的两个字节
file_wide_byte=f.read(4) #读取宽度字节
file_height_byte=f.read(4) #读取高度字节
f.seek(f.tell()+2) ## 跳过中间无用的两个字节
file_bitcount_byte=f.read(4) #得到每个像素占位大小
#下面就是将读取的字节转换成指定的类型
f_size,=struct.unpack('l',file_size_byte)
f_ofset,=struct.unpack('l',file_ofset_byte)
f_wide,=struct.unpack('l',file_wide_byte)
f_height,=struct.unpack('l',file_height_byte)
f_bitcount,=struct.unpack('i',file_bitcount_byte)
print("类型:",f_type,"大小:",f_size,"位图数据偏移量:",f_ofset,"宽度:",f_wide,"高度:",f_height,"位图:",f_bitcount)
'然后来读取颜色表'
color_table=np.empty(shape=[256,4],dtype=int)
f.seek(54) #跳过文件信息头和位图信息头
for i in range(0,256):
b=struct.unpack('B',f.read(1))[0];
g = struct.unpack('B', f.read(1))[0];
r = struct.unpack('B', f.read(1))[0];
alpha = struct.unpack('B', f.read(1))[0];
color_table[i][0]=r
color_table[i][1]=g
color_table[i][2]=b
color_table[i][3]=255
'下面部分用来读取BMP位图数据区域,将数据存入numpy数组'
#首先对文件指针进行偏移
f.seek(f_ofset)
#因为图像是8位伪彩色图像,所以一个像素点占一个字节,即8位
img=np.empty(shape=[f_height,f_wide,4],dtype=int)
cout = 0
for y in range(0, f_height):
for x in range(0,f_wide):
cout=cout+1
index=struct.unpack('B',f.read(1))[0]
img[f_height-y-1,x]=color_table[index]
while cout %4 !=0:
f.read(1)
cout=cout+1
plt.imshow(img)
plt.show()
f.close()
f.close()

但是python解析成图像数据太慢了,要2s多
import mmap
import cv2
import numpy as np
import datetime
starttime = datetime.datetime.now()
byteSize = 1921078
file_name = 'test1'
import struct
import matplotlib.pyplot as plt
# python读取共享内存
f = mmap.mmap(0, byteSize, file_name, mmap.ACCESS_READ)
#print(f.read(byteSize))
f_type=str(f.read(2)) #这个就可以用来读取 文件类型 需要读取2个字节
file_size_byte=f.read(4)# 这个可以用来读取文件的大小 需要读取4个字节
f.seek(f.tell()+4) # 跳过中间无用的四个字节
file_ofset_byte=f.read(4) # 读取位图数据的偏移量
f.seek(f.tell()+4) # 跳过无用的两个字节
file_wide_byte=f.read(4) #读取宽度字节
file_height_byte=f.read(4) #读取高度字节
f.seek(f.tell()+2) ## 跳过中间无用的两个字节
file_bitcount_byte=f.read(4) #得到每个像素占位大小
#下面就是将读取的字节转换成指定的类型
f_size,=struct.unpack('l',file_size_byte)
f_ofset,=struct.unpack('l',file_ofset_byte)
f_wide,=struct.unpack('l',file_wide_byte)
f_height,=struct.unpack('l',file_height_byte)
f_bitcount,=struct.unpack('i',file_bitcount_byte)
print("类型:",f_type,"大小:",f_size,"位图数据偏移量:",f_ofset,"宽度:",f_wide,"高度:",f_height,"位图:",f_bit+count)
'然后来读取颜色表'
color_table=np.empty(shape=[256,4],dtype=int)
f.seek(54) #跳过文件信息头和位图信息头
for i in range(0,256):
b=struct.unpack('B',f.read(1))[0];
g = struct.unpack('B', f.read(1))[0];
r = struct.unpack('B', f.read(1))[0];
alpha = struct.unpack('B', f.read(1))[0];
color_table[i][0]=r
color_table[i][1]=g
color_table[i][2]=b
color_table[i][3]=255
'下面部分用来读取BMP位图数据区域,将数据存入numpy数组'
#首先对文件指针进行偏移
f.seek(f_ofset)
#因为图像是8位伪彩色图像,所以一个像素点占一个字节,即8位
img=np.empty(shape=[f_height,f_wide,4],dtype=int)
cout = 0
starttime1 = datetime.datetime.now()
for y in range(0, f_height):
for x in range(0,f_wide):
cout=cout+1
index=struct.unpack('B',f.read(1))[0]
img[f_height-y-1,x]=color_table[index]
while cout %4 !=0:
f.read(1)
cout=cout+1
endtime1 = datetime.datetime.now()
endtime = datetime.datetime.now()
print(endtime1 - starttime1)
print(endtime - starttime)
plt.imshow(img)
plt.show()
f.close()
f.close()

下一步改进,打算用opencv读取看看
可以,可以,Opencv万岁,只用了3.9ms
import mmap
import cv2
import numpy as np
import datetime
starttime = datetime.datetime.now()
byteSize = 1921078
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)

补充:
# 1、使用cv2
import cv2
import numpy as np
from matplotlib import pyplot as plt
from PIL import Image
img_url = r'test.png'
with open(img_url, 'rb') as f:
a = f.read()
# 二进制数据流转np.ndarray [np.uint8: 8位像素]
img = cv2.imdecode(np.frombuffer(a, np.uint8), cv2.IMREAD_COLOR)
# # 将bgr转为rbg
rgb_img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
print(rgb_img)
# np.ndarray转IMAGE
a = Image.fromarray(rgb_img)
print(a)
# 显示图片
a.show()
2、使用io.BytesIO
import io
from PIL import Image
img_url = r'C:\Users\xxc\Desktop\capture.png'
with open(img_url, 'rb') as f:
a = f.read()
print(type(a))
# 将字节对象转为Byte字节流数据,供Image.open使用
byte_stream = io.BytesIO(a)
print(type(byte_stream))
roiImg = Image.open(byte_stream)
# 图片保存
roiImg.save(r'C:\Users\xxc\Desktop\save.png')
cv2和io.BytesIO相比,多了一步bgr转rbg,可能使用io.BytesIO更加方便。
版权声明:本文为qq_41375318原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。