2223|2

330

帖子

5

TA的资源

纯净的硅(中级)

楼主
 

【行空板 Python编程学习主控板】基于行空板的电子相册 [复制链接]

行空板提供了一个完整的而非裁剪的Python运行环境,默认还安装好了PIL库,可以很方便的进行图形的处理。

同时,行空板自身还有屏幕,那么结合PIL,可以很快实现一个电子相册。

 

要想实现一个电子相册,需要以下几个方面的功能:

  1. 图片源文件
  2. 从相册目录获取供显示用的图片列表
  3. 等比缩放图片
  4. 显示图片

下面,我们就一项一项的来实现。

 

1. 图片源文件:

行空板带有16G的eMMC存储空间,系统占用了一部分,甚于空间还很多:

 

而行空板的自带的WEB管理界面,提供了文件上传的功能:

 

虽然一次只能上传一张图片,但是使用非常简单方便。

所以,这个电子相册,图片源文件,通过WEB界面,上传到/root/album/目录下。

 

2. 从相册目录获取供显示用的图片列表

在Python中,进行目录操作,获取目录内的文件列表,是一件非常容易的事情。

代码如下:

```

   import os

 

    # 获取图片文件列表
    files= os.listdir("/root/album/") #得到文件夹下的所有文件名称
    photos = []
    for file in files: #遍历文件夹
        file_path = "%s/%s" % (album_dir, file)
        print([file_path, os.path.isfile(file_path), file.endswith(".jpg")])
        if os.path.isfile(file_path) and file.endswith(".jpg"): # 判断是否是文件,且后缀为.jpg才使用
            photos.append(file_path) # 将文件路径存到list中

```

在上述代码逻辑如下:

  1. 通过 os.listdir 获取/root/album/目录内的文件列表
  2. 遍历获取的文件列表
  3. 如果是文件,且后缀为.jpg,则添加到图片列表中

其中的关键调用:

  • os.listdir() 方法:用于返回指定的文件夹包含的文件或文件夹的名字的列表
  • os.path.isfile()方法:用于判断路径是否为文件
  • file.endswith(".jpg"):用于判断文件名称后缀是否为.jpg

 

 

3. 等比缩放图片

为什么要等比缩放图片呢?直接显示不行吗?

当然可以直接显示,但是需要注意的是,行空板的屏幕分辨率为240x320,如果直接显示,那么小于这个尺寸的图片,就占不满屏幕,大于这个尺寸的图片,则会超出屏幕只显示一部分。

所以,我们需要对图片进行等比缩放,按照宽高比,等比缩放到宽最大240,高最大320大小。

光缩放图片还不行,缩放后,我们还要将图片放在正中央,缩放后的图片如果不是正好240x320大小,那么还要在旁边留黑或者留白。

 

在Python中,应用PIL的Image模块,可以很方便的进行图片的处理。

等比缩放并留边的代码如下:

```

           from PIL import Image

           w_max = 240 # 屏幕宽度
           h_max = 320 # 屏幕高度
           ratio_base = float(w_max) / h_max # 宽高比

 

           img = Image.open(file_path)
            
            w, h = img.size
            ratio = float(w) / h
            if ratio>ratio_base:
                w_s = w_max
                h_s = int(w_s * ratio)
            elif ratio < ratio_base:
                h_s = h_max
                w_s = int(h_s * ratio)
            else:
                w_s = w_max
                h_s = h_max
                            
            # 等比缩放图片
            img = img.resize((w_s, h_s),Image.ANTIALIAS)

            # 给图片四周留黑
            w_blank = int((w_max - w_s)/2)
            h_blank = int((h_max - h_s)/2)
            img2 = Image.new("RGB", (w_max, h_max), "black")
            img2.paste(img, (w_blank, h_blank))

```

 

上述代码的逻辑如下:

  1. 先定义最大尺寸,并计算宽高比
  2. 使用PIL.Image打开图片
  3. 计算打开图片的宽高比,与最大尺寸进行对比,然后计算出来等比缩放后的大小;计算后的大小,宽不超过240,高不超过320
  4. 将图片根据计算后的宽高结果,进行等比缩放
  5. 新生成一个240x320的图片,且默认为黑色black;如果留白,则用white
  6. 将等比缩放后的图片,拷贝到新的图片,且根据缩放后的宽高,设置好拷贝后的位置,使得其居中

