项目分享| OpenMV STM32F7让热敏打印机变相机
-
为了给芭比娃娃拍个照,特制一个灰度复古相机。相机硬件还是热度很高的OpenMV STM32F7开发板,来看看制作过程吧。
☞ 系统硬件组成:
• OpenMV H7 + 开发板
• OpenMV LCD Shield 扩展板
• Adafruit 热敏打印机
• 12V 电源
• LM2596 降压稳定器模块 – 2 个
• 按钮
• 3d 打印部分
☞电气连接图:
☞ OpenMV H7开发板介绍:
OpenMV H7+ 是一种低功耗、紧凑型相机模块形式的计算机视觉系统。它与传统相机的不同之处在自带了一个微控制器,用于动态处理图像和控制外部设备。
图像由OmniVision OV7725 1/3" 感光CMOS摄像头,分辨率为640×480。摄像头以8位灰度模式或16位RGB565彩色格式拍摄视频,频率最高可达75帧每秒,支持 MJPEG、GIF 和未压缩的 RAW 视频压缩格式。相机具有 RGB LED 背光和两个用于在黑暗中拍摄的 IR LED。
焦距为 2.8 毫米、光圈为 F2.0 的镜头通过带有标准 M12 螺纹的卡口连接,留有0.5毫米的裕量,因此来自 GoPro 和其他便携式相机的可互换镜头适用于 OpenMV H7。
带有 ARM Cortex-M7 内核的 32 位 STM32H743VI 微控制器负责图像处理。该处理器有高达 480 MHz 的主频,它具有 1 MB 的 SRAM 和 2 MB 的板载flash。可以处理不同复杂度的计算机视觉算法,包括:
• 通过 TensorFlow Lite 进行图像分析;
• 视频帧中的运动检测;
• 人脸识别;
• 跟踪彩色物体和标记;
• 检测和读取二维码、条形码和AprilTags;
• 高速线路跟踪;
• 识别几何对象;
• 图像与指定模板的比较。
板子microSD 存储卡,用于录制视频和存储工作数据。高达 100 Mbit/s 的读写速度可以快速加载机器视觉对象。
☞ 电气连接
LCD Shield 用于从 OpenMV 摄像头模块即时显示图像,无需使用外部电线和多媒体设备。显示分辨率为128×160像素,深度为65536色。
OpenMV LCD Shield扩展板连接到OpenMV H7+的触点,然后将OpenMV H7+板连接到按钮和热敏打印机,这里可自制一个扩展板。
打印外壳,并将电源和稳定器模块放置在外壳底部。
最后,将Adafruit热敏打印机放置在机箱中,将带有铭牌的Openmw H7+板放置在面板上,并用热熔胶将其连接到机箱。
☞ 编写程序
智能相机在 OpenMV IDE 开发环境中用 MicroPython 编程,结合了程序代码编辑器、查看摄像机的视频缓冲区和实时构建 RGB 直方图以简化调试过程。
项目中要使用 Adafruit 热敏打印机,还需要下载 Adafruit_Thermal 库。
Adafruit 热敏打印机允许在标准宽度为 57 毫米、卷筒直径最大为 36 毫米的热敏纸收据带上打印文本、条形码和图像。印刷方法包括使用特殊的白炽灯头,将文字烧写在纸上。头部温度高达200摄氏度。在曝光的地方,纸张变暗并获得必要的文字。
此次尝试实现打印灰度图像。将从相机接收分辨率为 128x160 的 RG565 彩色图像并将其保存在 bmp 文件中。
sensor.set_pixformat(sensor.RGB565) #
sensor.set_framesize(sensor.LCD) # 128x160
对于图像中的每个点,我们将计算灰度值。我们从 bmp 文件中读取数据。文件内容分析:
字节 1、2 应为 [0x4D 0x42]: 424D
字节 3-6(图像大小)0000073E
字节 7、8(必须为零) 0000
字节 9、10(必须为零) 0000
字节 11-14(图像偏移) 00000036
字节 15-18(BITMAPINFOHEADER 结构的大小,必须为 40 [0x28]) 00000028
字节 19-22(图像宽度) 00000018
字节 23-26(图像高度) 00000019
Bytes 27, 28(图像中的平面数,必须为1)0001
字节 29、30(每个像素的位数(1、4、8 或 24 [0x18]))0018
-- -- 注24位色,是红绿蓝三色
文件签名分析(Header analysis)
BMP 文件(以 0x42 0x4D 开头)
RGB565 格式——每个点由 2 个字节表示。
r = ((color >> 11) & 0x1F);
g = ((color >> 5) & 0x3F);
b = (color & 0x1F);
grey=(3*r+6*g+1*b)/2
然后,为了模拟灰度颜色,将一个3x3的矩阵输出到黑白打印机,灰度值在0到255之间的一个像素将被转换成一个3x3的黑白矩阵,例如:
但是由于打印是逐行进行的,我们将首先创建一个位图文件,然后使用 Adafruit_Thermal 库打印它。
从 bmp 创建位图文件:
mask=[[1,1,1,1,1,1,1,1,1],[1,1,1,1,0,1,1,1,1],[0,1,1,1,1,1,1,1,0],
[0,1,1,1,0,1,1,1,0],[0,1,0,1,0,1,0,1,0],[1,0,1,0,0,0,1,0,1],
[0,0,1,0,1,0,1,0,0],[0,0,1,0,0,0,1,0,0],[0,0,0,0,1,0,0,0,0],
[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]]
def convertBMP_toBitmap(fbmp):
global arr1;
pyb.LED(GREEN_LED_PIN).on()
img=image.Image(fbmp)
img1=img
lcd.display(img1)
try:
with open(fbmp, 'rb') as bmp_file:
filenamebitmap=fbmp.replace(".bmp","")
#fbitmap=open("bitmap","wb")
fbitmap=open(filenamebitmap,"wb")
arr1 = [[0 for x in range(384)] for y in range(3)]
# BitmapHeader
headerbmp = bmp_file.read(14)
filesize=int.from_bytes(headerbmp[2:6], 'little')
fileoffset=int.from_bytes(headerbmp[-4:], 'little')
print("filesize = ",filesize)
print("fileoffset = ",fileoffset)
width=128
height=160
#
bmp_file.seek(fileoffset)
col=0;row=0;
#for d in range (0,(filesize-fileoffset)/2,1):
print("create bitmap ",filenamebitmap)
for row in range (0,160,1):
for col in range (0,128,1):
bytecolor=bmp_file.read(2)
color=int.from_bytes(bytecolor,"little")
#print("color= ",hex(color))
r = ((color >> 11) & 0x1F);
g = ((color >> 5) & 0x3F);
b = (color & 0x1F);
grey=(3*r+6*g+1*b)/2
setBits(col,grey)
arr2 = [[0 for x in range(48)] for y in range(3)]
for b1 in range (0,3):
for b2 in range (0,48):
bb=0x00;
for b3 in range (0,8):
bb=bb+(arr1[b1][b2*8+b3]<<(8-b3-1))
arr2[b1][b2]=bb;
fbitmap.write(bb.to_bytes(1,sys.byteorder));
fbitmap.close()
except OSError as e:
print('error: {}'.format(e))
pyb.LED(GREEN_LED_PIN).off()
def setBits(col,g):
global arr1;
g=int(g // 25)
for i in range(0,3):
for j in range(0,3):
arr1[i][col*3+j]=mask[g][i*3+j]
并打印位图文件:
def print_snaphot(ff):
pyb.LED(BLUE_LED_PIN).on()
filenamebitmap=ff.replace(".bmp","")
img1=image.Image(ff)
printer.printBitmapFromFile(384, 480, filenamebitmap)
pyb.LED(BLUE_LED_PIN).off()
当按钮被按下时,主循环打印
startphoto = Pin('P9', Pin.IN, Pin.PULL_UP)
while(True):
lcd.display(sensor.snapshot())
if startphoto.value()==0:
#
filename=save_snaphot()
print(filename)
#
convertBMP_toBitmap(filename)
#
print_snaphot(filename)
main.p整个脚本和库可以在“达尔闻说”微信回复:照相机,获取。
-