本项目生成的三维立体画设计为用“墙眼”方式观看。看到它们的最好方法,就是让眼睛聚焦在图像后面的点(如墙上)。有点神奇,一旦在这些图案中感知到某样东西,眼睛就会自动将它作为关注的焦点,如果三维图像已“锁定”,你很难对它视而不见的(如果你仍然无法看到图像,请看Gene Levin的文章“How to View Stereograms and Viewing Practice”[1],或许有帮助)。

图8-1 一张令人费解的图像,可能让你感到痛苦[2]

8.1 工作原理

三维立体画的工作原理是改变图像中图案之间的线性间距,从而产生深度的错觉。在观看三维立体画中的重复图案时,大脑会将间距解释为深度信息,如果有多个图案和不同的间距,尤其会这样。

8.1.1 感知三维立体画中的深度

如果你的眼睛汇聚在图像背后一个假想的点,大脑将左眼看到的一些点与右眼看到的另一些点匹配起来,你将会看到这些点位于图像之后的一个平面上。到该平面的感知距离取决于图案中的间距的数量。例如,图8-2展示了3行A。这些A每行间的距离相等,但它们的水平间距从上至下增加。

如果用“墙眼”的方式来看,图8-2中最上面一行应该出现在纸后面,中间行应该看起来像在第一行后面一点,底部一行应该出现在最远的位置。文本“floating text”应该看起来“浮在”这几行顶部。

为什么大脑将这些图案的间距解读为深度?通常情况下,如果看远处的物体,你的双眼协作,聚焦并汇聚在同一点,双眼向内转,直接指向目标点。但用“墙眼”方式观看三维立体画时,聚焦和汇聚发生在不同的位置。眼睛专注于三维立体画,但大脑将重复的模式看成来自同一个虚拟(虚构的)对象,眼睛汇聚在图像背后的一个点,如图8-3所示。解耦的聚焦和汇聚叠加在一起,让你在三维立体画中看到深度。

图8-2 线性间距和深度知觉

图8-3 在三维立体画中看到深度

三维立体画的感知深度取决于像素的水平间距。因为图8-2中的第一行具有最近的间隔,它出现在其他行的前面。然而,如果点的间距在图像中是变化的,大脑将认为每个点处于不同的深度,所以我们会看到一个虚拟的三维图像。

8.1.2 深度图

“深度图”是这样一幅图像:其中每个像素的值表示深度值,即从眼睛到该像素表示的对象部分的距离。深度图往往表现为一幅灰度图,亮的区域表示近的点,暗的区域表示远的点,如图8-4所示。

图8-4 深度图

注意,鲨鱼的鼻子是图像中最亮部分,似乎最接近你。朝向尾部的较暗区域看起来最远。

因为深度图表示从每个像素中心到眼睛的深度或距离,所以可以用它来获得与图像中像素位置相关联的深度值。我们知道,在图像中,水平偏移被认为是深度。所以,如果按照对应像素值深度值的比例,来偏移(图案)图像中的像素,就会对该像素产生与深度图一致的深度知觉。如果对所有像素这样做,最终就会将整个深度图编码到图像中,生成三维立体画。

深度图的每个像素存储了深度值,并且该值的分辨率取决于表示它的位数。因为本章采用常见的8位图像,深度值的范围是[0,255]。

顺便说一下,图8-4中的图像就是用于创建图8-1中的三维立体画的深度图。你很快就能学会自己如何做到这一点。

该项目的代码将遵循以下步骤:

1.读入深度图;

2.读入一幅平铺图像或创建一个“随机点”平铺图像;

3.通过重复平铺图像创建一幅新图像。该图像的尺寸与深度图一致;

4.对新图像中的每个像素,根据该像素相关联的深度值,将它按比例地向右移;

5.将三维立体画写入一个文件。

8.2 所需模块

本项目使用Pillow读取图片,访问它们的底层数据,创建和修改图像。

8.3 代码

为了从输入的深度图生成三维立体画,首先重复一幅给定的平铺图像,生成一幅中间图像。接下来,生成一幅充满随机点的平铺图像。然后进入生成三维立体画的核心代码,即利用所提供的深度图中的信息,移动输入的图像。要查看完整的项目,请直接跳到8.4节。

8.3.1 重复给定的平铺图像

我们从利用createTiledImage()方法开始,通过平铺一个图形文件,创建一幅新的图像。图像尺寸由dims元组指定,该元组形式为(width, height)。

