温馨提醒:本文有点长,5000+字数,可耐心阅读或收藏有空再看。写作花了很多时间,欢迎转发、点赞、留言,多多捧场,古柳也有动力持续创作
。对文章任何内容有疑问欢迎可视化群里交流。PS:堀未央奈,毕业快乐!
文章剩最后一节没写时,突然看到谁都没料到的乃木坂46成员宣布毕业,被击沉懵了,再也写不下去,很久缓过来后才写完,有了这么个插曲,记录一笔。
书接上文
上篇文章说到古柳不知何故陷入“个人可视化的至暗时刻”,挺长一段时间,没啥干劲,但期间依然发生了许多事,因而简单回顾了下:盘点这个月可视化的那些事。
文章最后放上了几张最近关于李子柒b站视频画面颜色的可视化图
,其实也是在这次实现中一点点找回了之前的状态,果然自己还是喜欢研究、复现作品,或许唯有如此古柳才能从糟糕的状态中“拯救自己”,人啊“都得一步一步救自己”
。
什么叫做救自己呢?就是忠于自己的感觉,认真做每一件事,不要烦,不要放弃,不要敷衍。哪怕写文章时标点符号弄清楚,不要有错别字——这就是我所谓的自己救自己。我们都得一步一步救自己。
——陈丹青
契机
使古柳这次下定决心开始动手实践颜色可视化的契机
,说起来或许过于简单。
某天刷推特时,看到这几张色彩鲜艳的照片,仿佛啪得一下很快
,无干劲的古柳被明媚的颜色冲击到,脑海中遂又一次响起“要不搞搞颜色可视化”的声音
,动心起念后开始研究与实践,并还算顺利地做出了几张效果图。
https://twitter.com/mitsuyuka_lp/status/1327915297257390080
埋下想复现种子的一席演讲
这里说是“又一次”,是因为这样的念头在过去曾有过很多次,但大概都因时机不成熟,便没了后文
,毕竟真的好好学了 D3.js
和前端基础知识还是近半年的事。若要问为何有此念头,那还要从很久以前看向帆老师的一席演讲说起。
链接:【一席】向帆:如果把每年的春晚都像蚊香一样卷起来的话,它就是这样的 - bilibili
链接:向帆:秘密的设计 - 一席
https://v.qq.com/x/cover/7qm4vff0bszr5m0/m0500kj8cmu.html
如果此前你没看过这个视频,或许此刻可以好好看看,其中尤为相关的是后半段春晚和全国美展获奖作品的内容
,这里专门剪辑出来方便观看。
视频里向帆老师用大家不曾有过的方式、以更宏观角度各种花式排列数据、进行可视化,令人叹为观止。惊艳之余,那时啥也不会的古柳也仿佛痴人说梦般在心中埋下了想实现类似效果的种子
。毕竟鲁迅曾说过“听君一席终觉浅,绝知此事要躬行”
。
如果你曾看过古柳以前的这两篇文章「图像检索(一):因缘际会与前瞻 - 20180506」、「伴随 P5.js 入坑创意编程 - 20190628」,便会发现其中都出现了向帆老师那次演讲。再看发布日期,此间岁月的念念不忘便不言自明
。
一晃三年
其实这次终于初步打通全部流程、作出几张颜色可视化效果图后,古柳才开始想自己到底最早是什么时候看到那个视频的
,一开始没翻历史文章,想着可能是2018年末吧,然后试着搜了下日记(正经人谁写日记
),没想到竟然是2017年11月的事,至今正好满三年,令人唏嘘
。
念念不忘,必有回响
,而古柳这次的回响竟然是在三年后。大家又是否有什么念念不忘的事,结果又如何了呢?
动手实践
说完那些因缘际会的事,将时间拉回到这次开始着手颜色可视化的时刻。
其实这次用到的数据
:也就是李子柒的所有B站视频及每个视频隔几秒钟抽帧出一幅画面,古柳在8月份时就完成了。上百个视频加上万张照片,大小超过40GB
,所以整个流程已经打通一半。
这回只需要搞清楚如何从一张照片里抽取主要颜色,然后批量化处理,再选择合适的方式进行可视化即可。
古柳这次可能就不开源代码了,但作为守武德的年轻人
,还是将每个步骤我是如何实现的简单讲下,点到为止,有能力的小伙伴其实足够复现,当然有任何疑问可群里交流。不过又想了想基于已抽取的颜色数据用 D3.js 进行可视化这一步后续倒是开源
。
五步通关
本次项目分为以下几步,用到了各种工具,搭配到一起才打通整个流程,大家也不一定完全按照古柳的方式实现,可相应选择自己顺手的技术进行替换,仅供参考:
- 选择感兴趣的、想要进行颜色可视化的对象,比如李子柒的所有视频;
- 爬取李子柒所有b站视频数据,并下载全部视频;
- 从每一个视频里隔几秒抽一帧画面,并存储在相应b站视频ID命名的文件夹下;
- 从每一帧画面里提取几种主要颜色,如
TOP5
颜色; - 用
D3.js
进行颜色可视化。
1. 选对象
这一步没啥好说的,任何能抽取出颜色的内容大概都可以
,可以挑自己感兴趣的UP主/电影/动画/纪录片等视频;也可以用自己以往拍摄的照片,这样就不用抽帧了。
这次选择李子柒的视频,一来是觉得她的视频虽然挺有争议,但毕竟在海外也有很多人喜欢,算是挺成功的文化输出;二来印象里她的视频画面都挺好看、意境唯美、有自己的风格,拿来可视化下或许是不错的选择。
2. 爬取b站数据,搭配 you-get 下载视频
李子柒在YouTube/微博/b站等很多平台都有更新视频,选择容易爬取的平台即可,比如b站。进到个人主页-投稿
栏目下,抓下包,就会发现是数据通过 API 返回
,无需自己解析页面、抽取数据,用最简单的爬虫,翻几页就能拿到所有视频数据。
李子柒 - b站个人主页
数据格式,以「芋头的一生,辣椒…是送的」这个视频为例,重要的属性大概有这些,其中每个视频有 aid 和 bvid
两个 id,bvid: BV1f54y1r7HV
是视频URL会带上的,如 https://www.bilibili.com/video/BV1f54y1r7HV
[{
aid: 842739336,
author: "李子柒",
bvid: "BV1f54y1r7HV",
comment: 5742,
created: 1604843617,
description: "小时候我爷爷教过一句让我很疑惑的顺口溜:“红薯芋头本姓张,煮的没有烧的香”…虽然到现在也想不明白为啥一定要姓“张”但一点也不妨碍我爱吃它!年初在前院大门口种了几排毛芋儿后门那多种了香芋,刚好也到了能下嘴的季节。芋儿鸡、烤芋儿、红糖芋圆蛋…你们呢?最喜欢怎么吃芋头啊?",
length: "19:59",
mid: 19577966,
pic: "//i1.hdslb.com/bfs/archive/4f65418c058899f40638a55e0cd13bef4bf93be1.jpg",
play: 2479512,
review: 0,
subtitle: "",
title: "芋头的一生,辣椒…是送的",
typeid: 214,
video_review: 37999,
},]
而 aid: 842739336
可用来下载视频,这里古柳搭配使用 you-get
命令行工具,其支持下载很多平台的视频/图像/音频。
和安装其他 Python 库一样简单:pip install you-get
,然后用下面的命令即可下载单个视频。更多用法见:you-get 中文说明
# 下载b站视频
you-get http://www.bilibili.com/video/av842739336
# --output-dir/-o 设置存储路径, --output-filename/-O 设置文件名: av842739336 => av842739336.mp4
you-get -o ./liziqi -O av842739336 http://www.bilibili.com/video/av842739336
批量下载可以通过将所有视频的 aid
都生成一句命令然后写到 shell
脚本里,然后 bash you-get-cmd.sh
运行脚本即可。
3. 用 ffmpeg 进行视频抽帧
视频抽帧或许大家之前没接触过,但其实也并不难,用 ffmpeg
同样一行命令搞定。Mac 下可直接通过 brew install ffmpeg
安装就行。
官网:https://ffmpeg.org/
原本古柳担心安装这类工具会不会有坑,专门提前搜了些文章,以防万一,没想到一帆风顺,没出问题。但保不齐大家自己安装时可能依旧有坑,所以最好有个心理准备
......
在正式开始抽帧前,古柳提前计算了下李子柒所有视频的累计总时长
,以便评估不同间隔秒数分别会抽出多少图片。
其实计算方式在8月28日这篇文章里有写到:收益3583万?我是如何快速统计「李子柒」YouTube频道视频累计播放量并计算收益的,只不过当时没透露是想做这个项目,也并不知道何时会打通后半流程,所以就先写了这篇有点标题党的文章,但其实背后是有原因的,草蛇灰线,伏脉千里
。
当时李子柒油管有116个视频,共50637秒,约14小时时长
,如果每秒抽1帧,就会有5万张图片。
链接:李子柒Liziqi - YouTube
# 116 个视频
$$('span.ytd-thumbnail-overlay-time-status-renderer').forEach(el=>console.log(el.innerHTML.trim()))
# 计算全部下一共多少秒
$$('span.ytd-thumbnail-overlay-time-status-renderer').reduce((sum, el)=>{
let item = el.innerHTML.trim()
let min = +item.split(':')[0]
let sec = +item.split(':')[1]
return sum + min * 60 + sec
}, 0)
# 50637s = 843.95 min = 14h
但抽太多内存会爆炸,且李子柒的视频画面不会快速变换,所以选择间隔大些,隔5秒抽1帧,就会有1万多张图片。直接用这里的命令即可对一个视频进行抽帧。
链接:使用ffmpeg从视频中截取图像帧(最简单实用的视频抽帧,一句命令)
# 抽帧,每5秒抽1帧
ffmpeg -i av842739336.mp4 -f image2 -vf fps=fps=1/5 image-%05d.png
同样通过 shell
脚本来批量抽帧,然后......就可以在电脑上煎鸡蛋了。
4. 图片颜色抽取
终于到后半流程了。
能抽取图片颜色的第三方库想来很多编程语言都有,但抽取后对颜色进行可视化的项目古柳却也想不起来太多(欢迎安利),可能唯一记得的就是 Shirely Wu
有做过,于是找了下 data sketches 上「九月旅行」主题的项目就是。后续可能会翻译这篇文章,所以这里挑要紧的、相关的说下。
首先介绍下,该项目是 Shirely Wu
对自己2012年5月至2016年8月,4年间13场旅行、4千张照片2万个颜色(每张抽取5种主要颜色)进行的可视化
,同一年的排列成一行,行内每场旅行用一个圆圈表示(径向图),圆圈内会展示本次旅行所拍摄照片的日期与颜色以及相关信息。
链接:http://sxywu.com/travel
文章中 Shirely Wu
写到颜色抽取用的 node.js
的第三方模块包 get-image-colors,并且为了加快抽取速度,会先用 gm 把照片缩小到8*8
大小。不过古柳这次偷个懒就没缩小,批量抽取上万张图片颜色,耗时大概在20min内,也还行。
这里是抽取一张照片颜色的代码,getColors()
默认会抽取5种主要颜色,colors
是 chroma.js 颜色对象组成的数组,需要转换成16进制颜色表示的数组。
const getColors = require("get-image-colors");
async function extractImageColor(imgPath){
let colors = await getColors(imgPath);
colors = colors.map((color) => color.hex());
return colors;
}
const imgPath = 'cnliziqi/bilibili-videos-20200807/av5491231av5491231-00001.png'
const colors = extractImageColor(imgPath);
接着挑一个视频看看抽出来的颜色效果如何,其实也看不出有啥规律,所以还是继续下一步用全量数据、从各种维度看看能否挖掘出什么好玩的。
注:其他关于如何安装 node.js
、npm
,如何初始化 Node.js
项目、如何安装 get-image-colors
、如何结合 fs
模块读取所有文件夹里的所有图片然后批量抽取,就不再展开了,其实也不难(逃),可自行解决或群里交流。
5. 颜色可视化
这部分内容可能会另写文章详细讲,并开源代码,所以此处择其要点讲下,有不清楚的地方可关注后续文章。
经过上一步的处理,有了一份如下格式的数据,含视频avid、该视频里所有抽帧图片的路径及其5种主要颜色
,因为有上万张图片,所以相应有5万多颜色数据点。至于每个视频的其他信息可结合第2步爬取的数据来查询。
[
{
"avid": "av753928375",
"imgColor": [
{
"img": "../my-media/cnliziqi/bilibili-videos-20200807/av753928375/av753928375-00001.png",
"colors": [
"#25312f",
"#bdcfdf",
"#708ba6",
"#ad2629",
"#826276"
]
},
},
]
https://github.com/sxywu/travel/blob/master/src/Trip.js
终于到最后一步颜色可视化,临门一脚古柳却不知道该怎么踢,颜色仿佛很熟悉但又很陌生,但从没想过该如何排列颜色,因而再好好看看 Shirely Wu
是怎么做的。
在代表每一场旅行的径向图里,按日期划分不同扇形区域,每一天拍的照片所涉及的颜色按照 Hue/色相
值(0-360)的不同而径向排列,并加上x/y力布局
以避免重叠。
HSB 又称 HSV,表示一种颜色模式:在HSB模式中,H(hues) 表示色相,S(saturation) 表示饱和度,B(brightness)表示亮度。色相(H)是色彩的基本属性,就是平常所说的颜色名称,如红色、黄色等,取0-360;饱和度(S)是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取0-100%;明度/亮度(B or V),取0-100%。
链接:https://github.com/sxywu/travel/blob/master/src/App.js
照猫画虎,先不用径向图,而是在x/y轴二维坐标系下进行展示。古柳先将上面的颜色数据打平变成一个仅包含5万多颜色的数组。
x轴用 Hue 值 区分,y轴固定在页面中间,然后加上x/y力布局
,看看效果:蛮意外绿色占比那么少,蓝色居然是最多的
,本以为画面里绿色自然植物应该会很多,不过本身只看过零星几个李子柒的视频,也说不上来准不准。
接着尝试其他设置,x轴用 Hue 值,y轴用 Saturation 值,不加力布局
。
x轴用 Hue 值,y轴用 Saturation 值,加x/y力布局
。
x轴用 Hue 值,y轴用 Saturation 值,加x/y力布局
。
小结
这些图都挺有趣的,都是古柳以前不曾有过的尝试。另外还可以结合视频发布日期、季节等不同维度进行布局,甚至其他能想到的角度都可以试试,看看会有什么发现。
由于本次并不完全是为了从李子柒的视频画面颜色中挖掘出什么内容,更多是为了打通爬取数据、下载视频、视频抽帧、颜色抽取、可视化整个流程
,所以最后出了几张图后,想到三年来念念不忘的颜色可视化终于有了个初步结果,就想先写篇文章记录下,更多可视化探索留到后面有时间再搞,到时候看看有没有值得分享的新发现。
以上就是本文内容,如果大家还想看到更多干货,欢迎【转发】、【点赞】、【在看】和【留言】,多多捧场,古柳也有持续创作的动力
,毕竟这惨淡的阅读量实在也是有点说服不了自己太频繁更新,还真不是因为懒。逃。