首页-达尔闻    全部    项目分享| OpenMV STM32F7让热敏打印机变相机

项目分享| OpenMV STM32F7让热敏打印机变相机

为了给芭比娃娃拍个照,特制一个灰度复古相机。相机硬件还是热度很高的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整个脚本和库可以在“达尔闻说”微信回复:照相机,获取

Control Render Error!ControlType:productSlideBind,StyleName:Style1,ColorName:Item0,Message:InitError, ControlType:productSlideBind Error:未将对象引用设置到对象的实例。