# tile a graphics file to create an intermediate image of a set size
def createTiledImage(tile, dims):# create the new image
❶  img = Image.new('RGB', dims)W, H = dimsw, h = tile.size# calculate the number of tiles needed
❷  cols = int(W/w) + 1
❸  rows = int(H/h) + 1# paste the tiles into the imagefor i in range(rows):for j in range(cols):
❹      img.paste(tile, (j*w, i*h))# output the imagereturn img

在❶行,利用提供的尺寸(dims)创建新的Python图像库(PIL)Image对象。新图像的尺寸由元组dims给出,形式是(width, height)。接着,保存平铺图像和输出文件的宽度和高度。在❷行,确定列数,在❸行,确定中间图像所需的行数,方法是用最终图像的尺寸除以平铺图像的尺寸。除的结果每次加1,如果输出图像的尺寸不是正好是平铺图像的整数倍,这也能确保右边最后的平铺图像不会缺失。如果没有这种预防措施,图像的右边可能被切断。然后,在❹行,循环遍历行和列,并用平铺图像填充它们。通过乘积(j*w, i*h),确定平铺图像左上角的位置,这样它能对准行和列。完成后,该方法返回指定尺寸的Image对象,用输入图像tile平铺。

8.3.2 从随机圆创建平铺图像

如果用户不提供平铺图像,就利用createRandomTile()方法,用随机圆圈创建一张平铺图像。

# create an image tile filled with random circles
def createRandomTile(dims):# create image
❶  img = Image.new('RGB', dims)
❷  draw = ImageDraw.Draw(img)# set the radius of a random circle to 1% of# width or height, whichever is smaller
❸  r = int(min(*dims)/100)# number of circles
❹  n = 1000# draw random circlesfor i in range(n):# -r makes sure that the circles stay inside and aren't cut off# at the edges of the image so that they'll look better when tiled
❺    x, y = random.randint(0, dims[0]-r), random.randint(0, dims[1]-r)
❻    fill = (random.randint(0, 255), random.randint(0, 255),random.randint(0, 255))
❼    draw.ellipse((x-r, y-r, x+r, y+r), fill)return img

在❶行,用dim给出的尺寸创建新的Image对象。用ImageDraw.Draw() ❷在该图像中画圆圈,用宽或高中较小值的1/100作为半径,画圆圈❸(Python的*运算符将dim元组中的宽度和高度值解包,这样就能传入到min()方法中)。

在❹行,设置要画的圆圈数为1000。然后调用random.randint(),获得范围为[0, width-r]和[0, height-r]的两个随机整数,从而算出每个圆圈的x和y坐标❺。“-r”确保生成的圆圈保持在width×height的图像矩形内部。不带-r,画的圆圈可能就在图像边缘,这意味着它会被切掉一部分。如果平铺这样的图像来创建三维立体画,结果不会好看,因为两个平铺图像之间没有空间。

要生成一个随机圆圈,先画出轮廓,然后填充颜色。在❻行,在[0,255]的范围内随机选取RGB值,用选择颜色填充。最后,在❼行,用draw中的ellipse()方法绘制每个圆圈。该方法的第一个参数是圆的边界矩形,它由左上角和右下角指定,分别为(x-r, y-r)和(x+r, y+r),其中(x, y)是该圆的圆心,r是半径。

让我们在Python解释器中测试这种方法。

>>> import autos
>>> img = autos.createRandomTile((256, 256))
>>> img.save('out.png')
>>> exit()

图8-5展示了测试的输出。

图8-5 尝试运行createRandomTile()

正如你在图8-5中看到的,我们已经创建了随机点的平铺图像。可以使用它来创建的三维立体画。

8.3.3 创建三维立体画

现在,让我们创建一些三维立体画。createAutostereogram()方法完成了大部分工作,如下所示:

def createAutostereogram(dmap, tile):# convert the depth map to a single channel if needed
❶  if dmap.mode is not 'L':dmap = dmap.convert('L')# if no image is specified for a tile, create a random circles tile
❷  if not tile:tile = createRandomTile((100, 100))# create an image by tiling
❸  img = createTiledImage(tile, dmap.size)# create a shifted image using depth map values
❹  sImg = img.copy()# get access to image pixels by loading the Image object first
❺  pixD = dmap.load()pixS = sImg.load()# shift pixels horizontally based on depth map
❻  cols, rows = sImg.sizefor j in range(rows):for i in range(cols):
❼      xshift = pixD[i, j]/10
❽      xpos = i - tile.size[0] + xshift
❾      if xpos > 0 and xpos < cols:
❿        pixS[i, j] = pixS[xpos, j]# display the shifted imagereturn sImg

