“属你最牛” | 树莓派百变打印机


大家好,我是旺仔爸爸,好久没有更新了,牛年春节就要到了,这次带来一款和牛年春节相关的作品,我给它起名为《“属你最牛”百变打印机》(下文简称:最牛打印机或打印机)

关键词:树莓派,python,爬虫,激光造物

#设计思路#


大家回想一下,过去以往,你过年的打开方式都是什么样子的呢,穿新衣,贴春联,放烟花,发红包,走亲戚,拜大年这些项目一定少不了

试想一下,拜年不再是传统的作揖磕头,而是一张印有自己画像的拜年海报,创意上一定是满分;如果将拜年的祝福音频以二维码的形式展现在一张明信片上,过年时送给对方,将是一件非常美好的事情;再比如让小朋友用微笑值来换取红包,笑的越开心,红包的数值就越大,一定是一件好玩的事情,相信你还会有很多不一样的想法


此次项目就是在三种不同的传统春节庆祝方式上增加了科技的元素后制作而成

接下来旺仔爸爸一一展开介绍,为您带来“最牛”的春节打开方式

到底牛不牛呢,先通过视频来了解一下

#方案介绍#


从视频中可以看出“最牛打印机”有三种模式

模式一:春节大红包

模式二: 拜年牛海报

模式三: 有声明信片

完成上述三种模式,则需要实现图像采集,声音录制,图像处理及打印,那么树莓派作为主控将是满足此项目需求的不二之选


什么是树莓派呢?

树莓派就是一个尺寸和信用卡差不多大小的小型电脑,而且是全世界畅销的计算机!是基于ARM的单板计算机,默认运行一款称为Raspbian的操作系统,它是基于Linux内核和Debian操作系统开发的开源操作系统。操作系统被装载在一张TF卡上,由USB供电。你只需要再连接上鼠标、键盘和显示器或者电视机,就可以进行基于Linux操作系统的程序设计了

树莓派可以做的项目有很多,比如服务器,路由器,语音识别,视觉识别等等,在音视频、图像处理、人工智能等方面很有优势,所以本次项目选用树莓派作为主控

关于树莓派的镜像烧录,系统配置等工作,请查看之前《因一次点外卖的经历成就的“传话筒” 》文章中的环境配置章节,本文就不再详细介绍


#材料清单#

要完成本次项目还需要准备以下材料

  • 树莓派4B(3B/3B+都可以)*1

  • 树莓派IO扩展板*1

  • 树莓派CSI 500W摄像头*1

  • hp2302喷墨打印机*1

  • 14寸拆机屏幕+驱动*1

  • 外置麦克风*1

  • 数字大按钮*2

  • ws2812灯带(32颗灯珠)*1

  • 喇叭*2

  • 功放板*1

  • USB声卡*1

  • HDMI连接线*1

  • 树莓派电源5V3A*1

  • 屏幕电源12V2A*1

  • 开关,插座,五金等

  • 40*60 6mm奥松板*10

  • 2mm白色透光亚克力板*1



准备好以上材料后,我们需要给“最牛打印机”设计漂亮的外观结构

#外观结构设计#


使用AutoCAD软件辅助设计“最牛打印机”的外观结构,材料选用6mm奥松板,为了结构的紧固性,榫卯卡槽设计宽度为5.7mm


使用激光切割机加工后的实物如下图所示


#电路接线#


电路连接之前,我们需要知道什么是树莓派的GPIO引脚,树莓派作为一款微型计算机,GPIO引脚集成到了树莓派中,用户可以控制它的引脚,从引脚连接传感器读取数据,使用GPIO引脚还可以控制LED,电机和显示器等组件,较新的树莓派版本具有40个GPIO引脚,有BOARD、BCM、wiringPi三种不同的引脚序号,下图列出了详细的引脚对照表,注意接线时引脚的选择和程序中的GPIO库要对应,下文中程序编写章节会详细介绍



“最牛打印机”使用了一款DFRobot的树莓派IO扩展板,可以很方便的使用BCM引脚接线


电路接线图如下所示


#组装制作#


组装制作时我们先将各种硬件安装在木板上,之后再进行整体拼装

首先安装两块侧板上的零件


以最牛打印机的屏幕为正前方,我们需要在左侧板的长方形孔位上安装开关



在右侧板里面一侧安装屏幕驱动板,屏幕控制按键通过几个设计好的孔位突显在外测



我们将屏幕驱动板的按键控制板以叠加的方式安装在侧板上,细节图如下


在侧板的外面一侧可以方便触碰按键(由于木板比较厚,可以削掉一部分里侧的木头让按键容易被触碰)


侧板上的硬件安装好后,接着我们将树莓派安装在背板上


下面两个木盒子的作用是为了将打印机垫高(因为旺仔爸爸将打印机改成了连供系统,所以需要让墨水仓的高度低于墨盒才能连续供墨)


我们在底板上用四颗自攻螺丝分别固定,为了防止金属的自攻螺丝突出划伤桌面或者地板,可以在“最牛打印机”的底板上挖出沉头孔


下面是两个盒子安装固定后的样子



两块侧板、底板、背板安装完成后就可以进行简单拼装,如下图所示,出纸口的面板安装完毕后就可以放置打印机了


接下来,我们将数字大按键和录制音频的麦克风安装在面板上

每个数字大按键需要分别焊接下拉电阻,目的是让信号更加稳定,然后将麦克风的音频线从预留的圆孔中引出



安装完成后如下图


接下来我们将数字大按键的面板拼装在最牛打印机上


下面一步需要将屏幕和ws2812安装在前面板上,这里设计灯带的作用是在摄像头采集图像时补光

最牛打印机使用的屏幕如下图所示,上下有8个定位孔



我们通过2mm的自攻螺丝将屏幕固定


固定好后的正面如下图所示


然后将ws2812灯带分成4节,每节8颗灯珠,先利用电烙铁焊接好线路后再使用热熔胶枪固定在前面板的背面


固定完成后,白色亚克力透光板粘在前面板的正面,遮住裸露在外面的灯带


将装有屏幕和ws2812灯带的面板拼装在最牛打印机上,最后将屏幕上的膜撕掉


接着我们将喇叭安装在前面板上,摄像头是装在的中间部位的,但现在不着急安装,防止组装时损坏摄像头的排线。这里需要介绍一下摄像头的安装结构,旺仔爸爸专门设计成了可以旋转的结构,方便调节摄像头的俯仰角,你如果还有更好的方案欢迎交流哦


喇叭安装好后,我们可以把功放板与喇叭进行连线


紧接着将喇叭面板拼装在最牛打印机上


下面是一块可以开合的顶板,使用金属合页作为开合的铰链结构,设计成开合的方式主要原因是为了方便检修维护


最后将顶板安装完毕后,我们就可以上电测试了


至此为止组装制作完成,我们开始程序设计

#程序设计#


