0%

电车惊魂

那是一个美好的一天的早晨,我怀着轻松的心情去上班。那天天气晴的恰到好处,被淡淡的云遮挡掉一部分的太阳光线让我觉得很舒服。

“又是美好的一天。”我心想。

我像往常一样走入电车,今天电车里人反常得很多,不对,不如说这段日子里面电车里人都反常得很多。座位几乎坐满了。

过了几站上来一个十五六岁的中学生。他走进来的时候时不时看看手表,我知道了他好像快要迟到了。没有地方坐下,他就站着,拉着电车中央的那根竖铁杆。

滴滴的警铃声响起,门关上,列车就启动。我马上感觉到加速度压在我身上,重力像是该换了方向。于是我看见那中学生一个趔趄,他站不稳了,马上用手抓住栏杆,另一只手里提着的包向后甩去。

加速完成了,他得到了一片刻的休息机会。他手扶着栏杆站稳,像是没力气没睡醒似的揉眼睛,这时我才注意到他的眼睛上重重的黑眼圈。

过了几站车外面开始风雨大作起来,本来阳光在建筑物的缝隙之间洒下来,有间隔地透过车窗玻璃进入我们的电车里面,我们的电车就像是穿梭在时空的隧道里面。现在乌云密布了,外面的乌云遮蔽太阳,外面的风吹得树都要朝侧面倒过去,风连树上的叶子也扯下来。

外面风雨大作起来,我们的电车里面也风雨飘摇。风把我们的电车吹得左摇右晃,开得慢的时候我觉得我们像是坐在船里飘在海上。车轮和轨道摩擦的啸叫与风雨的声音混合在一起很吵闹,把我的耳膜都向里压得难受,并且使我有了不祥的预感。

我们的车厢风雨飘摇起来,他内心好像也风雨大作了。他用手紧紧抓着竖杆,他手上的青筋暴起,脸上露出痛苦的神情,他咬牙切齿把牙龈整个地都露出来,他的脸上汗如雨下。他像是在和被挡在车外面进不来的风雨搏斗着,他一会被甩到左边,一会被甩到右边,他的两个脚快要拧起来了,他花了好一会把自己稳住。

我们一车厢人静静看他的表演。

突然他松开一只手捂住自己的胃部,他把面部的肌肉也要拧起来了,他似乎是胃痛到不能稳定的站立,于是他艰难地蹲下了,他蹲下的时候我看见一张卡片样的东西,从他的裤子口袋里面滚出来。

那张卡片滚到下一个车厢的连接处卡在地面的突起上停住了。

突然他像是想起了什么似的,他用一只手捂住耳朵,然后马上开始念咒语似的大声背诵古诗词“僵卧孤村不自哀,尚思为国戍轮台。夜阑卧听风吹雨,铁马冰河入梦来。僵卧孤村不自哀,尚思为国戍轮台。夜阑卧听风吹雨,铁马冰河入梦来……”背得很大声。我知道这是一首什么风雨大作的古诗。

背完古诗他又“静摩擦力略大于滑动摩擦力,所以我的卡不会回来……”

我不知道他的咒语和当前情况有没有关系,不过事实上他的咒语没有缓解他的痛苦,他脸上的神情还是那么痛苦。

然后我们车厢中的有一个人扑哧的笑了,开始是掩口胡卢而笑。他的样子确实很好笑,我也想着。

笑声一个传染俩,马上变成了哄堂大笑,有的人笑他上学迟到,肯定是昨晚不好好睡觉打游戏;有的人笑他读书读傻了,只知道念古诗咒语了;有的人笑他弱不禁风,连列车的一点点加速度也把握不住;有的人笑他的头发那么长,肯定不好好学习;有的人笑他不带伞,要遭殃;还有两个带行李箱的情侣大学生,笑你们高中不准谈恋爱,笑你们八月中旬就开学,我们九月了赶到学校城市还有三两天玩耍的光景。

我呢?我也跟着他们笑,笑得上气不接下气,我伸出我的右手,一个大拇指指向老天爷,一个食指指向他,还有三四五指弯回来朝向自己。

我也一直这么笑着,上气不接下气,直到我的站点要到了,于是我收起笑容和东西站起来,在我离开座位的一瞬间,我就被巨大的加速度甩到了车厢后面,头重重地撞在后面车厢的竖杆上。

于是我残存的意识听到新的一轮哄堂大笑开始了,指向我。

这个问题的发现和解决是有将近一年了,当时我在开发一个背单词的一个小项目,但是我在想打包的时候出现问题了。

我想更换窗口的图标,就是windows下左上角的那个小图标,但是tkinter给的方法的参数却是一个文件名,这意味着我不能完美地把这个项目打包成一个单文件,而是需要把这个icon文件和打包好的exe放在一起,变成两个文件发布。

网上所给出的方法一般是先把这个ico文件打包进去,需要的时候在写到cache, 然后再让tkinter用这个文件名来导入。这个方法一看就极其不优雅,虽然性能也就这样了,但是这样的方法是我所不能接受的。

最后,我查看了ttkbootstrap的源码解决了问题。

我想,ttkbootstrap有一个自带的图标,是不管在哪个代码里面执行都会有这个图标,于是我想参考官方的做法。

我当初发现的ttkbootstrap的代码是在哪里我早就已经忘记了,但是我解决问题的思路仍清晰。

之前我看到ttkbootstrap的源码里面有一段base64,然后使用了这段base64来导入,并非网上的先写到cache, 这也符合我对一个成熟的项目的预期。

所以我贴上我解决的代码:

root = tk.Tk()
root.title("Xdict背单词")
photo = ttk.PhotoImage(master=root, data=myIcon.img)
root.iconphoto(True, photo)

这段代码中的data项就是一个base64字符串。

制作myIcon.py需要编写一个mkicon.py.

#!/bin/python3
import base64
with open("icon.py","a") as f:
    f.write("img='")
with open("bell.png","rb") as i:
    b64str = base64.b64encode(i.read())
    with open("icon.py","ab+") as f:
        f.write(b64str)