在❶行,进行完整性检查,确保深度图和图像具有相同的尺寸。在❷行,如果用户没有提供平铺图像,就创建随机圆圈平铺图像。在❸行,创建一张平铺好的图像,符合提供的深度图的大小。然后,在❹行生成这张平铺好的图像的副本。

在❺行,调用Image.load()方法,将图像数据加载到内存中。该方法允许用形如[i, j]的二维数组来访问图像像素。在❻行,将图像的尺寸保存为行数和列数,将图像看成单个像素构成的网格。

三维立体画创建算法的核心在于,根据从深度图中收集的信息,移动平铺图像中像素的方式。要做到这一点,遍历平铺图像,处理每一个像素。在❼行,根据深度图pixD中的相关像素,查找偏移的值。然后将这个深度值除以10,因为这里用的是8位深度图,这意味着深度的范围是0到255。如果除以10,得到的深度值范围是0到25。由于深度图输入图像的尺寸通常是几百像素,所以这些偏移值很合适(尝试改变除数,看看它如何影响最终图像)。

在❽行,计算像素的新x位置,用平铺图像填充三维立体画。每隔w个像素,像素的值不断重复,由公式ai = ai + w表示,其中的ai是在x轴下标i处的给定像素的颜色(因为考虑的是像素行,而不是列,所以忽略y方向)。

要创建深度感,就要让间隔(或重复的间距)与该像素的深度图值成正比。这样在最终的三维立体画图像中,每个像素和它前一次(周期地)出现相比,偏移了delta_i。这可以表示为bi=bi-w+δt

这里,bi表示最后的三维立体画图像中,下标i处给定像素的颜色值。这正是❽行所做的事。深度图值为0(黑色)的像素没有偏移,被视为背景。

在❿行,用偏移的值替换每个像素。在❾行,检查确保没有试图访问不在图像中的像素,因为偏移,在图像边缘可能发生这种情况。

8.3.4 命令行选项

现在,我们来看看该程序的main()方法,其中提供了一些命令行选项。

  # create a parserparser = argparse.ArgumentParser(description="Autosterograms...")# add expected arguments
❶  parser.add_argument('--depth', dest='dmFile', required=True)parser.add_argument('--tile', dest='tileFile', required=False)parser.add_argument('--out', dest='outFile', required=False)# parse argsargs = parser.parse_args()# set the output fileoutFile = 'as.png'if args.outFile:outFile = args.outFile# set tiletileFile = Falseif args.tileFile:tileFile = Image.open(args.tileFile)

在❶行,像以前的项目一样,利用argparse为程序定义了一些命令行选项。一个必需的参数是深度图文件,两个可选的参数是平铺图像文件名和输出文件名。如果未指定平铺图像,程序会生成随机圆圈平铺图像。如果未指定输出文件名,则三维立体画会输出到as.png文件。

8.4 完整代码

下面是完整的三维立体画程序。也可以从https://github.com/electronut/pp/blob/ master/autos/autos.py下载这段代码。