程序设计开始前,我们需要先了解一下最牛打印机的运作过程

#最牛打印机思维导图#


我们根据上图来逐步分析最牛打印机的程序设计,在“有声明信片”模式中用到了两种python爬虫知识,由于篇幅原因,旺仔爸爸打算单独写一篇文章来详细介绍,本文主要介绍“春节大红包”和“拜年牛海报”两种模式

模式一:春节大红包

准备红包模板

首先我们需要准备符合牛年主题的红包素材,因为人像要和红包素材融合在一起,所以在寻找素材时最好有一块比较明显的区域用来显示人像,下面是本次项目中用到的两种红包模板A和B


实现流程

接下来我们了解一下“春节大红包”模式的实现流程,包含6个步骤


旺仔爸爸详细列出了上图6个步骤所用到的程序块,基本上都是python的基础知识,理解了这些程序块就可以随心所欲的控制“最牛打印机”了


看不懂没关系,三种模式的程序基本是触类旁通的,一种模式掌握后剩余了两个模式就会很容易理解,我们来挨个了解一下

步骤1:pygame显示图像

首先需要在命令行中输入下面指令安装pygame库

sudo pip3 install pygame  #游戏库

接着我们了解pygame的基础框架

pygame游戏库的基础框架

import pygame
#初始化
pygame.init()
#创建游戏窗口,窗口width,height
root=pygame.display.set_mode((1200,600))
#窗口标题
pygame.display.set_caption("我的游戏")
#设置背景颜色,fill((R,G,B))
root.fill((255,255,0))
#首次显示,以后的显示display.update()
pygame.display.flip()
while True: #检测事件(event)
    for event in pygame.event.get():#遍历事件
    #检测关闭按钮是否被点击
    if event.type == pygame.QUIT:


上面的代码运行后会在屏幕上显示一个1200*600的窗口,背景色为黄色,需要注意首次在窗口中更新显示使用display.flip()指令,之后的更新使用display.update()指令

熟悉了pygame的基本框架后,我们就可以在基本框架的基础上做很多丰富的事情了,比如常见的各种小游戏都可以使用pygame开发,本次项目用到了文本、图形、图片三种显示方法,接下来我们依次学习掌握三种显示方法

显示文字

#=========显示文字==========
#Font(文字的路径,字号)
# 字体默认为程序文件路径,也可以指定文件路径


word=pygame.font.Font("李旭科书法.ttf",50)
#render(文字内容,True,文字颜色,背景颜色)
text=word.render("最牛打印机",True,(255,0,0),(0,0,255))
#旋转缩放文字(对象,角度,缩放比例)
text=pygame.transform.rotozoom(text,0,1)
#渲染文字(对象,坐标)
root.blit(text,(100,100))
pygame.display.update()

上面的代码运行后会将“最牛打印机”几个字以“李旭科书法”字体,50号字,红色字体,蓝色背景的方式显示在坐标(100,100)的位置


显示图片

#=========显示图片===========
#加载图片  默认为当前程序文件路径(相对路径),也可以指定文件路径(绝对路径)如:"C:/Users/guoli/Desktop/apple.png"
photo=pygame.image.load("apple.png") 
#图片旋转和缩放(图片的对象,旋转的角度,缩放的比例) photo_new=pygame.transform.rotozoom(photo,0,0.1)
#渲染图片
aadroot.blit(photo_new,(100,100))
pygame.display.update()

运行上面代码后会将名字为“apple”的图片以实际尺寸十分之一的大小显示在坐标(100,100)的位置


在文字显示和图片显示程序中的字体或图片路径可以是绝对路径也可以是相对路径,也就是如果使用的字体或图片与当前程序在用一个文件夹中则可以使用相对路径,反之则为需要使用绝对路径,如上面程序中代码所写那样,绝对路径总是从根文件夹开始

显示图形

#=========画图形============
#画矩形rect(画在哪里,线的颜色,矩形的范围(起点坐标,宽和高),线宽)
pygame.draw.rect(root,(255,0,0),(100,100,400,200),3)
#画圆 circle(画在哪里,线的颜色,圆的坐标,半径,线宽)
pygame.draw.circle(root,(255,0,0),(200,300),20,3)
pygame.display.update()


上面的代码运行后,会绘制一个宽400高200的长方形矩形框和半径为20的空心圆

矩形框的线宽为3,以坐标(100,100)点为左上角,线的颜色为红色

空心圆的线宽为3,圆心坐标为(200,300),线的颜色为红色

如果将代码中的线宽改为0,则绘制实心的圆或者矩形

掌握了图形的绘制方法后我们就可以对“最牛打印机”实现各种选择切换的操作了

步骤2:picamera控制CSI摄像头程序

程序文件名为"make_camera"

from picamera.array import PiRGBArray   #picamera 函数库,用来控制CSI摄像头
from picamera import PiCamera, Color
def camera():
    demoCamera = PiCamera()
    demoCamera.resolution = (640, 480)   #设置摄像头的分辨率
    demoCamera.framerate = 90               #设定摄像头的帧率,数字越小越清晰    
    demoCamera.capture('classPhoto.png') #拍下一张照片,保存在当前程序路径,也可制定路径
    print("camera ok") demoCamera.close()

picamera库默认系统自带,可以直接调用,如果报错,可以打开命令行输入下面的指令手动安装,如果你已经安装过树莓派系统了,相信命令行输入指令难不倒你,如果你还没有使用过命令行,建议先学习一下《因一次点外卖的经历成就的“传话筒”》中关于如何操作命令行的详细教程


sudo apt-get install  python3-picamera

程序中涉及到了对摄像头的基本操作,其中包含,设置摄像头分辨率,帧率,照片拍摄等,代码中已经注释,更加丰富的玩法可以参考官方链接

https://picamera.readthedocs.io/en/release-1.13/

步骤3:PIL图像处理

命令行输入如下指令安装PIL图像处理库

sudo pip3 install Pillow   #图像处理库

安装好PIL图像处理库后,我们输入如下程序进行简单的操作测试,导入图片、显示文字并保存

from PIL import Image, ImageDraw, ImageFont
import os
#图片路径
filepath='apple.png'
#打开图片
image = Image.open(filepath)
#新建绘图对象
draw = ImageDraw.Draw(image)
#显示图片
image.show()
#文字内容
text = "苹果"
#字体
setFont = ImageFont.truetype('李旭科书法.ttf', 20)
#字体颜色
fillColor = "#0000ff"   #蓝色
#绘制文字
draw.text((40,40),text,font=setFont,fill=fillColor,direction=None)
#文字显示
image.show()
filename="C:/Users/guoli/Desktop/pingguo.png"
#保存
image.save(filename)

结果如下图所示,通过示例程序掌握PIL图像处理库的简单用法后就可以在“最牛打印机”上施展拳脚了


步骤4:微笑值获取

程序文件名为"face"

微笑值获取需要调用requests库从百度智能云获取数据