with open("icon.py","a") as f:
    f.write("'")

这段代码的意思就是读取目录下的bell.png的文件内容并把他转换为base64, 输出到myIcon.py, 这样pyinstaller也可以直接知道要调用。

最后要在main.py里面引入myIcon

写的不太清楚,若不能理解请通过文章“博客介绍”里面的联系方式联系我

我刚开始尝试linux系统的时候是一年前,那时候我装的是linux mint, 碰巧这个系统是基于ubuntu 20.04, 而这个系统出来的时候我的笔记本都没有出来,所以里面好多的问题,比如屏幕缩放的问题、视频硬解的问题,chromium鼠标滚动速度慢的问题、触控板不支持多点触控的问题……

好在我最终没有放弃,用到了现在,然而时间过去了一年,我也亲眼见证了linux系统的好多严重妨碍使用体验的小小bug被修复了,可喜可贺。

让我们一起见证linux变得越来越好!

-1. 关于选linux发行版的一个建议

建议如果选择LTS发行版用作个人linux电脑,则不要选择太老的,比如你像我一样,在2022年7月初装了linuxMint, 然而这个时候LinuxMint只有20.x版,Ubuntu的22.04已经出了,LinuxMint开发有一定的时间延迟,但是我的电脑是2020年的款,所以我阴差阳错的装上了2年前、我的电脑出生之前的distrobution, 所以导致了很多的驱动、软件等问题

建议选择新一点的,最好滚动更新,因为linux作为PC是个还在进步的系统,直接装上大概率是不如Windows的完美体验的,总有点小毛病,比如视频硬解、比如Firefox的触控板和触摸屏支持。过了一段时间这些bug可能会一个一个修复,但是你的发行版是LTS就收不到更新了。好像现在python3.11都出了但是ubuntu 20.04还是最高支持到3.8

1. linux firefox支持触控板和触屏平滑滚动

linux的firefox默认是不支持触控板的平和滚动的,所以滚动起来就是模拟鼠标,然后是一顿一顿的,卡顿不跟手。还有一个问题是他不支持平滑缩放,对于笔记本电脑来说这是一个十分影响使用体验的问题。更离谱的是如果你的笔记本电脑支持触屏,那么你用手指在屏幕上滑动的时候火狐会认为你是用鼠标在屏幕滑动,于是选中了很多文字。好在现在我们可以通过更改配置来实现这两个功能。

引自网页:

使linux版firefox支持触屏操作

一共有两个地方需要修改:

第一个是在about:config中找到dom.w3c_touch_events.enabled项改为1(启用),默认为2(自动)。

第二个地方是修改文件/etc/security/pam_env.conf,在文件最后添加下面代码

MOZ_USE_XINPUT2 DEFAULT=1

修改完成后重启Firefox就可以使用触摸屏进行操作了。支持的操作有拖拽和双指缩放。

此外还发现鼠标滚轮滚送速度有些慢,会经常抽动。通过设置mousewheel.min_line_scroll_amount项为40,设置 general.smoothScroll项为true,设置 general.smoothScroll.pages项为false。

这样设置完重启firefox可能是不够的,可能还要重启系统

如果还不行就下载一个Wayland的桌面,然后你去Wayland里面看看开了没,开了以后应该X11也能用的

装完后好像还是不如windows丝滑

我这么弄能成功纯属瞎折腾瞎猫碰上死耗子

2. Firefox开启浏览器的视频硬件加速

linux作为一台个人电脑的一个很重要的功能是放视频,毕竟如果用CPU软解然后卡顿发热,那么是真的不可接受的

Firefox开启视频硬件加速的方法,你首先要在电脑上装好VA-API的显卡驱动,我只知道intel的。

然后要开启firefox里面的一些选项

推荐直接看这篇文章

https://zhuanlan.zhihu.com/p/268401890

能看懂Archwiki的推荐Archwiki

3. 总结

linux的一些小毛病是很难折腾的,说不定不是我的问题干脆就是软件bug, 比如我最近在KDE看到我的CPU总是有一个核心100%占用,但是我下载了gnome的系统monitor, 又用htop发现全正常。所以折腾很久是很正常的,但是linux是在进步的!我非常高兴看到进步。

生物学考复习

细胞呼吸模型图(自制)

光合作用模型图

光反应将光能转化为化学能,并释放氧气

碳反应将二氧化碳还原成糖

碳反应过程名称:1. CO2的固定;2. 三碳酸的还原;3. 五碳糖的再生

光反应的场所是类囊体膜;碳反应的场所是叶绿体的基粒

光合色素与提取与分离

胡萝卜素扩散快的原因是在层析液中的溶解度大

含量最多的是叶绿素a(色素带最宽)

叶绿素吸收红光和蓝紫光

类胡萝卜素吸收蓝紫光

观察胞质环流实验

取黑藻幼叶的原因是:1. 黑藻幼叶薄,1~2层细胞,易于观察;2. 叶绿体少,易观察

检验糖类、油脂、蛋白质的实验中的注意点

脂肪检测中使用的染液是苏丹III染液,使用的酒精溶液是50%的用来洗去染料

脂肪检测实验只能用作观察脂肪颗粒,溶液里面的脂肪是不能观察,因为这个是个染色,不是反应

三个实验中只有检测还原糖用的本尼迪特试剂需要加热80摄氏度到100摄氏度水浴

检测蛋白质时候用的双缩脲试剂是先加A再加B, A加的多,要加2mL, B加的少只有5滴

有关DNA的几个实验

活体肺炎链球菌转化实验(格里菲斯):必修二P49 与 体外肺炎链球菌转化实验(艾弗里)(仍存疑)

S菌和P菌的对比

性质 S菌 P菌
菌落表面 光滑 粗糙
致病性 致病 不致病
荚膜 有 无

活体肺炎链球菌转化实验发现了转化因子的存在并且猜想是DNA,因为加热杀死的S型菌也可以使R型菌转化为S型菌
活体肺炎链球菌转化实验不能证明DNA是噬菌体的遗传物质