import sys, random, argparse
from PIL import Image, ImageDraw# create spacing/depth example
def createSpacingDepthExample():tiles = [Image.open('test/a.png'), Image.open('test/b.png'),Image.open('test/c.png')]img = Image.new('RGB', (600, 400), (0, 0, 0))spacing = [10, 20, 40]for j, tile in enumerate(tiles):for i in range(8):img.paste(tile, (10 + i*(100 + j*10), 10 + j*100))img.save('sdepth.png')# create an image filled with random circles
def createRandomTile(dims):# create imageimg = Image.new('RGB', dims)draw = ImageDraw.Draw(img)# set the radius of a random circle to 1% of# width or height, whichever is smallerr = int(min(*dims)/100)# number of circlesn = 1000# draw random circlesfor i in range(n):# -r makes sure that the circles stay inside and aren't cut off# at the edges of the image so that they'll look better when tiledx, y = random.randint(0, dims[0]-r), random.randint(0, dims[1]-r)fill = (random.randint(0, 255), random.randint(0, 255),random.randint(0, 255))draw.ellipse((x-r, y-r, x+r, y+r), fill)# return imagereturn img# tile a graphics file to create an intermediate image of a set size
def createTiledImage(tile, dims):# create the new imageimg = Image.new('RGB', dims)W, H = dimsw, h = tile.size# calculate the number of tiles neededcols = int(W/w) + 1rows = int(H/h) + 1# paste the tiles into the imagefor i in range(rows):for j in range(cols):img.paste(tile, (j*w, i*h))# output the imagereturn img# create a depth map for testing
def createDepthMap(dims):dmap = Image.new('L', dims)dmap.paste(10, (200, 25, 300, 125))dmap.paste(30, (200, 150, 300, 250))dmap.paste(20, (200, 275, 300, 375))return dmap# given a depth map image and an input image,
# create a new image with pixels shifted according to depth
def createDepthShiftedImage(dmap, img):# size checkassert dmap.size == img.size# create shifted image
sImg = img.copy()
# get pixel access
pixD = dmap.load()
pixS = sImg.load()
# shift pixels output based on depth map
cols, rows = sImg.size
for j in range(rows):for i in range(cols):xshift = pixD[i, j]/10xpos = i - 140 + xshiftif xpos > 0 and xpos < cols:pixS[i, j] = pixS[xpos, j]# return shifted imagereturn sImg# given a depth map (image) and an input image,
# create a new image with pixels shifted according to depth
def createAutostereogram(dmap, tile):# convert the depth map to a single channel if neededif dmap.mode is not 'L':dmap = dmap.convert('L')# if no image is specified for a tile, create a random circles tileif not tile:tile = createRandomTile((100, 100))# create an image by tilingimg = createTiledImage(tile, dmap.size)# create a shifted image using depth map valuessImg = img.copy()# get access to image pixels by loading the Image object firstpixD = dmap.load()pixS = sImg.load()# shift pixels horizontally based on depth mapcols, rows = sImg.sizefor j in range(rows):for i in range(cols):xshift = pixD[i, j]/10xpos = i - tile.size[0] + xshiftif xpos > 0 and xpos < cols:pixS[i, j] = pixS[xpos, j]# return shifted imagereturn sImg# main() function
def main():# use sys.argv if neededprint('creating autostereogram...')# create parserparser = argparse.ArgumentParser(description="Autosterograms...")# add expected argumentsparser.add_argument('--depth', dest='dmFile', required=True)parser.add_argument('--tile', dest='tileFile', required=False)parser.add_argument('--out', dest='outFile', required=False)# parse argsargs = parser.parse_args()# set the output fileoutFile = 'as.png'if args.outFile:outFile = args.outFile# set tiletileFile = Falseif args.tileFile:tileFile = Image.open(args.tileFile)# open depth mapdmImg = Image.open(args.dmFile)# create stereogramasImg = createAutostereogram(dmImg, tileFile)# write outputasImg.save(outFile)# call main
if __name__ == '__main__':main()

8.5 运行三维立体画生成程序

现在,我们用凳子(stool-depth.png)的深度图运行该程序。

$ python3 autos.py --depth data/stool-depth.png

图8-6左边展示了深度图,右边展示了生成的三维立体画。因为没有为平铺提供图像,这张三维立体画使用了随机生成的平铺图像。

图8-6 autos.py运行示例

现在,让我们给定一个平铺图像作为输入。像前面一样使用stool-depth.png深度图,但这一次,提供图像escher-tile.jpg[3]作为平铺图像。

$ python3 autos.py --depth data/stool-depth.png –tile data/escher-tile.jpg

图8-7展示了输出。

图8-7 使用平铺图像的autos.py运行示例

8.6 小结

在本项目中,我们学习了如何创建三维立体画。给定深度图的图像,我们现在可以创建随机点的三维立体画,或用提供的图像来平铺。


如果你想知道如何利用编程来理解和探索想法。那么你可以看看这本《Python极客项目编程》,这本书的项目假设你了解基本的Python语法和基本的编程概念,并假设你熟悉高中数学知识。我已经尽了最大的努力,详细解释了所有项目中需要的数学知识。

《Python极客项目编程》

《Python极客项目编程(异步图书出品)》([美],Mahesh,Venkitachalam)【摘要 书评 试读】- 京东图书​item.jd.com

本书包含了一组富有想象力的编程项目,它们将引导你用Python 来制作图像和音乐、模拟现实世界的现象,并与