关于百度平台的使用方法可以参考《因一次点外卖的经历成就的“传话筒”》文章中百度智能云平台设置章节

调用百度智能云之前需要安装网络请求库,指令如下

sudo pip3 install requests    #网络请求库

import requests    #网络请求
import base64      
import json


def getToken():
    ak = 'vw4Gl1Oz4yPEfNrqG4OFoBYK'
    sk = '16fIx3KpUgmslXjdKivHGlxhBygyOC0F'
    host = f'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={ak}&client_secret={sk}'
    response = requests.get(host)
    return response.json().get("access_token")


def img_to_base64(file_path):
    with open(file_path, 'rb') as f:
        base_64_data = base64.b64encode(f.read())
        s = base_64_data.decode()
        return s


def FaceDetect(token_, base_64_data):
    params = {}
    request_url = "https://aip.baidubce.com/rest/2.0/face/v3/detect"
    params["image"] = base_64_data
    params["image_type"] = "BASE64"
    params["face_field"] = "age,beauty"
    access_token = token_
    request_url = request_url + "?access_token=" + access_token
    headers = {'content-type': 'application/json'}
    response = requests.post(request_url, data=params, headers=headers)
    if response:
        print(response.json())
        print(response.json()["result"]["face_list"][0]["age"])
        return(response.json()["result"]["face_list"][0]["beauty"])


def face(photo):
    base_64 = img_to_base64(photo)     #图片格式转换
    token  = getToken()                #获取json格式的token信息
    return(FaceDetect(token, base_64)) #获取微笑值


print("微笑值:",face('444.png'))

传入一种人脸图片路径后运行程序会得到如下结果,微笑值显示为48.19,如果输入的不是人脸则会报错


步骤5:微笑值换算成压岁钱在红包中显示

此步骤用到了前面提到的PIL图像处理库的文字绘制功能以及pygame库的图片显示功能,没有用到新的知识点,只需将以上步骤的微笑值扩大100倍后显示即可,当然扩大缩小的系数可以随意调整,详细过程在后面的程序中介绍

步骤6:使用python脚本操作打印机

程序文件名为"print_photo"

import pprint, cups  #打印机库
import time
def printing(picture):
    conn = cups.Connection()
    printers = conn.getPrinters ()
    pprint.pprint(printers)
    print()
    printer = conn.getDefault()
    print("Default1:", printer)
    if printer == None:
        printer = list(printers.keys())[0]
        print("Default2:", printer)
    myfile = picture                        #传入文件地址
    pid = conn.printFile(printer, myfile, "test", {})     #设置打印参数
    while conn.getJobs().get(pid, None) is not None:    #开始打印
        time.sleep(1)

上面的程序实现了传入一张图片,python程序自动打印,在程序成功运行之前还需要做下面的配置工作

下载打印驱动

树莓派的默认系统基于 Debian ,我们需要安装支持 Debian系统的打印机驱动,hp打印机对于 Debian系统或者说Linux内核系统是支持比较好的,所以本次项目中的打印机我们选用的是hp2312喷墨打印机,在 hp 官网搜索驱动,会提示Linux 系统的驱动由 hplip 提供

下面是hp驱动官网地址

https://developers.hp.com/hp-linux-imaging-and-printing/gethplip


在下拉菜单中我们选择Debian系统,接着按提示一步步下载


安装驱动

下载完成后,接着我们安装打印机驱动,打印机插到树莓派上,然后将下载的 hplip-3.20.11.run 文件直接放到树莓派目录中,修改一下执行权限,然后输入下面指令运行

$ chmod 755 hplip-3.20.11.run

$ ./hplip-3.20.11.run

安装过程比较长,会需要一些交互输入,会让你输入管理员账号的密码,账号密码为树莓派默认,然后耐心的等待就好

测试打印

现在树莓派已经可以进行正常的打印了,我们随便打开一个文档,打印测试一下

确定没有问题再进行接下来的操作

按键及LED灯控制

按键控制需要用到树莓派GPIO引脚控制函数库

命令行输入下面的指令安装GPIO库,如果报错可能系统已经自带了GPIO库,可以输入import RPi.GPIO as GPIO指令测试

sudo apt-get install python3-rpi.gpio

这里需要注意的是树莓派有两种引脚序号的编排方式,我们此次使用的是BCM方式,也就是下图外测的GPIO引脚序号


我们将红色和绿色数字按键分别接12、13号引脚,红色和绿色LED灯分别接26、27号引脚,运行下面程序,会看到,当红色按键按下时红灯点亮,绿色按键按下时绿灯点亮,测试一切正常,接下来就可以将按键和LED灯用在"最牛打印机"中了

import RPi.GPIO as GPIO  #//引入函数库


GPIO.setmode(GPIO.BCM)  #//设置引脚编号规则
GPIO.setup(12, GPIO.IN)    #red  Button//将12号引脚设置成输出模式
GPIO.setup(13, GPIO.IN)    #green Buttoon//将13号引脚设置成输出模式
GPIO.setup(26, GPIO.OUT)#red  LED
GPIO.setup(27, GPIO.OUT)#green  LED


if GPIO.input(13) == 1:#green Button  选择
      
      GPIO.output(27,GPIO.HIGH)#green  LED


else:
      GPIO.output(27,GPIO.LOW)


if GPIO.input(12) == 1:#red  Button  确认
      GPIO.output(26,GPIO.HIGH)#red   LED


else:
      GPIO.output(26,GPIO.LOW)

GPIO按键在“春节大红包”中的控制程序如下图,绿色大按键用来选择红包,红色按键确认后将选择的红包放大显示,如果红色大按键和绿色大按键同时按键后会跳出当前模式回到主函数的界面

while True:
          if GPIO.input(13) == 1 and GPIO.input(12) == 1:
                
              GPIO.output(26,GPIO.LOW)
              GPIO.output(27,GPIO.LOW)
              return 1
              break
          else:
              if GPIO.input(13) == 1:#green Button  选择
                  GPIO.output(27,GPIO.HIGH)#green  LED
                  num_green+=1
                  print(num_green)
              else:GPIO.output(27,GPIO.LOW)
              if GPIO.input(13) == 0 and num_green >350:
                  pygame.draw.rect(window,(255,255,255),(490,photo_h[j]-10,width+20,height+20),3)
                  pygame.draw.circle(window,(255,255,255),(420,text_h[j]),8,0)
                  j+=1
                  if j>1:j=0
                  pygame.draw.rect(window,(0,0,0),(490,photo_h[j]-10,width+20,height+20),3)
                  pygame.draw.circle(window,(0,0,0),(420,text_h[j]),8,0)
                  pygame.display.update()
                  num_green=0
              if GPIO.input(12) == 1:#red  Button  确认
                  GPIO.output(26,GPIO.HIGH)#red   LED
                  num_red+=1
              else:GPIO.output(26,GPIO.LOW)
              if GPIO.input(12) == 0 and num_red >350:
                  num_red=0
                  print("回车")
                  window.fill((255,255,255))
                  photo2=pygame.image.load(picture[j])
                  photo2=pygame.transform.rotozoom(photo2,0,0.28)
                  window.blit(photo2,(420,350))
                  picture_circle(j)
                  time.sleep(1)
                  print("printing")
                  print_photo.printing('round_avatar.png')
                  return 1
                  break