体外肺炎链球菌转化实验这个实验证明了:
DNA是转化因子(即遗传物质),赋予了生物的遗传特性

T2噬菌体侵染细菌实验:必修二P51

DNA注入到细菌中,蛋白质外壳留在外面,但是合成了完整的噬菌体

结论是:DNA是遗传物质,蛋白质不是遗传物质

在一部分没有DNA的病毒中,RNA是遗传物质:烟草花叶病毒重组实验:必修二P53

单独的RNA可以感染烟草,单独的蛋白质不能感染烟草,用RNA酶处理过的RNA也不能感染烟草

不同病毒株系的RNA和蛋白质混合之后繁殖的病毒类型是提供RNA的株系

实验证明了没有DNA只有RNA的生物的遗传物质是RNA

一些容易遗忘的细胞器功能

溶酶体来自高尔基体

动物的高尔基体的功能是蛋白质的加工、分类、包装、运输;植物的高尔基体的功能是合成果胶,与细胞壁的合成与修复有关

光面内质网的功能是运输蛋白质、合成脂质(磷脂、胆固醇和类固醇激素)、解毒

细胞的有丝分裂的周期

细胞的物质运输的物质举例

转运方式 实例 方向 载体 能量
简单扩散 O2、CO2 甘油、脂溶性维生素 高浓度→低浓度 F F
渗透 水、酒精 高浓度→低浓度 F F
易化扩散 葡萄糖进入红细胞、某些离子 高浓度→低浓度 T F
主动转运 葡萄糖、氨基酸、离子 低浓度→高浓度 T T
胞吞、胞吐 蛋白质 与浓度无关 F T

其他注意点

叶绿体纸层析法提取光合色素中使用的酒精是95%,且这是个溶剂不是层析液,层析液用的是石油醚或乙醚等

检测油脂里面用的是50%酒精来洗去多余的染料细胞膜中

胆固醇:位于脂双层中的疏水环境,有一个很小的亲水基团,与磷脂头部连接。
作用:双重调节:与磷脂脂肪酸链的相互作用,具有限制其运动、增加其有序性的作用;另一方面,也能将磷脂分子分隔开以增强其运动性。
作用与温度相关:环境温度较低时,胆固醇有助于保持细胞膜的柔韧性;细胞膜外侧磷脂分子中胆固醇的含量往往高于内侧,因此内侧的磷脂活动性比较弱。

密码子在mRNA上,启动子在DNA上,起始密码也在mRNA上

使种群基因频率发生变动的因素有:**突变、基因迁移、遗传漂变、非随机交配、自然选择**

错题整理

人类的卵细胞可以用肉眼直接看到 (T)

细胞中的遗传物质都是DNA (T)

病毒是非细胞生物,说明细胞不是生命活动的基本单位 (F)

在环境温度较低时,胆固醇有助于保持细胞膜的柔韧性 (T)

蓝细菌没有叶绿体,且可以进行光合作用 (T)

蓝细菌不存在有膜的细胞器,因此不能作为独立的生命单位存在(F)

液泡中的色素使得某些植物的花、叶、果实呈现不同的颜色(T)

细胞液能调节细胞渗透压平衡、酸碱平衡、离子平衡(T)

⭐液泡能合成大量水解酶,能吞噬衰老的细胞器(T)

分泌蛋白质(胰岛素)先在核糖体合成,在经过内质网加工,随后由高尔基体加工,并形成包裹着胰岛素的囊泡,转运至细胞膜,并与之融合。

母乳中含丰富的抗体(免疫球蛋白),可以增强婴儿的抵抗力。新生儿小肠上皮细胞通过消耗ATP可以直接吸收母乳中的抗体和半乳糖。这两种物质被吸收到血液中的方式分别是:胞吞、主动转运。

解答A

A、渗透作用的条件是半透膜和浓度差,则甲细胞和丙细胞与外界溶液存在浓度差,能发生渗造作用,A正确;

B、水分子既可以由细胞内到细胞外,也可以由细胞外到细胞内,因此水分子的运动方向不代表着它的扩散方向,B错误;

C、光学显微镜无法观察到水分子运输,C错误;

D、将甲、乙和丙细胞同时分别置于蒸馏水中,丙细胞由于开始时吸水膨胀,则放在蒸馏水中先破裂,D错误。

渗透作用的定义:水分子(和其他溶剂分子)通过膜的扩散现象。水分子从低浓度溶液一侧(水的浓度较高)跨膜扩散到高浓度溶液一侧(水的浓度低)
特点:从高浓度向低浓度一侧运输 不消耗细胞的能源 受外界物质浓度限制

胞吞体现了细胞膜控制物质进出的功能(F)因为胞吞没有经过细胞膜

丙酮酸先被氧化成乙醛再被还原为乳酸(F)

癌细胞细胞呼吸产生的CO2都来自线粒体(T)因为无氧呼吸如果是乳酸发酵则不产生CO2,所以所有产生的CO2全都来自线粒体的有氧呼吸

若呼吸产物中有水,则一定进行了需氧呼吸(T)

线粒体内膜上存在酶葡萄糖运载体等多种蛋白质(F)因为线粒体进行需氧呼吸的第二三阶段,葡萄糖不进入线粒体

丙酮酸产生二氧化碳的过程中可能生成[H],也可能消耗[H](T)因为可能是需氧呼吸产生还原氢,也可能是酒精发酵消耗[H]

无氧呼吸产生的乳酸再生成葡萄糖的过程需要消耗能量(T)

蛋白质可以通过核孔进入细胞核(T)

⭐着丝粒的分裂不是纺锤丝的牵引导致的,而是自发发生的,所以“纺锤丝的牵引导致着丝粒分裂”是(F)

⭐基因A与b最本质的差别是:碱基排列顺序不同(这题太鬼了吧)

活体肺炎链球菌转化实验不能证明DNA是噬菌体的遗传物质

高等植物细胞中每个染色体组中都含有常染色体和性染色体(F)因为雌雄同株的植物体内没有性染色体