Arduino 和树莓派这样的硬件进行交互。你将学习使用常见的Python 工具和库,如numpy、matplotlib 和pygame,

来完成以下工作:

● 利用参数方程和turtle模块生成万花尺图案;

● 通过模拟频率泛音在计算机上创作音乐;

● 将图形图像转换为ASCII文本图形;

● 编写一个三维立体画程序,生成隐藏在随机图案下的3D图像;

● 通过探索粒子系统、透明度和广告牌技术,利用OpenGL着色器制作逼真的动画;

● 利用来自CT和MRI扫描的数据实现3D可视化;

● 将计算机连接到Arduino编程,创建响应音乐的激光秀。

通过本书,你可以享受作为极客的真正乐趣!

作者通过一系列不简单的项目,向你展示如何用Python来解决各种实际问题。在学习这些项目时,你将探索Python编程语言的细微差别,并学习如何使用一些流行的Python库。但也许更重要的是,你将学习如何将问题分解成几个部分,开发一个算法来解决这个问题,然后从头用Python来实现一个解决方案。解决现实世界的问题可能很难,因为它们往往是开放式的,并且需要各个领域的专业知识。但Python提供了一些工具,协助解决问题。克服困难,寻找实际问题的解决方案,这是成为专家级程序员的旅途中最重要的环节。

让我们来看看有哪些练手项目?

第一部分:热身运动

第1章展示了如何解析iTunes播放列表文件,并从中收集有用的信息,如音轨长度和共同的音轨。在第2章中,我们使用参数方程及海龟作图法,绘制类似万花尺产生的那些曲线。

第1章 解析iTunes播放列表

第2章 万花尺

第二部分:模拟生命

这部分是用数学模型来模拟现象。在第3章中,我们将学习如何实现Conway游戏的生命游戏算法,产生动态的模式来创建其他模式,以模拟一种人工生命。第4章展示了如何用Karplus-Strong算法来创建逼真的弹拨音。然后,在第5章中,我们将学习如何实现类鸟群算法,模拟鸟类的聚集行为。

第3章 Conway生命游戏

第4章 用Karplus-Strong算法产生音乐泛音

第5章 类鸟群:仿真鸟群

第三部分:图像之乐

这部分介绍使用Python读取和操作2D图像。第6章展示了如何根据图像创建ASCII码艺术图。在第7章中,我们将进行照片拼接。在第8章中,我们将学习如何生成三维立体图,它让人产生3D图像的错觉。

第6章 ASCII文本图形

第7章 照片马赛克

第8章 三维立体画

第四部分:走进三维

这一部分的项目使用OpenGL的3D图形库。第9章介绍使用OpenGL创建简单3D图形的基本知识。在第10章中,我们将创建粒子模拟的烟花喷泉,它用数学和OpenGL着色器来计算和渲染。在第11章中,我们将使用OpenGL着色器来实现立体光线投射算法,来渲染立体数据,该技术常用于医疗影像,如MRI和CT扫描。

第9章 理解OpenGL

第10章 粒子系统

第11章 体渲染

第五部分:玩转硬件

在最后一部分中,我们将用Python来探索Arduino微控制器和树莓派。在第12章中,我们将利用Arduino,通过一个简单电路读取并标绘传感器数据。在第13章中,我们将利用Python和Arduino来控制两个旋转镜和激光器,生成响应声音的激光秀。在第14章中,我们将使用树莓派打造一个基于网络的气象监测系统。

第12章 Arduino简介

第13章 激光音乐秀

第14章 基于树莓派的天气监控器