完整程序

下面为“最牛打印机”模式一:“春节大红包”的所有代码,其中微笑值程序,照片拍摄程序和打印机程序为单独的python程序文件,使用时直接以import的方式调用程序名即可,程序中具体代码在前面已经详细介绍

import PIL, PIL.Image,PIL.ImageTk,PIL.ImageDraw, PIL.ImageFont, PIL.ImageFilter    #图像处理库
import numpy              #科学计算库
import os,time,pygame     #文件操作库,时间库,游戏库
import print_photo        #打印机打印程序
import face,make_camera   #微笑值程序,照片拍摄程序
import RPi.GPIO as GPIO  #//引入函数库


GPIO.setmode(GPIO.BCM)  #//设置引脚编号规则
GPIO.setup(12, GPIO.IN)    #red  Button//将12号引脚设置成输出模式
GPIO.setup(13, GPIO.IN)    #green Buttoon//将13号引脚设置成输出模式
GPIO.setup(26, GPIO.OUT)#red  LED
GPIO.setup(27, GPIO.OUT)#green  LED


def picture_circle(j):
    x_w = 0 # 窗口距屏幕左边距离
    y_h = 30 # 窗口距屏幕上边距离
    #初始化
    pygame.init()
    os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (x_w, y_h)
    #创建游戏窗口
    window=pygame.display.set_mode((1900,1000))
    #设置窗口标题
    pygame.display.set_caption("属我最牛")
    #设置背景颜色
    window.fill((255,255,255))
    pygame.display.update()
    picture=["./card/1.png","./card/2.png"]
    while (GPIO.input(13) == 0):
        #pixels.fill((255,255,255))
        make_camera.camera()                             #拍摄照片
        text=str(int(face.face('classPhoto.png')*100))   #获取微笑值比计算为红包金额
        if j==0:
            R,G,B=255,255,0
        if j==1:
            R,G,B=255,0,0
        ttf = PIL.ImageFont.truetype('华文琥珀.TTF',90)  #红包金额的显示字体
        bg_size = (1328, 590)
        # 生成一张尺寸为 750x1334 背景色为白色的图片
        #bg = PIL.Image.new('RGB', bg_size, color=(255,0,0))
        bg = PIL.Image.open(picture[j]).convert('RGBA').resize(bg_size, PIL.Image.ANTIALIAS)
        draw = PIL.ImageDraw.Draw(bg)
        draw.text((770,430),text+'元',font=ttf,fill=(R,G,B))  #红包金额显示在图片上
        # 头像尺寸
        avatar_size = (430, 430)
        # 头像路径
        avatar_path = os.path.join('classPhoto.png')
        # 加载头像文件到 avatar
        avatar = PIL.Image.open(avatar_path)
        # 把头像的尺寸设置成我们需要的大小
        avatar = avatar.resize(avatar_size)
        # 新建一个蒙板图, 注意必须是 RGBA 模式
        mask = PIL.Image.new('RGBA', avatar_size, color=(0,0,0,0))
        # 画一个圆
        mask_draw = PIL.ImageDraw.Draw(mask)
        mask_draw.ellipse((0,0, avatar_size[0], avatar_size[1]), fill=(0,0,0,255))
        # 计算头像位置
        x, y = int((bg_size[0]-avatar_size[0])/2), int((bg_size[1]-avatar_size[1])/2)
        # box 为头像在 bg 中的位置
        # box(x1, y1, x2, y2)
        # x1,y1 为头像左上角的位置
        # x2,y2 为头像右下角的位置
        x-=375
        box = (x, y, (x + avatar_size[0]), (y + avatar_size[1]))
        # 以下使用到paste(img, box=None, mask=None)方法
        #   img 为要粘贴的图片对你
        #   box 为图片 头像在 bg 中的位置
        #   mask 为蒙板,原理同 ps, 只显示 mask 中 Alpha 通道值大于等于1的部分
        bg.paste(avatar, box, mask)
        # 要保存图片的路径
        img_path = os.path.join('round_avatar.png')
        # 保存图片
        bg.save(img_path)
        print('保存成功 at {}'.format(img_path))
        photo=pygame.image.load('round_avatar.png')


        window.blit(photo,(200,150))
        pygame.display.update()


def newyear():
      x_w = 0 # 窗口距屏幕左边距离
      y_h = 30 # 窗口距屏幕上边距离
      flag = 0
      #初始化
      pygame.init()
      os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (x_w, y_h)
      #创建游戏窗口
      window=pygame.display.set_mode((1900,1000))
      #设置窗口标题
      pygame.display.set_caption("属我最牛")
      #设置背景颜色
      window.fill((255,255,255))
      photo_h=[70,500]
      text_h=[218,678]
      j=0
      picture=["./card/1.png","./card/2.png"]
      photo1=pygame.image.load(picture[j])#加载图片
      photo1=pygame.transform.rotozoom(photo1,0,0.3)#图片缩放
      window.blit(photo1,(500,70))
      photo2=pygame.image.load(picture[j+1])
      photo2=pygame.transform.rotozoom(photo2,0,0.3)
      window.blit(photo2,(500,500))
      width,height = photo2.get_size()
      print(width,height)
      #画矩形rect(画在哪里,线的颜色,矩形的范围(起点坐标,宽和高),线宽)
      pygame.draw.rect(window,(0,0,0),(490,photo_h[0]-10,width+20,height+20),3)
      #画圆circle(画在哪里,线的颜色,圆心的坐标,半径,线宽=0实心)
      pygame.draw.circle(window,(0,0,0),(420,218),20,2)
      pygame.draw.circle(window,(0,0,0),(420,218),8,0)
      pygame.draw.circle(window,(0,0,0),(420,678),20,2)
      #Font(字体文件路径,字号)
      font = pygame.font.Font('李旭科书法.ttf',50)
      #render(文字内容,True,文字颜色,背景颜色)
      text_a = font.render('A',True,(0,0,0),(255,255,255))
      text_b = font.render('B',True,(0,0,0),(255,255,255))
      window.blit(text_a,(370,190))
      window.blit(text_b,(370,650))


      pygame.display.flip()
      num_green,num_red=0,0
      while True:
            if GPIO.input(13) == 1 and GPIO.input(12) == 1:
                
                GPIO.output(26,GPIO.LOW)
                GPIO.output(27,GPIO.LOW)
                return 1
                break
            else:
                if GPIO.input(13) == 1:#green Button  选择
                    GPIO.output(27,GPIO.HIGH)#green  LED
                    num_green+=1
                    print(num_green)
                else:GPIO.output(27,GPIO.LOW)
                if GPIO.input(13) == 0 and num_green >350:
                    pygame.draw.rect(window,(255,255,255),(490,photo_h[j]-10,width+20,height+20),3)
                    pygame.draw.circle(window,(255,255,255),(420,text_h[j]),8,0)
                    j+=1
                    if j>1:j=0
                    pygame.draw.rect(window,(0,0,0),(490,photo_h[j]-10,width+20,height+20),3)
                    pygame.draw.circle(window,(0,0,0),(420,text_h[j]),8,0)
                    pygame.display.update()
                    num_green=0
                if GPIO.input(12) == 1:#red  Button  确认
                    GPIO.output(26,GPIO.HIGH)#red   LED
                    num_red+=1
                else:GPIO.output(26,GPIO.LOW)
                if GPIO.input(12) == 0 and num_red >350:
                    num_red=0
                    print("回车")
                    window.fill((255,255,255))
                    photo2=pygame.image.load(picture[j])
                    photo2=pygame.transform.rotozoom(photo2,0,0.28)
                    window.blit(photo2,(420,350))
                    picture_circle(j)
                    time.sleep(1)
                    print("printing")
                    print_photo.printing('round_avatar.png')
                    return 1
                    break
                
            #检测事件
            for event in pygame.event.get():#遍历事件
                #检测关闭按钮是否被点击
                if event.type == pygame.QUIT:
                    #退出
                    exit() 