地理学选考复习

太阳圈层

P33 地质年代简表

地质年代简表

地球气质年代温度变化书P38

地球产生生命的“**金锁链条件**”:液态水、适宜的温度和比较厚的大气层

地震波与圈层结构

纵波(S波)快,固液气都传播;横波(P波)速度慢,只能在固体传播

P波是primary wave,S波是secondary wave P波也可以说是压力波pressure wave,S波也可以说是剪力波shear wave

地震波的传播速度:

地壳中氧硅铝铁钙钠钾镁的含量依次最多

上层硅铝层,不连续,密度小;
下层硅镁层,连续,密度大。

水圈具有连续不规则的特点

风成地貌

风蚀作用包括吹蚀作用和磨蚀作用

冰川地貌

冰川侵蚀地貌

冰川侵蚀地貌包括冰斗、冰川槽谷(U型谷)、角峰、刃脊等

冰斗是三面岩壁陡峭,围椅状

冰川槽谷是在冰川流动时刨蚀作用形成的谷地,两壁陡立谷地开阔 举例:珠穆朗玛峰,西欧阿尔卑斯的勃朗峰

刃脊是仅有相邻的两个冰斗不断向内侵蚀,中间形成的一道较为尖锐的山脊

角峰是多个冰斗在同一个地区的多个冰斗一起向中间侵蚀中央剩下的高耸尖锐的岩体

峡湾是U型谷地在冰川消融,海平面上升之时被海水淹没形成的,北欧地区非常常见

冰川堆积地貌

常见的是冰碛湖、冰斗湖

冰碛物是冰川融化时裹挟的物质被放下,无分选性,大小悬殊,分选性很差

冰碛物不断堵塞河道、湖盆,水流不畅,不断汇集,形成冰斗湖、冰碛湖

大气垂直分层

书P73

对流层、平流层、高层大气的分界线分别是12km, 50km, 是在中纬度地区

洋流、海盐性质与海洋运动知识扩充:上升流

寒流与暖流对海洋与气候的影响

寒流减温减湿,暖流增温增湿

⭐在同纬度地带,寒流经过的海区盐度偏低,暖流经过的海区盐度偏高

海洋的温度随高度垂直变化是随深度变大,温度变低,深层海水随纬度的温度变化不大

海水盐度深层的地方35不到一点,随纬度较平均

密度是越深越大

上升流 百度百科:

上升流,又名涌升流,是从表层以下沿直线上升的洋流,是由表层流场产生水平辐散所造成。如风吹走表层水,由下面的水上升得以补充。因表层流场的水平辐散,使表层以下的海水铅直上升的流动。相反,因表层流场的水平辐合,使海水由海面铅直下降的流动,称为下降流。上升流和下降流合称为升降流,是海洋环流的重要组成部分。它和水平流动一起构成海洋(总)环流。

上升流通常发生在沿岸地区,是一种垂直向上逆向运动的洋流。由于受风力吹送,将表层海水推离海岸,致使海面略有下降,为达到水压的均衡,深层海水就在这里补偿上升,形成上升流。

海洋底部陆地与矿产资源

土壤分层

淋溶层是淋溶作用下物质向下迁移和损失,有机质含量低,色泽较淡

淀积层是土壤物质沉淀、积累的层次

从上到下:有机层、腐殖质层、淋溶层、淀积层、母质层、母岩层

地理与化学:天然气的开采利用

而我们日常生活中所说的“天然气”即狭义上的天然气含义,是指一种主要由甲烷组成的气态化石燃料,它主要存在于油田和天然气田,也有少量出于煤层。

天然气主要由气态低分子烃和非烃气体混合组成,埋藏在地底的深层地质构造之中。一部分天然气与原油储存在同一层,对于这一类的天然气,会随着原油一起被开采出来;同时也有单独存在天然气。目前,我国天然气的主要用途为燃料,可制造炭黑、化学药品以及液化石油气,由天然气生产的丙烷、丁烷是现代工业生产的重要原料。

天然气来源

天然气来源于地下多孔隙岩层中,包括油田气、气田气、煤层气、泥火山气和生物生成气等,也有少量出于煤层。原文

开采天然气的影响

煤、石油的开采,对环境造成了恶劣影响。

一、对土地的毁坏
采煤、采油,都要占用、浪费大量的土地资源。

采煤的矿渣、煤矸石,采油的钻台、设备,占地是自身设备的几十倍,对土地的毁坏是不可逆的。

二、地下水的破坏
造成地下水位降低,水质变差,污染。

三、地面下沉
山体滑坡、地震的可能性大大增加。地面建筑倒塌的危险大大增加。

四、能源问题
煤和石油都是不可再生能源。原文

必修一:自然地理常见数据

光速 $3\times10^5 km/s$, 所以一光年约等于$9.4607\times10^{12} km$

日地平均距离$1.5亿$千米

距离太阳最近的恒星与太阳之间的距离大约$4.2$光年

波长小于0.4是紫外光,大于0.76是红外光,两者之间是可见光

太阳黑子的周期$11$年

地壳的平均厚度是$17km$,大陆地壳的平均厚度是$39-41km$,高山高原地区最厚处可达$70km$,大洋地壳平均厚度$5-10km$

地幔的厚度约$2900km$

地球半径约$6400km$

一般把$2000-3000km$的高度当作大气圈的上界

生物圈渗透于三圈,厚度约$20km$,绝大部分集中于地面$+100m$ 水面$ -200m$

地球年龄约$46$亿年

对流层,低纬度地区高$17-18km$,中纬度地区高$10-12km$,高纬度地区高$8-9km$

平流层顶高度$50-55km$

臭氧层在$15-35km$的气层中,即平流层底

大气的电离层在$60-500km$的高空

世界海洋的平均盐度$35‰$

积累 笔记

粮食安全指的是粮食产品,水产品等等内容不算在内

气温年较差指的是一年中最热月和最冷月平均气温的差值

降水充足和光照充足基本上对立