其中的关键调用:

  • Image.open()方法:表示打开一个图片文件
  • Image.resize((宽度, 高度),Image.ANTIALIAS):表示调整图片的尺寸
    • Image.ANTIALIAS表示重新调整时,使用的采样规则。PIL提供了4种不同的采样规则:

      • ① NEAREST:最近滤波。从输入图像中选取最近的像素作为输出像素。

      • ② BILINEAR:双线性内插滤波。在输入图像的2*2矩阵上进行线性插值。

      • ③ BICUBIC:双立方滤波。在输入图像的4*4矩阵上进行立方插值。

      • ④ ANTIALIAS:平滑滤波。对所有可以影响输出像素的输入像素进行高质量的重采样滤波,以计算输出像素值。

  • Image.new("RGB", (宽度, 高度), "颜色")

    • 颜色可以为颜色的名称,也可以使元组表示RGB,例如(0,0,0)为黑色,(255,255,255)为白色,(255,0,0)为红色,其他以此类推

  • Image.paste(img, (x, y)):表示将img图片,拷贝到当前打开的图片的(x, y)坐标位置

 

4. 显示图片

图片有了,也等比缩放好了,现在就要显示图片了。

在行空板上,自带有GUI库,用于屏幕的操作,可以很方便的显示图片。

```

from unihiker import GUI   #导入包

gui=GUI()  #实例化GUI类
gui.clear() # 清除屏幕

photo_prev = None

 

photo_image = gui.draw_image(x=0, y=0, image=img2, origin='top_left')
if not photo_prev == None:
    # 移除上一次显示的图片
    photo_prev.remove()

photo_prev = photo_image

```

 

上述代码的逻辑如下:

  1. 初始化屏幕库,并清屏
  2. 将上一步调整好的图片,显示到屏幕上
  3. 并把前一张显示的图片移除

其中的关键调用如下:

  • gui=GUI():实例化一个GUi对象
  • gui.clear():清屏
  • gui.draw_image(x=0, y=0, image=img2, origin='top_left'):在屏幕上左上角为坐标原点显示图片,image可以直接为一个图片的绝对路径,也可以为PIL.Image打开的图片
  • photo_prev.remove():表示清除该控件,不限图片,其他控件也可以用

这里为什么每次显示后,要清除原有的呢?

因为,如果提前清除的话,屏幕可能会闪,有显示空挡;

如果不清除的话,那越显示积累越多,屏幕上堆的控件太多,会造成堆积问题,影响性能。

所以,每次显示后,清除老的。

 

5. 最终代码

整合上述各个部分的代码,最终代码如下:

import os
from unihiker import GUI   #导入包
from PIL import Image
from time import sleep


album_dir = "/root/album" #相册图片目录

w_max = 240 # 屏幕宽度
h_max = 320 # 屏幕高度
ratio_base = float(w_max) / h_max # 宽高比

gui=GUI()  #实例化GUI类
gui.clear() # 清除屏幕

while True:
    photo_prev = None # 上一个显示的图片

    # 获取图片文件列表
    files= os.listdir(album_dir) #得到文件夹下的所有文件名称
    photos = []
    for file in files: #遍历文件夹
        file_path = "%s/%s" % (album_dir, file)
        # print([file_path, os.path.isfile(file_path), file.endswith(".jpg")])
        if os.path.isfile(file_path) and file.endswith(".jpg"): # 判断是否是文件,且后缀为.jpg才使用
            photos.append(file_path) # 将文件路径存到list中

    if len(photos):
        # 遍历显示图片
        for i in range(0,len(photos)):
            file_path = photos[i]
            
            # 打开图片,并计算等比缩放后的宽高
            img = Image.open(file_path)
            
            w, h = img.size
            ratio = float(w) / h
            if ratio>ratio_base:
                w_s = w_max
                h_s = int(w_s * ratio)
            elif ratio < ratio_base:
                h_s = h_max
                w_s = int(h_s * ratio)
            else:
                w_s = w_max
                h_s = h_max
                            
            # 等比缩放图片
            img = img.resize((w_s, h_s),Image.ANTIALIAS)

            # 给图片四周留黑
            w_blank = int((w_max - w_s)/2)
            h_blank = int((h_max - h_s)/2)
            img2 = Image.new("RGB", (w_max, h_max), "black")
            img2.paste(img, (w_blank, h_blank))

            # print([img.size, img2.size]) 
            # 绘制图片
            photo_image = gui.draw_image(x=0, y=0, image=img2, origin='top_left')
            if not photo_prev == None:
                # 移除上一次显示的图片
                photo_prev.remove()
            photo_prev = photo_image
            img = None
            img2 = None
            sleep(3)
    sleep(3)

 

6. 实际效果:

最终实际效果,如视频所示:

362_1667792024

 

如果再配上音乐,效果就会更完美了,大家试试!

 

最新回复

行空板可以用ubuntu,用python开发程序是很方便的。     详情 回复 发表于 2022-11-8 06:39
点赞(1) 关注

回复
举报

7048

帖子

11

TA的资源

版主

沙发
 
乔老师,那是相片控呀,非常精彩的DEMO!
 
 

回复

115

帖子

0

TA的资源

一粒金砂(高级)

板凳
 

行空板可以用ubuntu,用python开发程序是很方便的。

 

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表