起因


喜欢的歌,静静地听;喜欢的人,远远的看。30天前,就是3月14号,我情不自禁地走近了《LoveLive!学院偶像祭》,这是我的第一张卡片(见下图)。第二天也就是3月15日,海未生日了。

 

之后我一直搜集游戏过程中遇到的卡片(截屏),卡片本身有一定的比例,而我的手机屏幕分辨率是 1920x1080,截完的图像下面这样。整个游戏界面并没有充满屏幕,所以有黑边;卡片比游戏界面小,截出的图很不美观而且方向不正。

中间的卡片的区域是 1080x1520

我本人并不是处女座,然而也不能忍受不美好的事物。于是一步一步地走上了程序员这条路。

我以为做程序员可以填满人生的遗憾。然而,制造更多遗憾的。却偏偏是做程序员。

(问:一个什么都拥有的程序猿他还缺少什么?)

非程序员的解决办法


  1. while( true )
  2. {
  3. PS 打开截图;
  4. 添加辅助线;
  5. 裁剪区域;
  6. 旋转正图像;
  7. sit,不对,是save;
  8. }

没图你说个毛啊!!!

谁说我没图,看图文并茂:

这些卡片在app中是以3位数字作为id编号的,可见数量实在不少。

这样不断循环,耗时费力,截完后累觉不爱了 :-(

Pythoner 的解决办法


第一版的程序

实现功能:处理图像(裁剪 + 旋转)

废话的流程图

程序代码大致是这样的:

运行后的结果,黑斑也没有了,头也不歪了,还有了新后缀,Ta好我也好:

第二版的程序


改进之处:图片文件自动命名

图片的命名规则:人物名字_属性_等级_星星数-N.png (其中N为正整数)

例如上图中的海未应该如此命名,园田海未_Pure_R_3-1.png

程序思路

1.人物名字如何命名?

建立相应的文件夹,将截图分类放到对应的文件夹下面,脚本获取文件夹名作为新名字的第一部分。

2.属性如何确认?

比较各张截图,人物卡片的右下角在固定位置有相同大小的圆圈,我们取坐标点 (920, 1400) 的 RGB 值判断。

 

下图右边是我一开始定义的字典,左边是运行过程中打印出来的 color

3.如何确定星星数(也就是角色的稀有度)?

搞完了右下角,我们来搞左下角。再做几条辅佐线,以确定来自星星的你的距离。

部分细心的读者肯定看到我从 ps 转向了 狗(嗯,我不记得软件的名字,除了图标)。

纵坐标大概递加 55px,获取坐标点的 color 值,如果不是 (8, 4, 34, 255) 计数变量的值就加1。

发现第二个元素的值有一点差别,其实也可以取指定位置的元素用来判断。

 

为了阅读的方便,数星星的代码搬到了这里。

  1. def get_count_of_star(image):
  2. count = 0
  3. positon_of_star = (33, 1090) #星星的初始位置,但星星是会运动的
  4. for i in range(0,8): #[0,8) 星星最多有8个
  5. color = image.getpixel(positon_of_star) #星星有发亮吗?
  6. positon_of_star = (33, positon_of_star[1]+55) #坐标下移到下一个星星处
  7. if color[2] != 34: #只比较第三个元素
  8. count += 1 #不是暗的,说明星星是有效的
  9. return count

参数 image 是已打开的图像,返回发亮星星的个数。

4.如何确定左上角的等级?

另外因为我不会文字识别,左上角的等级字符就无法获取,但是并不表示就不能解决这个问题。

观察众多的卡片发现了一条得到等级的捷径,这条捷径就是等级跟星星数是有对应关系的:

等级(左上角)

星星数(左下角)

N 1,  2
R 3,  4
SR 5,  6
UR 7,  8

有时只要转换一下思考的角度,也同样能解决问题。

代码设计


(一)工作路径相关

  1. import os
  2. os.getcwd() # 查看当前工作目录
  3. os.chdir("/home/luoxu") # 改变目录
  4.  
  5. for root, dirs, files in os.walk(dir):
  6. for name in files:
  7. print os.path.join(root, name)

os.listdir 可以列出 dir 里面的所有文件和目录,但不包括子目录中的内容
os.walk 可以遍历下面的所有目录,包括子目录,返回路径,路径下目录的元组和文件的元祖。

(二)获取某个目录下的 png 图像文件

glob 是 python 自带的一个文件操作相关模块,可以用来查找匹配的文件。

  1. import glob
  2. glob.glob('/home/luoxu/*.png')

参数是某个路径字符串,字符串可以为绝对路径也可以为相对路径,字符串最后部分表示匹配的文件类型。

*, ? , [ ] 三个通配符,* 代表 0 个或多个字符,? 代表一个字符,[ ] 匹配指定范围内的字符,如[0-9]匹配数字。

该方法返回所有匹配的文件路径列表。

(三)图像处理相关

图像处理用的是 Pillow 模块,官方网站上有手册 http://effbot.org/zone/pil-index.htm

  1. from PIL import Image
  2. im = Image.open("lenna.jpg") #打开图像
  3. box = (200, 0, 1720, 1080)
  4. im.crop(box) #按box的对角坐标裁剪区域
  5. im.transpose(Image.ROTATE_90) #逆时针旋转90度
  6. im.save('newFileName.png', "PNG") #保存新的图像文件newFileName.png
  7. color = i.getpixel((920,1400)) #获取某像素点的rgb值

脚本只用这几个方法,更详细的细节还是使用的时候去阅读文档。

(四)一些变量的说明

  1. box = (200, 0, 1720, 1080)

原图是1920x1080,裁剪后是1520x1080,对角(200,0), (1720,1080)

  1. POSITION = (920,1400)

右下角确定属性用的,通过 getpixel(POSITION) 方法获得的值有三种情况:

  1. attributes = {'Smile':(234,0,115,255),
  2. 'Pure' :(34,170,85,255),
  3. 'Cool' :(0,153,238,255)
  4. }

星星数和等级的映射表

  1. grade = {1:'N', 2:'N',
  2. 3:'R', 4:'R',
  3. 5:'SR', 6:'SR',
  4. 7:'UR', 8:'UR'
  5. }

(五)数星星

回去看上文相关的部分。

(六)另外

我再提供两张截图,如果读者愿意可以拿去测试代码,不一样的是,不需要旋转,裁剪区域不同。

完整的脚本代码 [image-processing.py] :

  1. #!/usr/bin/env python3.5
  2. # -*- coding:utf-8 -*-
  3.  
  4. from PIL import Image
  5. import glob, os
  6.  
  7. box = (200, 0, 1720, 1080) #裁剪区域
  8. POSITION = (920,1400) #属性坐标
  9.  
  10. #属性-颜色映射
  11. attributes = {'Smile':(234,0,115,255),
  12. 'Pure' :(34,170,85,255),
  13. 'Cool' :(0,153,238,255)
  14. }
  15. #星星数-等级映射
  16. grade = {1:'N', 2:'N',
  17. 3:'R', 4:'R',
  18. 5:'SR', 6:'SR',
  19. 7:'UR', 8:'UR'
  20. }
  21.  
  22. def image_processing(dirpath, dirname):
  23. os.chdir(dirpath + '/' + dirname)
  24. ## print(dirpath + dirname)
  25. s_cnt = p_cnt = c_cnt = 1
  26. images = glob.glob('*.png') #获取所有png文件
  27. for image in images:
  28. try:
  29. im = Image.open(image)
  30. new_im = im.crop(box).transpose(Image.ROTATE_90) #裁剪和旋转
  31. ## filename, ext = os.path.splitext(image)
  32. ## new_im.save(filename + "-new.png", "PNG")
  33. color = new_im.getpixel(POSITION) #属性坐标->颜色元组
  34. count = get_count_of_star(new_im) #判断星星的数量
  35. if color == attributes['Smile']: #确认颜色对应Smile属性
  36. new_im.save(dirname + "_Smile_{grade}_{count}-{number}.png".format(grade=grade[count],count=count,number=s_cnt), "PNG")
  37. s_cnt += 1
  38. elif color == attributes['Pure']:
  39. new_im.save(dirname + "_Pure_{grade}_{count}-{number}.png".format(grade=grade[count],count=count,number=p_cnt), "PNG")
  40. p_cnt += 1
  41. elif color == attributes['Cool']:
  42. new_im.save(dirname + "_Cool_{grade}_{count}-{number}.png".format(grade=grade[count],count=count,number=c_cnt), "PNG")
  43. c_cnt += 1
  44. else:
  45. new_im.save(dirname + "-new.png", "PNG")
  46.  
  47. except IOError:
  48. print('{}: io error!'.format(image))
  49.  
  50. print(dirname + ':finished.')
  51.  
  52. def get_count_of_star(image):
  53. count = 0
  54. positon_of_star = (33, 1090) #星星的初始位置,但星星是会运动的
  55. for i in range(0, 8): #[0,8) 星星最多有8个
  56. color = image.getpixel(positon_of_star) #星星有发亮吗?
  57. positon_of_star = (33, positon_of_star[1]+55) #坐标下移到下一个星星处
  58. if color[2] != 34: #只比较第三个元素
  59. count += 1 #不是暗的,说明星星是有效的
  60. return count
  61.  
  62. if __name__ == '__main__':
  63. for dirpath, dirnames, filenames in os.walk(os.getcwd()):
  64. for dirname in dirnames:
  65. ## path = dirpath + dirname
  66. image_processing(dirpath, dirname)

运行结果


运行前准备好,文件夹下放着待处理的截图:

脚本执行后得到我们想要的结果:

从上面的结果可以看出,脚本还是存在一些问题的:1,用于比对颜色属性(右下角)的值定的太死,有的像素点RGB值差了一点,结果就不能识别了,上文我提到过一次;2.对于不确定截图统一命名是名字-new导致覆盖问题。

我还专门做了动态图片:

Pythonner 的解决办法


我不是Pythonner,我不知道Pythonner is how thinking

不过我知道怎样就简单,就是什么都不做,不去 care 那些黑边,呵呵。

最后


下载 https://pypi.python.org/pypi/Pillow/

手册 http://effbot.org/imagingbook/

github https://github.com/python-pillow/Pillow

末了发一下桌面,听说下雨天 PyCharm 和 LoveLive! 更配哦!

不要再往下看了,妹子在上面(不明白不理解日本人发明了emoji,却迟迟不包含 LoveLive! 的手势)

[ller必读] LoveLive! 必备技能之 Python Pillow 自动处理截图的更多相关文章

  1. 「黑客必备技能」Python正则表达式详解

    说在前面 正则表达式是一个很强大的字符串处理工具,几乎任何关于字符串的操作都可以使用正则表达式来完成,作为一个爬虫工作者,每天和字符串打交道,正则表达式更是不可或缺的技能. 正则表达式在不同的语言中使 ...

  2. 详解linux运维工程师入门级必备技能

    详解linux运维工程师入门级必备技能 | 浏览:659 | 更新:2013-12-24 23:23 | 标签:linux it自动化运维就是要很方便的运用各种工具进行管理维护,有效的实施服务器保护 ...

  3. 自动化部署必备技能—部署yum仓库、定制rpm包

    部署yum仓库.定制rpm包 目录 第1章 扩展 - yum缓存 1.1 yum缓存使用步骤... 1 1.1.1 导言... 1 1.1.2 修改配置文件... 1 1.1.3 使用缓存... 1 ...

  4. 高级Linux运维工程师必备技能(扫盲篇)

    高级Linux运维工程师必备技能(扫盲篇) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在了解文件系统之前,我们要学习一下磁盘存储数据的方式,大家都知道文件从内存若要持久化存储的 ...

  5. 百度Hr分享,一个合格的数据工程师简历中必备技能?

    如果你是一名数据科学方面的求职者,你肯定想知道在简历上写些什么才能获得面试的机会:如果你想进入这个领域,你一定想知道具备哪些技术才能成为一名有竞争力的求职者. 在本文中,我们对Indeed中一千份数据 ...

  6. Android高工必备技能

    转载:http://www.jianshu.com/p/d791bbede02c Step 1. 玩转RxJava 使用RxJava处理异步极其方便,各种操作符可以对数据做流水线式操作,再加上与Ret ...

  7. 【转帖】系统软件工程师必备技能-进程内存的working set size(WSS)测量

    系统软件工程师必备技能-进程内存的working set size(WSS)测量 2018年12月28日 18:43:01 Linuxer_ 阅读数:145 https://blog.csdn.net ...

  8. SQL Server管理员必备技能之性能优化

    SQL Server管理员必备技能之性能优化 高文龙关注1人评论1171人阅读2017-09-22 08:27:41 SQL Server 作为企业必不可少的服务之一,所以对于管理员的日常运维是一个极 ...

  9. java高并发系列 - 第15天:JUC中的Semaphore,最简单的限流工具类,必备技能

    这是java高并发系列第15篇文章 Semaphore(信号量)为多线程协作提供了更为强大的控制方法,前面的文章中我们学了synchronized和重入锁ReentrantLock,这2种锁一次都只能 ...

随机推荐

  1. python--(协程 和 I/O多路复用)

    python--(协程 和 I/O多路复用) 一.协程 1. >>>单线程下实现并发, 最大化线程的效率, 检测 IO 并自动切换,程序级别的任务切换, 之前多进程多线程都是系统级别 ...

  2. Maven学习总结(7)——eclipse中使用Maven创建Web项目

    Maven学习总结(七)--eclipse中使用Maven创建Web项目 一.创建Web项目 1.1 选择建立Maven Project 选择File -> New ->Project,如 ...

  3. [cogs461] [网络流24题#10] 餐巾 [网络流,最小费用最大流]

    建图:从源点向第一层连边,第一层表示当天用掉多少餐巾,第二层表示当天需要多少餐巾,所以注意购买餐巾的边容量为无穷大,要从源点开始连向第二层的点,每天可能有剩余,在第一层内表示为流入第二天的节点.具体见 ...

  4. linux -- 视频尺寸-cif、2cif、dcif、D1、HD1、4D1

    1 CIF简介     CIF是常用的标准化图像格式(Common Intermediate Format).在H.323协议簇中,规定了视频采集设备的标准采集分辨率.CIF = 352×288像素 ...

  5. [bzoj3295][Cqoi2011]动态逆序对_主席树

    动态逆序对 bzoj-3295 Cqoi-2011 题目大意:题目链接. 注释:略. 想法:直接建立主席树. 由于是一个一个删除,所以我们先拿建立好的root[n]的权值线段树先把总逆序对求出来,接着 ...

  6. [bzoj2802][Poi2012]Warehouse Store_贪心_堆

    Warehouse Store bzoj-2802 Poi-2012 题目大意:一家商店的连续n天内,每一天会进货$a_i$个,有且只有一个客人回来买$b_i$个,问至多满足多少人. 注释:$1\le ...

  7. PHP array_diff_assoc()

    定义和用法 array_diff_assoc() 函数返回两个数组的差集数组.返回的数组的元素都取自被比较的数组(既第一个数组). 和 array_diff() 函数 不同,本函数要求键名和键值都进行 ...

  8. [PWA] Check Online Status by using the NavigatorOnLine API

    Even if you have your application fully cached, you couldn’t perform any external request without in ...

  9. Graphics简单汇总

    1.主页面布局文件 activity_main.xml(仅仅有2个button按钮) <?xml version="1.0" encoding="utf-8&quo ...

  10. luogu3358 最长k可重区间集问题 网络流

    题目大意: 关键词:最小费用最大流 不相交路径 如果两个线段重叠了,那我们则把一个线段放在下一层,另一个线段放在上一层.把流量为1的流看作一条线,一条线把位于同一层的线段(互不重叠)都串了起来.最多有 ...