钢琴AI扒谱,软件安装与体验

简介

这个软件是一个github上开源的AI扒谱软件,效果极端优秀,可以把任何力度、节奏等等的扒到位。

github地址https://kgithub.com/qiuqiangkong/piano_transcription_inference

这个软件是只能扒成midi, 也就是一个通用的音乐格式,但是这个midi是不会有任何谱面记号的,也正因为如此,midi可以做到很好的自由度和还原度。

musescore软件可以直接打开midi。

因为这个原因,所以如果你直接用musescore软件打开的话,虽然谱面的音符你是直接可以看到了,但是midi原本的还原度也丧失了很多,听起来怪怪的,而且谱面是很差劲的,很乱的。所以尽量安装一个其他的软件来读取midi文件。

虽然不能直接制作成谱子,但是可以参考音符的位置,然后再人工添加记号,省下了很多听音的时间。

archlinuxWiki上说,vlc在archlinux官方源里面没有支持midi, however, vlc-git in AUR是支持的,或者你也可以安装vlc-plugin-fluidsynth-bin来使vlc支持。

就算支持了,midi也需要软音源来播放,可以理解为一个包括了很多乐器发出的声音的文件,然后midi就是乐谱,电脑就是演奏者,根据乐谱来实时演奏。

这个软音源,比较流行的有Fluid-soundfont.tar.gz,在archlinux community源里面,可以直接使用yay或者pacman安装。其他的linux distrobutions我暂时不清楚可不可以。

这个项目的要下载的东西不多的,不像stable-diffusion那样把我剩下了10多个GB的内存全部卡爆。

yay -S soundfont-fluid

安装好了以后要找到VLC的工具/偏好设置(在左下角点显示设置->全部)/输入、编解码器/音频编解码器/FluidSynth,把右边的SoundFont文件里面改为/usr/share/soundfonts/FluidR3_GM.sf2然后就可以播放了。

顺带一提,这个音源好像不是很好听,但是凑合着用吧。

「教程原视频」https://www.bilibili.com/video/BV1e5411E7vA/?p=2&vd_source=4663f9a4c778e1a074fa26b38bf7f76b

我几乎完全没有按照这个教程来。

亲自踩坑安装,和效果体验

在linux上应该会方便一点,因为我看了原视频,如果在windows上需要安装wget什么的

  1. 安装torch
pip install torch

这个命令敲好之后基本上如果你有nvidia的显卡的话应该会把cuda安装好。

如果慢的要记得换源,后面加-i再加清华源,可以自己去https://tuna.moe上查看教程。

  1. 把github上的项目克隆下来。
git clone https://github.com/qiuqiangkong/piano_transcription_inference

如果你网络不幸不行,可以在github前面加个k使用他的镜像站。

github都上不去,中国的开源环境真是没救了。

git clone https://kgithub.com/qiuqiangkong/piano_transcription_inference
  1. 运行项目
python3 example.py --audio_path='input.mp3' --output_midi_path='output.mid' --cuda

如果你没有nvidia显卡的话后面–cuda别往上加了。

这个项目如果有显卡的话,是很快的,歌都放不完就扒好了,然后显卡的要求也没什么,我的MX350在linux下,很快就扒好了

  1. 自动脚本

这个项目直接使用pip安装下来的有点奇怪,他没有example.py, 也没有__init__.py,所以不能直接运行,所以我使用克隆。
但是克隆的问题就是它不能在除了这个目录以外的地方运行,不然no such file。
所以我写了个自动的,可以少敲命令。

#!/bin/bash

ex_path='/media/xht/Data/github/piano_transcription_inference'
pwd1=$PWD

cd $ex_path

python3 example.py --audio_path="$pwd1/$1" --output_midi_path="$pwd1/$2" --cuda

自行修改ex_path

可能出现的问题

也许在python3 example.py ……的时候会出现No librosa.core attribute audio这样的错误提示,这样的提示大概说明了librosa的版本不兼容,所以要指定版本安装

pip install librosa==0.9.2

也许会提示什么no such file什么什么的error提示,那么这个时候你需要在运行example.py的时候当前目录PWD必须要在example.py那里,如果从其他的地方来运行的话,会报错。如果不在的花切换到那里。
对于这个问题,可以使用我之前提到过的脚本来运行。

README里面的Installation里面说要pip安装这个项目,实测不装,只是git clone也可以。

第一次运行的时候可能会大约200KB/s地下载一个160多MB的文件,这是正常的,等待一会就可以了。

英语单词笔记生成器

必应爬虫

写一个文本文件i.txt, 使得它的每一行都是一个要查的单词或者词组。

然后把这段代码执行

import requests
from bs4 import BeautifulSoup

url = "https://cn.bing.com/dict/search?q=%s"
user_agent = "Mozilla/5.0 (Windows NT 10.0; WOW64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.5666.197 Safari/537.36"
# word = "supply"

def search(word):
    # try:
    response = requests.get(url % word, {"user-agent":user_agent})
    soup = BeautifulSoup(response.text, "html.parser")
    wordH1 = soup.find_all("h1")[1].text
    音标 = soup.find_all("div", class_="hd_prUS b_primtxt") + soup.find_all("div", class_="hd_pr b_primtxt")
    print(wordH1)
    for each in 音标:
        print(each.text)
    ul = soup.find_all("ul")[2]
    text = str(ul)
    soup1 = BeautifulSoup(text, "html.parser")
    meaningLi = soup1.find_all("li")
    for each in meaningLi:
        print(each.text)
    try:
        forms = soup.find("div", class_="hd_if").text
        print(forms)
    except:
        pass
    # using = soup.find("div", class_="wd_div").get_text(separator=" ").replace(" ,", ",")
    # print(using)
#     list1 = using.split(".")
#    for i in range(len(list1)):
#        list1.insert(i + 1, "  ")
#    using1 = ".".join(list1)
#    list2 = using1.split("+")
#    for i in range(len(list2)):
#        if i != 0:
#            list2[i] = list2[i][2:]
#    using2 = "+".join(list2)



        
        

        

    print()