newyear()                                           

程序运行后会出现如下画面,绿色大按键按下可以让矩形框和实心圆在两种红包模式中交替切换显示


当红色大按钮按下后会出现下面的运行结果,摄像头采集照片,将图像经过PIL库处理后显示在红包素材上,同时将百度智能云返回的微笑值数据换算成压岁钱的金额显示在红包素材上


用户确认红包后,长按绿色大按键进行打印,打印出的效果如下图所示


模式二:拜年牛海报


准备海报模板

第一步我们需要准备符合牛年主题的拍照海报,寻找素材时要有一块比较明显的区域用来显示人像,下面是本次项目中用到的3种拍照模板A、B、C


实现流程

当你掌握了“春节大红包”模式后,你会发现“拜年牛海报”的模式会非常的简单

接下来我们来看一下“拜年牛海报”模式的实现流程,包含4个步骤,同“春节大红包”基本类似,不同的是少了两个步骤,只需要采集图像,处理图像,显示图像和打印图像就可以了


步骤1:pygame显示海报模板

同样需要使用pygame库,安装库和调用程序方式参考“春节大红包”模式

步骤2:picamera图像采集

需要安装picamera库,调用程序和安装库方式与“春节大红包”模式也完全相同

步骤3:图像处理

需要使用PIL库,使用方法和“春节大红包”类似,不同的是,“拜年牛海报”模式下需要将人像以圆形和菱形两种方式进行显示,下面的代码中提供了圆形和菱形图案的绘制方法

while (GPIO.input(13) == 0):
            #pixels.fill((255,255,255))
            make_camera.camera()
            # 背景尺寸
            bg_size = (585, 801)
            # 生成一张尺寸为 750x1334 背景色为白色的图片
            bg = PIL.Image.open(picture[j]).convert('RGBA').resize(bg_size, PIL.Image.ANTIALIAS)
            draw = PIL.ImageDraw.Draw(bg)
            # 头像尺寸
            if j==0:#海报1圆形
                avatar_size = (320, 320)
                x, y = int((bg_size[0]-avatar_size[0])/2), int((bg_size[1]-avatar_size[1])/2)-30
            if j==1:#海报2菱形
                avatar_size = (360, 360)
                box_polygon=(avatar_size[0]/2,0, avatar_size[0], avatar_size[1]/2,avatar_size[0]/2,avatar_size[1],0,avatar_size[1]/2)
                x, y = int((bg_size[0]-avatar_size[0])/2)+10, int((bg_size[1]-avatar_size[1])/2)-60
            if j==2:#海报3圆形       
                avatar_size = (300, 300)
                x, y = int((bg_size[0]-avatar_size[0])/2)-20, int((bg_size[1]-avatar_size[1])/2)-90
            # 头像路径
            avatar_path = os.path.join('classPhoto.png')
            # 加载头像文件到 avatar
            avatar = PIL.Image.open(avatar_path)
            # 把头像的尺寸设置成我们需要的大小
            avatar = avatar.resize(avatar_size)
            # 新建一个蒙板图, 注意必须是 RGBA 模式
            mask = PIL.Image.new('RGBA', avatar_size, color=(255,0,0,0))
            mask_draw = PIL.ImageDraw.Draw(mask)
            if j==1:#菱形
                mask_draw.polygon(box_polygon, fill=(0,0,0,255))
            else:#圆形
                mask_draw.ellipse((0,0, avatar_size[0], avatar_size[1]), fill=(0,0,0,255))
            # 计算头像位置       
            # box 为头像在 bg 中的位置
            # box(x1, y1, x2, y2)
            # x1,y1 为头像左上角的位置
            # x2,y2 为头像右下角的位置           
            box = (x, y, (x + avatar_size[0]), (y + avatar_size[1]))
            # 以下使用到paste(img, box=None, mask=None)方法
            #   img 为要粘贴的图片对象
            #   box 为图片 头像在 bg 中的位置
            #   mask 为蒙板,原理同 ps, 只显示 mask 中 Alpha 通道值大于等于1的部分
            bg.paste(avatar, box, mask)
            # 要保存图片的路径
            img_path = os.path.join('round_avatar.png')
            # 保存图片
            bg.save(img_path)

步骤4:打印海报

调用“print_photo”程序,方法同“春节大红包”

按键和LED灯控制

同样需要调用GPIO库,方法类似

下图为GPIO按键在“春节大红包”中的控制程序,绿色大按键用来选择海报,红色按键确认后将选择的海报放大显示,如果红色大按键和绿色大按键同时按下后会跳出当前模式回到主函数的界面

while True:
         if GPIO.input(13) == 1 and GPIO.input(12) == 1:
             GPIO.output(26,GPIO.LOW)
             GPIO.output(27,GPIO.LOW)
             return 3
             break
         else:
             if GPIO.input(13) == 1:#green Button
                 GPIO.output(27,GPIO.HIGH)#green  LED
                 num_green+=1
                 print(num_green)
             else:GPIO.output(27,GPIO.LOW)
             if GPIO.input(13) == 0 and num_green >350:
                 pygame.draw.circle(window,(255,255,255),(circle_w[j],750),8,0)
                 pygame.draw.rect(window,(255,255,255),(photo_w[j]-15,100,width+25,height+20),3)
                 j+=1
                 if j>2: j=0
                 pygame.draw.rect(window,(0,0,0),(photo_w[j]-15,100,width+25,height+20),3)
                 pygame.draw.circle(window,(0,0,0),(circle_w[j],750),8,0)
                 pygame.display.update()
                 num_green=0
             if GPIO.input(12) == 1:#red  Button
                 GPIO.output(26,GPIO.HIGH)#red  LED
                 num_red+=1
             else:GPIO.output(26,GPIO.LOW)
             if GPIO.input(12) == 0 and num_red >350:
                 num_red=0
                 window.fill((255,255,255))
                 photo_ox(j)
                 time.sleep(1)
                 print("printing")
                 print_photo.printing('round_avatar.png')
                 return 3
                 break       
