【Python 项目】三维立体画 - 2

所需模块

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

代码

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

重复给定的平铺图像

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

def createTiledImage(tile, dims):
	# 利用提供的尺寸(dims)创建新的 Python 图像库(PIL)Image 对象
	img = Image.new('RGB', dims)
	W, H = dims
	w, h = tile.size
	# 确定列数
	cols = int(W/w) + 1 
	rows = int(H/h) + 1 # 确定中间图像所需的行数
	# paste the tiles into the image
	for i in range(rows):
		for j in range(cols):
			img.paste(tile, (j*w, i*h)) # 循环遍历行和列,并用平铺图像填充它们
	# output the image
	return img

通过乘积(jw, ih),确定平铺图像左上角的位置,这样它能对准行和列。完成后,该方法返回指定尺寸的 Image 对象,用输入图像 tile 平铺。

从随机圆创建平铺图像

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

def createRandomTile(dims):
	# 用 dim 给出的尺寸创建新的 Image 对象
	img = Image.new('RGB', dims)
	draw = ImageDraw.Draw(img)
	# 用 ImageDraw.Draw() 在该图像中画圆圈,用宽或高中较小值的 1/100 作为半径,画圆圈
	r = int(min(*dims)/100)
	# 设置要画的圆圈数为 1000
	n = 1000
	# draw random circles
	for i in range(n):
		# 算出每个圆圈的 x 和 y 坐标
		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)) # 在[0,255]的范围内随机选取 RGB 值,用选择颜色填充
		draw.ellipse((x-r, y-r, x+r, y+r), fill)
	return img

创建三维立体画

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

def createAutostereogram(dmap, tile):
	# 进行完整性检查,确保深度图和图像具有相同的尺寸
	if dmap.mode is not 'L':
		dmap = dmap.convert('L')
	# 如果用户没有提供平铺图像,就创建随机圆圈平铺图像
	if not tile:
		tile = createRandomTile((100, 100))
	# 创建一张平铺好的图像,符合提供的深度图的大小
	img = createTiledImage(tile, dmap.size)
	# 生成这张平铺好的图像的副本
	sImg = img.copy()
	# 调用 Image.load()方法,将图像数据加载到内存中。该方法允许用形如[i, j]的二维数组来访问图像像素
	pixD = dmap.load()
	pixS = sImg.load()
	# 将图像的尺寸保存为行数和列数,将图像看成单个像素构成的网格
	cols, rows = sImg.size
	for 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 image
	return sImg

三维立体画创建算法的核心在于,根据从深度图中收集的信息,移动平铺图像中像素的方式。要做到这一点,遍历平铺图像,处理每一个像素。

在:

xshift = pixD[i, j]/10

根据深度图 pixD 中的相关像素,查找偏移的值。然后将这个深度值除以 10,因为这里用的是 8 位深度图,这意味着深度的范围是 0 到 255。如果除以 10,得到的深度值范围是 0 到 25。由于深度图输入图像的尺寸通常是几百像素,所以这些偏移值很合适。

在:

xpos = i - tile.size[0] + xshift

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

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

命令行选项

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

# create a parser
parser = 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 args
args = parser.parse_args()
# set the output file
outFile = 'as.png'
if args.outFile:
	outFile = args.outFile
# set tile
tileFile = False
if args.tileFile:
	tileFile = Image.open(args.tileFile)

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

Python是一种功能强大的编程语言,它可以使用许多库和工具来制作三维立体图。在本文中,我们将详细说明如何使用Matplotlib库和mpl_toolkits.mplot3d模块来创建三维立体图。 Matplotlib库提供了许多绘制图形的函数和工具。mpl_toolkits.mplot3d模块是Matplotlib库中的一个子模块,它提供了一种用于绘制三维图形的工具。要制作三维图形,需要使用这两个库和模块。 首先,需要导入这两个库和模块: ```python import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D ``` 然后,需要创建一个3D Axes对象,该对象将用于显示三维图形。以下是创建3D Axes对象的示例代码: ```python fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ``` 上面的代码将创建一个名为“fig”的新图形,然后创建一个名为“ax”的3D Axes对象,该对象位于新图形上的位置(1,1,1)。 现在,我们可以向3D Axes对象中添加数据并绘制三维图形了。以下是一个绘制三维正弦函数的示例代码: ```python x = np.linspace(-5, 5, 100) y = np.sin(x) z = np.zeros_like(x) ax.plot(x, y, z) ``` 上面的代码将在三维坐标系中绘制正弦函数。函数的x坐标值存储在x数组中,y坐标值存储在y数组中,而z坐标值全部设为零。使用ax.plot()函数将数据添加到3D Axes对象中,并在三维图形中绘制。 还有许多其他功能可以使用,例如添加标签、轴、网格等等,让图形更具可读性。 总之,使用Matplotlib库和mpl_toolkits.mplot3d模块可以轻松制作三维立体图。根据您的需求和数据类型,您可以选择不同的绘图类型和设置,以实现最佳效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

QuantumStack

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值