#     for each in using.contents:
#         #print(each.text)
#         for eacheach in each.contents:
#             print(eacheach.text)
    # except:
    #     pass
    
    
if __name__ == "__main__":
    while True:
        word = input()
        if word != "":
            search(word)


使用命令

python3 1.py < i.txt > o.txt

然后就生成了一份英语的单词笔记

像这个

bound
美 [baʊnd]
英 [baʊnd]
n.跳跃;蹦跳
adj.一定会;很可能会;受(法律、义务或情况)约束(必须做某事)
v.跳跃着跑;形成…的边界(或界限)
网络惊世狂花;范围;限制
第三人称单数:bounds  现在分词:bounding  过去式:bounded  
同义词 反义词 adj. unlikely, free adj. certain, sure, obliged, forced v. border, border on, be contiguous to, touch, be adjacent to n. jump, leap, spring, bounce, hop

restore
美 [rɪˈstɔr]
英 [rɪˈstɔː(r)]
v.恢复;修复;恢复(某种情况或感受);使复原
网络还原;重建;归还
第三人称单数:restores  现在分词:restoring  过去式:restored  
搭配 同义词 v.+n. restore confidence, restore order, restore system, restore service, restore reputation v. reinstate, re-establish, reestablish, bring back, return

你也可以用这个脚本来便捷地查词,不加参数直接执行就好了

计算尺的原理与制作

事情是这样的,我在b站看到了一个古董计算尺的视频,就想着自己能不能搞一把,但是奈何在网上逛了一圈没找到能用的图片,所以只好自己考功名一下他的原理然后写写代码自动生成。

本文是介绍简易计算尺的制作过程,目前只完成了乘除部分。

什么是计算尺

计算尺就是在没有电子计算工具的时代用来辅助计算的一种仪器。
详情可以在这个视频里面看到
【百元科技古董-01】被禁止带入考场的尺子与人类没有计算器之前的工程师帮手

计算尺的原理

计算尺的乘除部分使用的是对数原理,上个学期在数学书上看到的对数原理的应用终于在这里找到了铁证。

计算尺的基本原理是把其他的运算变成加减运算,所以才可以用尺子的平行移动来计算。

简单来说,$lg(x \cdot y) = lg(x) + lg(y)$, 所以,我们可以制作出两把一样的尺子,这两把尺子的每一个刻度长度都是相应数字的$log_{10}$值,且这两把尺子的左端刻度起点都是1,那么我们把上尺的1对准下尺的第一个乘数,然后找到上尺上的另一个乘数的刻度,再把这个刻度啮合的下尺刻度读出,就可以得到结果。

这个过程就是把两个乘数的$log_{10}$值相加,然后用这个$log$值再对应回原乘积

除法是乘法的逆运算,所以计算与原理也很简单。原理就是$lg(\dfrac x y) = lg(x) - lg(y)$.如果要计算除法,那么则需要把上尺的除数对准下尺的被除数刻度,然后读出上尺中的对准了下尺中的1刻度的刻度,这个刻度就是商数。

具体的用法也可以在刚刚我提到的b站视频里面看到。

计算尺的图像生成

svg: 可缩放矢量图形(Scalable Vector Graphics,SVG)基于 XML 标记语言,用于描述二维的矢量图形

考虑到svg作为纯文本(代码)的图像格式比较好生成,所以我就选用svg生成。

一张简单的svg图像的代码大概这样:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="2977.2px" height="4208.4px" viewBox="0 0 2977.2 4208.4"
 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" baseProfile="tiny">

<line x1="0" y1="0" x2="200" y2="200"
  style="stroke:rgb(255,0,0);stroke-width:2"/>

</svg>

使用python语言进行开发,不导入第三方库了因为要考功名很麻烦,我就用一点点功能,所以直接使用print的方法就好了。

import math as m

# svg 前缀
_svg = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="4208.4px" height="2977.2px" viewBox="0 0 2977.2 4208.4"
 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" baseProfile="tiny">
"""

#svg 后缀
svg_ = """
</svg>
"""

print(_svg)

#参数设置
rate = 2100
end_num = 500
xMove = -1340
yMove = 60


# 画上尺!!
for a in range(1, end_num + 1):
    # 根据对数原理计算刻度的位置
    lgi = m.log(a, 10) * rate
    # 划出有刻度数值的标识的较长的线和数字
    if ((a % 5 == 0 or a <= 10) and a <= end_num // 2) or (a % 10 == 0 and a > end_num // 2):
        textY = yMove + 16 if (a > end_num // 2 and a % 20 == 0) or (a <= end_num // 2 and a % 10 == 0) else yMove + 30
        print('<text x="%d" y="%d" fill="black" font-size="20">%d</text>' %(lgi + xMove, textY, a))
        print('<line x1="%d" y1="%d" x2="%d" y2="%d" style="stroke:black;stroke-width:1"/>' % (lgi + xMove, yMove, lgi + xMove, yMove + 80))
    # 划出短标识
    else:
        print('<line x1="%d" y1="%d" x2="%d" y2="%d" style="stroke:black;stroke-width:1"/>' % (lgi + xMove, yMove + 50, lgi + xMove, yMove + 80))
    
# 划出尺子的上下边缘
print('<line x1="%d" y1="%d" x2="%d" y2="%d" style="stroke:black;stroke-width:1"/>' % (m.log(1, 10) * rate + xMove, yMove, m.log(end_num, 10) * rate + xMove, yMove))
print('<line x1="%d" y1="%d" x2="%d" y2="%d" style="stroke:black;stroke-width:1"/>' % (m.log(1, 10) * rate + xMove, yMove + 80, m.log(end_num, 10) * rate + xMove, yMove + 80))
# 画上尺结束

yMove += 160


# 画下尺!!
for a in range(1, end_num + 1):
    # 根据对数原理计算刻度的位置
    lgi = m.log(a, 10) * rate
    # 划出有刻度数值的标识的较长的线和数字
    if ((a % 5 == 0 or a <= 10) and a <= end_num // 2) or (a % 10 == 0 and a > end_num // 2):
        textY = yMove + 64 if (a > end_num // 2 and a % 20 == 0) or (a <= end_num // 2 and a % 10 == 0) else yMove + 78 
        print('<text x="%d" y="%d" fill="black" font-size="20">%d</text>' %(lgi + xMove, textY, a))
        print('<line x1="%d" y1="%d" x2="%d" y2="%d" style="stroke:black;stroke-width:1"/>' % (lgi + xMove, yMove, lgi + xMove, yMove + 80))
    # 划出短标识
    else:
        print('<line x1="%d" y1="%d" x2="%d" y2="%d" style="stroke:black;stroke-width:1"/>' % (lgi + xMove, yMove, lgi + xMove, yMove + 50))
    
# 划出尺子的上下边缘
print('<line x1="%d" y1="%d" x2="%d" y2="%d" style="stroke:black;stroke-width:1"/>' % (m.log(1, 10) * rate + xMove, yMove, m.log(end_num, 10) * rate + xMove, yMove))
print('<line x1="%d" y1="%d" x2="%d" y2="%d" style="stroke:black;stroke-width:1"/>' % (m.log(1, 10) * rate + xMove, yMove + 80, m.log(end_num, 10) * rate + xMove, yMove + 80))

# 画下尺结束


print(svg_)

然后把这个svg文件打开做个微调就可以用来打印了😃

程序的使用

python3 calc_ruler.py > output.svg

你也可以通过调整注释:参数设置下面的那几行代码中的值来更改你想要的尺子的范围、大小、缩放等等。

最终效果

svg

计算尺的改进

因为1刻度里面的空隙很大(也即log函数的特性),所以我们可以将里面填满小刻度。

代码如下

import math as m

# svg 前缀
_svg = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="8000px" height="5656.85424949238019521351px" viewBox="0 0 8000 5656.85424949238019521351"
 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" baseProfile="tiny">
"""