“拜年牛海报”的完整程序

下面为“最牛打印机”模式二:“拜年牛海报”的所有代码,其中照片拍摄程序和打印机程序为单独的python程序文件,使用时直接以import的方式调用程序名即可,具体代码前面已经详细介绍

将“拜年牛海报”和“春节大红包”的代码进行对比,你会发现“春节大红包”的素材是竖向显示的,而“拜年牛海报”的海报素材则是横向显示的

import PIL, PIL.Image,PIL.ImageTk,PIL.ImageDraw, PIL.ImageFont, PIL.ImageFilter  #图像处理库
import numpy                #科学计算库
import os,time,pygame       #游戏库
import print_photo          #打印机打印程序
import make_camera          #照片拍摄程序
import RPi.GPIO as GPIO     #//引入函数库


GPIO.setmode(GPIO.BCM)      #//设置引脚编号规则
GPIO.setup(12, GPIO.IN)     #red  Button//将12号引脚设置成输出模式
GPIO.setup(13, GPIO.IN)     #green Button//将13号引脚设置成输出模式
GPIO.setup(26, GPIO.OUT)    #red LED
GPIO.setup(27, GPIO.OUT)    #green LED
 
def photo_ox(j):
        picture=["./new_year/ox1.png","./new_year/ox3.png","./new_year/ox8.png"]
        x_w = 0 # 窗口距屏幕左边距离
        y_h = 30 # 窗口距屏幕上边距离
         #初始化
        pygame.init()
        os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (x_w, y_h)
        #创建游戏窗口
        window=pygame.display.set_mode((1900,1000))
        #设置窗口标题
        pygame.display.set_caption("属我最牛")
        #设置背景颜色
        window.fill((255,255,255))
        while (GPIO.input(13) == 0):
            #pixels.fill((255,255,255))
            make_camera.camera()
            # 背景尺寸
            bg_size = (585, 801)
            # 生成一张尺寸为 750x1334 背景色为白色的图片
            bg = PIL.Image.open(picture[j]).convert('RGBA').resize(bg_size, PIL.Image.ANTIALIAS)
            draw = PIL.ImageDraw.Draw(bg)
            # 头像尺寸
            if j==0:#海报1圆形
                avatar_size = (320, 320)
                x, y = int((bg_size[0]-avatar_size[0])/2), int((bg_size[1]-avatar_size[1])/2)-30
            if j==1:#海报2菱形
                avatar_size = (360, 360)
                box_polygon=(avatar_size[0]/2,0, avatar_size[0], avatar_size[1]/2,avatar_size[0]/2,avatar_size[1],0,avatar_size[1]/2)
                x, y = int((bg_size[0]-avatar_size[0])/2)+10, int((bg_size[1]-avatar_size[1])/2)-60
            if j==2:#海报3圆形       
                avatar_size = (300, 300)
                x, y = int((bg_size[0]-avatar_size[0])/2)-20, int((bg_size[1]-avatar_size[1])/2)-90
            # 头像路径
            avatar_path = os.path.join('classPhoto.png')
            # 加载头像文件到 avatar
            avatar = PIL.Image.open(avatar_path)
            # 把头像的尺寸设置成我们需要的大小
            avatar = avatar.resize(avatar_size)
            # 新建一个蒙板图, 注意必须是 RGBA 模式
            mask = PIL.Image.new('RGBA', avatar_size, color=(255,0,0,0))
            mask_draw = PIL.ImageDraw.Draw(mask)
            if j==1:#菱形
                mask_draw.polygon(box_polygon, fill=(0,0,0,255))
            else:#圆形
                mask_draw.ellipse((0,0, avatar_size[0], avatar_size[1]), fill=(0,0,0,255))
            # 计算头像位置       
            # box 为头像在 bg 中的位置
            # box(x1, y1, x2, y2)
            # x1,y1 为头像左上角的位置
            # x2,y2 为头像右下角的位置           
            box = (x, y, (x + avatar_size[0]), (y + avatar_size[1]))
            # 以下使用到paste(img, box=None, mask=None)方法
            #   img 为要粘贴的图片对象
            #   box 为图片 头像在 bg 中的位置
            #   mask 为蒙板,原理同 ps, 只显示 mask 中 Alpha 通道值大于等于1的部分
            bg.paste(avatar, box, mask)
            # 要保存图片的路径
            img_path = os.path.join('round_avatar.png')
            # 保存图片
            bg.save(img_path)
            print('保存成功 at {}'.format(img_path))
            photo=pygame.image.load('round_avatar.png')
            #photo=pygame.transform.rotozoom(photo,0,0.5)
            window.blit(photo,(600,60))
            pygame.display.update()
        