Python 的练手项目:用Python创建一张三维立体画相关推荐

  1. python练手经典100例-Python 的练手项目有哪些值得推荐?

    首先两点建议:最好不要写太应用的程序练手,如果你发现你写程序的大部分时间都在查库手册(或者类似的事情),那就是大家所说的"搬砖"了:要思考什么更像是知识,什么只是经验,还是那句老话 ...

  2. 熬夜整理出了70个清华大佬都在用的Python经典练手项目【附源码】

    我们都知道,不管学习那门语言最终都要做出实际的东西来,而对于编程而言,这个实际的东西当然就是项目啦,不用我多说大家都知道学编程语言做项目的重要性. 于是,小编熬了几个通宵,终于整理出了70个清华大佬都 ...

  3. Python体系练手项目200例(附源代码),练完可显著提升python水平(鲲鹏编程--Python教育新物种)

    个人公众号 yk 坤帝 后台回复 练手项目 获取全部源代码 1.十转二 2.十转八 3 十转十六 4.字符串转字节 5.转为字符串 6.十转 ASCII 7.ASCII 转十 8.转为字典 9.转为浮 ...

  4. python新手项目-Python 的练手项目有哪些值得推荐?

    其实初学者大多和题主类似都会经历这样一个阶段,当一门语言基础语法学完,之后刷了不少题,接下来就开始了一段迷茫期,不知道能用已经学到的东西做些什么即便有项目也无从下手,而且不清楚该如何去提高技术水平. ...

  5. 70个Python实用练手项目(附源码)

    不管学习哪门语言都要做出实际的东西来,这个实际的东西就是项目. 恶霸整理了 70 个 Python 实战项目,都有完整且详细的教程,你可以从中选择自己想做的项目进行参考学习练手,你也可以从中寻找灵感去 ...

  6. 快乐学习!Python趣味练手项目:PyQ5模块实现通过中文名字识别性别

    嗨~我是小鱼,一个不太厉害混迹编程界的老学姐 今天分享一个超级厉害的模块PyQ5,学过编程的都了解过这个小工具吧?不仅可以生成艺术签名还可以让电脑自己哼唱歌曲.今天我们利用这个pyq5这个小工具和贝叶 ...

  7. 100个Python实战练手项目(附源码+素材),学习必备

    前言: 不管学习哪门语言都希望能做出实际的东西来,这个实际的东西当然就是项目啦,不用多说大家都知道学编程语言一定要做项目才行. 这里整理了最新32个Python实战项目列表,都有完整且详细的视频教程和 ...

  8. 吐血整理Python体系练手项目500例(附源代码),练完可显著提升python水平

    1.有一个jsonline格式的文件file.txt大小约为10K 2.补充缺失的代码 3.输入日期, 判断这一天是这一年的第几天? 4.打乱一个排好序的list对象alist? 5.现有字典 d= ...

  9. 吐血整理Python体系练手项目500例(附源代码),练完可就业

    1.有一个jsonline格式的文件file.txt大小约为10K 2.补充缺失的代码 3.输入日期, 判断这一天是这一年的第几天? 4.打乱一个排好序的list对象alist? 5.现有字典 d= ...

最新文章

  1. Alpha冲刺 - (5/10)
  2. vmare安装ghostwin7
  3. FCKeditor 在ASP.Net 中的使用说明
  4. golang var 初始化时机_你应该知道的 Go 调度器知识:Go 核心原理 — 协程调度时机...
  5. 神经网络的sigmoid激活函数是一种平方映射
  6. 58金融产品经理董宁:互金产品设计21问
  7. PHP-Codeigniter:实习笔记1
  8. mysql 中间表的好处_Mysql中使用中间表提高统计查询速度
  9. 常见问题及解决方案(前端篇)
  10. YASnippet - emacs 的代码片段管理工具
  11. Java动态加载类(对反射的基本理解)
  12. java中关于线程的状态属性_深入理解Java多线程与并发框(第①篇)——线程的状态...
  13. 【论文写作】网上选课系统中模块设计如何写
  14. img标签显示不出图片_前端开发,原生 JS 实现最简单的图片懒加载
  15. Windows Server 2008通过计划任务定时执行bat文件
  16. 理解insert all/insert first的使用
  17. Storm目录树、任务提交、消息容错、通信机制
  18. dis 密集光流_密集光流估计的自监督注意力机制
  19. 物联网通信技术 机械工业 课后习题总结
  20. html banner图片滚动,jQuery实现的网站banner图片无缝轮播效果完整实例

热门文章

  1. 在下列html中 哪个可以添加背景颜色,在下列的 HTML 中,哪个可以添加背景颜色()...
  2. Js模块化规范(commonJs、Es6模块化)
  3. Postgresql vacuum freeze相关参数
  4. PyAutoGUI 自动控制鼠标和键盘操作(三个小案例)
  5. 可视化生成css_使用CSS进行数据可视化:图形,图表等
  6. 如何在Excel里安装excel插件?
  7. hdu 5264 pog loves szh I
  8. IOS开发常用数学函数
  9. ACL2021--ChineseBert论文分享
  10. 原来淘宝会屏蔽最低价格的!大家按价格排序出来的,其实不是最低 手机淘宝搜索不显示最低价...