#svg 后缀
svg_ = """
</svg>
"""

print(_svg)

#参数设置
rate = 2500
end_num = 500
small_end_num = 25
xMove = 0
yMove = 60


# 画上尺!!
# 划出整数刻度位置
for a in range(1, end_num + 1):
    # 根据对数原理计算刻度的位置
    lgi = m.log(a, 10) * rate
    # 划出有刻度数值的标识的较长的线和数字
    if ((a % 5 == 0 or a <= 10) and a <= end_num // 2) or (a % 10 == 0 and a > end_num // 2):
        textY = yMove + 16 if (a > end_num // 2 and a % 20 == 0) or (a <= end_num // 2 and a % 10 == 0) else yMove + 30
        print('<text x="%d" y="%d" fill="black" font-size="20">%d</text>' %(lgi + xMove, textY, a))
        print('<line x1="%d" y1="%d" x2="%d" y2="%d" style="stroke:black;stroke-width:1"/>' % (lgi + xMove, yMove, lgi + xMove, yMove + 80))
    # 划出短标识
    else:
        print('<line x1="%d" y1="%d" x2="%d" y2="%d" style="stroke:black;stroke-width:1"/>' % (lgi + xMove, yMove + 50, lgi + xMove, yMove + 80))
# 划出尺子的上下边缘
print('<line x1="%d" y1="%d" x2="%d" y2="%d" style="stroke:black;stroke-width:1"/>' % (m.log(1, 10) * rate + xMove, yMove, m.log(end_num, 10) * rate + xMove, yMove))
print('<line x1="%d" y1="%d" x2="%d" y2="%d" style="stroke:black;stroke-width:1"/>' % (m.log(1, 10) * rate + xMove, yMove + 80, m.log(end_num, 10) * rate + xMove, yMove + 80))

# 划出小数刻度位置
for a in range(10, small_end_num * 10 + 1):
    lgi = m.log(a / 10, 10) * rate
    print('<line x1="%d" y1="%d" x2="%d" y2="%d" style="stroke:black;stroke-width:1"/>' % (lgi + xMove, yMove + (30 if a % 5 == 0 else 40), lgi + xMove, yMove + 80))

# 画上尺结束

yMove += 160


# 画下尺!!
for a in range(1, end_num + 1):
    # 根据对数原理计算刻度的位置
    lgi = m.log(a, 10) * rate
    # 划出有刻度数值的标识的较长的线和数字
    if ((a % 5 == 0 or a <= 10) and a <= end_num // 2) or (a % 10 == 0 and a > end_num // 2):
        textY = yMove + 64 if (a > end_num // 2 and a % 20 == 0) or (a <= end_num // 2 and a % 10 == 0) else yMove + 78 
        print('<text x="%d" y="%d" fill="black" font-size="20">%d</text>' %(lgi + xMove, textY, a))
        print('<line x1="%d" y1="%d" x2="%d" y2="%d" style="stroke:black;stroke-width:1"/>' % (lgi + xMove, yMove, lgi + xMove, yMove + 80))
    # 划出短标识
    else:
        print('<line x1="%d" y1="%d" x2="%d" y2="%d" style="stroke:black;stroke-width:1"/>' % (lgi + xMove, yMove, lgi + xMove, yMove + 50))
    
# 划出尺子的上下边缘
print('<line x1="%d" y1="%d" x2="%d" y2="%d" style="stroke:black;stroke-width:1"/>' % (m.log(1, 10) * rate + xMove, yMove, m.log(end_num, 10) * rate + xMove, yMove))
print('<line x1="%d" y1="%d" x2="%d" y2="%d" style="stroke:black;stroke-width:1"/>' % (m.log(1, 10) * rate + xMove, yMove + 80, m.log(end_num, 10) * rate + xMove, yMove + 80))

# 划出小数刻度位置
for a in range(10, small_end_num * 10 + 1):
    lgi = m.log(a / 10, 10) * rate
    print('<line x1="%d" y1="%d" x2="%d" y2="%d" style="stroke:black;stroke-width:1"/>' % (lgi + xMove, yMove, lgi + xMove, yMove + (40 if a % 5 == 0 else 30)))
    
# 画下尺结束


print(svg_)

那么这就可以生成一张带有刻度的svg图像了。

eg1

然后使用inkscape软件微调,复制几份用来使用A4打印机打印,再裁纸。

print

其他的运算我以后可能也会做。

2023-06-06 小核桃

2023-06-07 更新

踩坑记录

  1. 之前的代码里面有bug, 上尺的刻度线画错了,整数厘米的地方和0.5厘米的地方没有区分开来,所以导致测量时候会令人困惑。

  2. 之前的代码里面,我输出的时候用的是%d,但是这里的刻度为了精确,应该使用双精度浮点型,也即double的%Lf来输出,然而%d只能用来输出整数,所以导致了踩坑。而且使用的格式化输出并不会导致代码更简洁。
    使用%d的后果就是后面的小数被四舍五入掉了,所以到后面接近500的刻度线的时候有些刻度会(精确的)叠在一起,我很早就发现了这个问题,但是直到现在我才发现这个问题的解决办法。
    这个踩坑给我一个教训,也就是输出格式化字符串的时候最好用f"string{var_name}"来输出,虽然这是一个很晚才支持的特性,但是这可以使代码更清晰和少犯错。

现在我把修改过的代码贴上来

import math as m

# svg 前缀
_svg = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="8000px" height="5656.85424949238019521351px" viewBox="0 0 8000 5656.85424949238019521351"
 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" baseProfile="tiny">
"""

#svg 后缀
svg_ = """
</svg>
"""

print(_svg)

#参数设置
rate = 2500
end_num = 500
small_end_num = 25
xMove = 0
yMove = 60


# 画上尺!!
# 划出整数刻度位置
for a in range(1, end_num + 1):
    # 根据对数原理计算刻度的位置
    lgi = m.log(a, 10) * rate
    # 划出有刻度数值的标识的较长的线和数字
    if ((a % 5 == 0 or a <= 10) and a <= end_num // 2) or (a % 10 == 0 and a > end_num // 2):
        textY = yMove + 16 if (a > end_num // 2 and a % 20 == 0) or (a <= end_num // 2 and a % 10 == 0) else yMove + 30
        print('<text x="%Lf" y="%Lf" fill="black" font-size="20">%d</text>' %(lgi + xMove, textY, a))
        print('<line x1="%Lf" y1="%Lf" x2="%Lf" y2="%Lf" style="stroke:black;stroke-width:1"/>' % (lgi + xMove, yMove, lgi + xMove, yMove + 80))
    # 划出短标识
    else:
        print('<line x1="%Lf" y1="%Lf" x2="%Lf" y2="%Lf" style="stroke:black;stroke-width:1"/>' % (lgi + xMove, yMove + 30, lgi + xMove, yMove + 80))
# 划出尺子的上下边缘
print('<line x1="%Lf" y1="%Lf" x2="%Lf" y2="%Lf" style="stroke:black;stroke-width:1"/>' % (m.log(1, 10) * rate + xMove, yMove, m.log(end_num, 10) * rate + xMove, yMove))
print('<line x1="%Lf" y1="%Lf" x2="%Lf" y2="%Lf" style="stroke:black;stroke-width:1"/>' % (m.log(1, 10) * rate + xMove, yMove + 80, m.log(end_num, 10) * rate + xMove, yMove + 80))

# 划出小数刻度位置
for a in range(10, small_end_num * 10 + 1):
    lgi = m.log(a / 10, 10) * rate
    print('<line x1="%Lf" y1="%Lf" x2="%Lf" y2="%Lf" style="stroke:black;stroke-width:1"/>' % (lgi + xMove, yMove + (40 if a % 5 == 0 else 50), lgi + xMove, yMove + 80))

# 画上尺结束

yMove += 160


# 画下尺!!
for a in range(1, end_num + 1):
    # 根据对数原理计算刻度的位置
    lgi = m.log(a, 10) * rate
    # 划出有刻度数值的标识的较长的线和数字
    if ((a % 5 == 0 or a <= 10) and a <= end_num // 2) or (a % 10 == 0 and a > end_num // 2):
        textY = yMove + 64 if (a > end_num // 2 and a % 20 == 0) or (a <= end_num // 2 and a % 10 == 0) else yMove + 78 
        print('<text x="%Lf" y="%Lf" fill="black" font-size="20">%d</text>' %(lgi + xMove, textY, a))
        print('<line x1="%Lf" y1="%Lf" x2="%Lf" y2="%Lf" style="stroke:black;stroke-width:1"/>' % (lgi + xMove, yMove, lgi + xMove, yMove + 80))
    # 划出短标识
    else:
        print('<line x1="%Lf" y1="%Lf" x2="%Lf" y2="%Lf" style="stroke:black;stroke-width:1"/>' % (lgi + xMove, yMove, lgi + xMove, yMove + 50))
    
# 划出尺子的上下边缘
print('<line x1="%Lf" y1="%Lf" x2="%Lf" y2="%Lf" style="stroke:black;stroke-width:1"/>' % (m.log(1, 10) * rate + xMove, yMove, m.log(end_num, 10) * rate + xMove, yMove))
print('<line x1="%Lf" y1="%Lf" x2="%Lf" y2="%Lf" style="stroke:black;stroke-width:1"/>' % (m.log(1, 10) * rate + xMove, yMove + 80, m.log(end_num, 10) * rate + xMove, yMove + 80))

# 划出小数刻度位置
for a in range(10, small_end_num * 10 + 1):
    lgi = m.log(a / 10, 10) * rate
    print('<line x1="%Lf" y1="%Lf" x2="%Lf" y2="%Lf" style="stroke:black;stroke-width:1"/>' % (lgi + xMove, yMove, lgi + xMove, yMove + (40 if a % 5 == 0 else 30)))
    
# 画下尺结束


print(svg_)

那么这就是新的代码,然后还有新的图片

eg11111
打印用的图片
SuperPrint