def ox():
      x_w = 0 # 窗口距屏幕左边距离
      y_h = 30 # 窗口距屏幕上边距离
      flag=0
      #初始化
      pygame.init()
      os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (x_w, y_h)
      #创建游戏窗口
      window=pygame.display.set_mode((1900,1000))
      #设置窗口标题
      pygame.display.set_caption("属我最牛")
      #设置背景颜色
      window.fill((255,255,255))
      photo_w=[300,730,1220]
      circle_w=[510,940,1430]
      text_w=[430,880,1370]
      j=0
      picture=["./new_year/ox1.png","./new_year/ox3.png","./new_year/ox8.png"]
      photo_1=pygame.image.load(picture[j])
      photo_1=pygame.transform.rotozoom(photo_1,0,0.45)
      window.blit(photo_1,(310,120))
      photo_2=pygame.image.load(picture[j+1])
      photo_2=pygame.transform.rotozoom(photo_2,0,0.22)
      window.blit(photo_2,(750,120))
      photo_3=pygame.image.load(picture[j+2])
      photo_3=pygame.transform.rotozoom(photo_3,0,0.21)
      window.blit(photo_3,(1220,120))
      width,height = photo_3.get_size()
      print(width,height)
      pygame.draw.rect(window,(0,0,0),(photo_w[j]-15,100,width+25,height+20),3)
      #画圆circle(画在哪里,线的颜色,圆心的坐标,半径,线宽=0实心)
      pygame.draw.circle(window,(0,0,0),(circle_w[j],750),20,2)
      pygame.draw.circle(window,(0,0,0),(circle_w[j+1],750),20,2)
      pygame.draw.circle(window,(0,0,0),(circle_w[j+2],750),20,2)
      pygame.draw.circle(window,(0,0,0),(circle_w[j],750),8,0)
      font = pygame.font.Font('李旭科书法.ttf',50)
      text_a = font.render('A',True,(0,0,0),(255,255,255))
      text_b = font.render('B',True,(0,0,0),(255,255,255))
      text_c = font.render('C',True,(0,0,0),(255,255,255))
      window.blit(text_a,(text_w[j],720))
      window.blit(text_b,(text_w[j+1],720))
      window.blit(text_c,(text_w[j+2],720))    
      pygame.display.flip()
      num_green,num_red=0,0
      while True:
            if GPIO.input(13) == 1 and GPIO.input(12) == 1:
                GPIO.output(26,GPIO.LOW)
                GPIO.output(27,GPIO.LOW)
                return 3
                break
            else:
                if GPIO.input(13) == 1:#green Button
                    GPIO.output(27,GPIO.HIGH)#green  LED
                    num_green+=1
                    print(num_green)
                else:GPIO.output(27,GPIO.LOW)
                if GPIO.input(13) == 0 and num_green >350:
                    pygame.draw.circle(window,(255,255,255),(circle_w[j],750),8,0)
                    pygame.draw.rect(window,(255,255,255),(photo_w[j]-15,100,width+25,height+20),3)
                    j+=1
                    if j>2: j=0
                    pygame.draw.rect(window,(0,0,0),(photo_w[j]-15,100,width+25,height+20),3)
                    pygame.draw.circle(window,(0,0,0),(circle_w[j],750),8,0)
                    pygame.display.update()
                    num_green=0
                if GPIO.input(12) == 1:#red  Button
                    GPIO.output(26,GPIO.HIGH)#red  LED
                    num_red+=1
                else:GPIO.output(26,GPIO.LOW)
                if GPIO.input(12) == 0 and num_red >350:
                    num_red=0
                    window.fill((255,255,255))
                    photo_ox(j)
                    time.sleep(1)
                    print("printing")
                    print_photo.printing('round_avatar.png')
                    return 3
                    break       
            #检测事件
            for event in pygame.event.get():#遍历事件
                #检测关闭按钮是否被点击
                if event.type == pygame.QUIT:
                    #退出
                    exit()
ox()                              

运行程序后会出现如下画面,绿色大按键按下可以让矩形框和实心圆在3种不同的海报模式中交替切换显示


当红色大按钮按下后会出现下面的运行结果,摄像头采集照片,将人像经过PIL库处理后显示在海报素材上,显示效果如下图所示


用户选好海报后,长按绿色大按键进行打印,打印出的效果如下图所示


“最牛打印机”的两种最关键的模式掌握后,意味着你已经打开了不一样的牛年

最后我们再来了解一下主函数的运行过程

主函数

主函数实现的主要步骤为,绿色大按键按下可以在三种不同的模式中切换,红色大按键按下为确认,进入相对应的模式,相信掌握了前面模式的你,一定对于主函数的程序有了大体思路


主函数与三种模式的关系如下图所示,在主函数中以import调用程序名方式调用三种模式


主函数的界面显示的方法与“春节大红包”模式类似,也是竖向显示

每个模式的图片通过PIL库进行了圆角处理,处理的细节程序如下

此自定义函数使用时需要传入两个参数,分别是图片对象和圆角半径,程序运行后会返回一个处理过圆角的图像

def circle_corner(img, radii):
    """
    圆角处理
    :circle_corner img: 源图像。
    :circle_corner radii: 半径,如:30。
    :return: 返回一个圆角处理后的图像。
    """
    # 画圆(用于分离4个角)
    circle = PIL.Image.new('L', (radii * 2, radii * 2), 0)  # 创建一个黑色背景的画布
    draw = PIL.ImageDraw.Draw(circle)
    draw.ellipse((0, 0, radii * 2, radii * 2), fill=255)  # 画白色圆形
    # 原图
    img = img.convert("RGBA")
    w, h = img.size
    # 画4个角(将整圆分离为4个部分)
    alpha = PIL.Image.new('L', img.size, 255)
    alpha.paste(circle.crop((0, 0, radii, radii)), (0, 0))  # 左上角
    alpha.paste(circle.crop((radii, 0, radii * 2, radii)), (w - radii, 0))  # 右上角
    alpha.paste(circle.crop((radii, radii, radii * 2, radii * 2)), (w - radii, h - radii))  # 右下角
    alpha.paste(circle.crop((0, radii, radii, radii * 2)), (0, h - radii))  # 左下角
    #alpha.show()
    img.putalpha(alpha)  # 白色区域透明可见,黑色区域不可见
    img_path = os.path.join('123.png')
    img.save(img_path)
    return ('123.png')

三种不同模式的图像经过处理后就可以使用前面提到的pygame库中图像,文字,图形的处理方法将主函数的界面显示出来了,

绿色大按键按下在三种模式中切换选择,红色大按键确认,在三种模式运行结束后或者红色大按键和绿色大按键同时按下会返回不同的数值,根据不同的数值会执行主函数的递归调用,重新显示主函数的界面

while True:
       if GPIO.input(13) == 1:#green按键
           GPIO.output(27,GPIO.HIGH)#green LED
           time.sleep(0.2)
           pygame.draw.circle(window,(255,255,255),(x-130,y+height//2+40),8,0)
           pygame.draw.rect(window,(255,255,255),(x-20,y-20,width+40,height+37),3)
           y+=300
           count+=1
           if y>770:y=72
           if count>3:count=1
           pygame.draw.rect(window,(0,0,0),(x-20,y-20,width+40,height+37),3)
           pygame.draw.circle(window,(0,0,0),(x-130,y+height//2+40),8,0)
           pygame.display.update()
       else:GPIO.output(27,GPIO.LOW)
       if GPIO.input(12) == 1:#red 按键
           GPIO.output(26,GPIO.HIGH)#red LED
           time.sleep(1)
           GPIO.output(26,GPIO.LOW)#根据count数值选择对应的模式
           if count ==1:flag=star.star()
           if count ==2:flag=cow.ox()
           if count ==3:flag=new_year.newyear()
       if flag == 1 or flag==2 or flag ==3:
           pygame.display.quit() 
           page()   #递归调用  重新回到主函数显示   

主函数的完整程序如下图所示,这里解释一下,在几个程序中PIL库的调用使用了有点麻烦的PIL.XXX调用方式,原因是为了避免与其他库中图像处理的Image指令重复

import PIL, PIL.Image,PIL.ImageTk,PIL.ImageDraw, PIL.ImageFont, PIL.ImageFilter  #图像处理库
import numpy                #科学计算库
from random import randint  #随机数库
import os                   #文件操作库
import pygame               #游戏库
import time                 #时间库
import new_year             #新年红包程序
import cow                  #拜年牛海报程序
import star                 #有声明信片程序
import qrcode_cook          #自动生成音频二维码程序
import print_photo          #打印机打印程序
import RPi.GPIO as GPIO     #//引入GPIO函数库
GPIO.setmode(GPIO.BCM)      #//设置引脚编号规则
GPIO.setup(12, GPIO.IN)     #red Button  //将12号引脚设置成输入模式
GPIO.setup(13, GPIO.IN)     #green Button  //将13号引脚设置成输入模式
GPIO.setup(26, GPIO.OUT)    #red   LED
GPIO.setup(27, GPIO.OUT)    #green  LED


def circle_corner(img, radii):
    """
    圆角处理
    :circle_corner img: 源图像。
    :circle_corner radii: 半径,如:30。
    :return: 返回一个圆角处理后的图像。
    """
    # 画圆(用于分离4个角)
    circle = PIL.Image.new('L', (radii * 2, radii * 2), 0)  # 创建一个黑色背景的画布
    draw = PIL.ImageDraw.Draw(circle)
    draw.ellipse((0, 0, radii * 2, radii * 2), fill=255)  # 画白色圆形
    # 原图
    img = img.convert("RGBA")
    w, h = img.size
    # 画4个角(将整圆分离为4个部分)
    alpha = PIL.Image.new('L', img.size, 255)
    alpha.paste(circle.crop((0, 0, radii, radii)), (0, 0))  # 左上角
    alpha.paste(circle.crop((radii, 0, radii * 2, radii)), (w - radii, 0))  # 右上角
    alpha.paste(circle.crop((radii, radii, radii * 2, radii * 2)), (w - radii, h - radii))  # 右下角
    alpha.paste(circle.crop((0, radii, radii, radii * 2)), (0, h - radii))  # 左下角
    #alpha.show()
    img.putalpha(alpha)  # 白色区域透明可见,黑色区域不可见
    img_path = os.path.join('123.png')
    img.save(img_path)
    return ('123.png')


def page():
    
      flag,count,i,x,y=0,1,0,1100,70
      x_w = 0 # 窗口距屏幕左边距离
      y_h = 30 # 窗口距屏幕上边距离
      print(1)
      pygame.init()
      os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (x_w, y_h)#窗口显示在屏幕的左上角
      #创建游戏窗口
      window=pygame.display.set_mode((1900,1000),0,0)
      #设置窗口标题
      pygame.display.set_caption("属我最牛")
      #设置背景颜色
      window.fill((255,255,255))
      pygame.display.flip()
      print(2)
      text=["有声明信片",
            "拜年牛海报",
            " 春节大红包"]
      font = pygame.font.Font('李旭科书法.ttf',40)  #模式序号的字体
      font_title = pygame.font.Font('STHUPO.TTF',50)#标题的字体
      path = "./page_1"
      files = os.listdir(path)
      for file in files:#遍历files中的所有图片并显示
            img = PIL.Image.open(path+'/'+file)
            img = circle_corner(img, radii=200)
            #img.show()
            photo=pygame.image.load(img)
            #picture=["./page_1/1.png","./page_1/2.png","./page_1/3.png"]
            photo=pygame.transform.rotozoom(photo,0,0.2)
            width,height = photo.get_size()
            window.blit(photo,(x,y))
            pygame.draw.circle(window,(0,0,0),(x-130,y+height//2+40),20,2)
            text_a = font.render(text[i],True,(0,0,0))
            window.blit(text_a,(x-250,y+height//2-50)) 
            y+=300
            i+=1
      pygame.display.update()
      x,y=1100,72
      photo=pygame.image.load('./page_1/1.png')
      photo=pygame.transform.rotozoom(photo,0,0.2)
      width,height = photo.get_size()#获取图片的尺寸
      pygame.draw.rect(window,(0,0,0),(x-20,y-20,width+40,height+37),3)#显示矩形选择框
      pygame.draw.circle(window,(0,0,0),(x-130,y+height//2+40),8,0)    #显示圆形选项框
      text_b = font_title.render("属你最牛百变打印机",True,(255,0,0))  #显示标题
      text_c = font.render("选择",True,(0,0,0))                        #显示"选择"选项
      text_d = font.render("确认",True,(0,0,0))                        #显示"确认"选项
      window.blit(text_b,(450,40))
      window.blit(text_c,(210,370))
      window.blit(text_d,(510,370))
      img_red = PIL.Image.open('./button/red.png') #显示红色按钮
      img_red = circle_corner(img_red, radii=200)
      photo_red=pygame.image.load(img_red)
      photo_red=pygame.transform.rotozoom(photo_red,0,0.3)
      window.blit(photo_red,(500,470))
      img_green = PIL.Image.open('./button/green.png') #显示绿色按钮
      img_green = circle_corner(img_green, radii=200)
      photo_green=pygame.image.load(img_green)
      photo_green=pygame.transform.rotozoom(photo_green,0,0.37)
      window.blit(photo_green,(200,470))
      pygame.display.update()
      while True:
          if GPIO.input(13) == 1:#green按键
              GPIO.output(27,GPIO.HIGH)#green LED
              time.sleep(0.2)
              pygame.draw.circle(window,(255,255,255),(x-130,y+height//2+40),8,0)
              pygame.draw.rect(window,(255,255,255),(x-20,y-20,width+40,height+37),3)
              y+=300
              count+=1
              if y>770:y=72
              if count>3:count=1
              pygame.draw.rect(window,(0,0,0),(x-20,y-20,width+40,height+37),3)
              pygame.draw.circle(window,(0,0,0),(x-130,y+height//2+40),8,0)
              pygame.display.update()
          else:GPIO.output(27,GPIO.LOW)
          if GPIO.input(12) == 1:#red 按键
              GPIO.output(26,GPIO.HIGH)#red LED
              time.sleep(1)
              GPIO.output(26,GPIO.LOW)#根据count数值选择对应的模式
              if count ==1:flag=star.star()
              if count ==2:flag=cow.ox()
              if count ==3:flag=new_year.newyear()
          if flag == 1 or flag==2 or flag ==3:
              pygame.display.quit() 
              page()   #递归调用  重新回到主函数显示         
          #检测事件
          for event in pygame.event.get():#遍历事件
              #检测关闭按钮是否被点击
              if event.type == pygame.QUIT:
                  #退出
                  exit()                           
if __name__ == '__main__':
      page()                                

以上就是关于“属你最牛”百变打印机的两种模式的介绍内容

下一期预告:模式三、有声明信片



#最后#


通过本次项目,我们学会了使用树莓派进行图像采集的方法,实现了通过请求百度智能云获取人脸图像的微笑值,掌握了使用PIL库处理图像,使用pygame库显示内容的技巧

相信创意远不止这样,你一定还有更多的想法,欢迎一起制作更多有趣,好玩的项目,旺仔爸爸期待与您一起交流

造物让生活更美好,我们下期再见

祝大家新的一年,牛转乾坤

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值