Python PIL library Image.fromarray()导致AttributeError:';元组';对象没有属性'__阵列接口x27;
我正在使用物理模拟器pybullet,并希望使用以下两行代码在我的模拟中保存来自“虚拟摄影机”的图像Python PIL library Image.fromarray()导致AttributeError:';元组';对象没有属性'__阵列接口x27;,python,image,ubuntu,python-imaging-library,Python,Image,Ubuntu,Python Imaging Library,我正在使用物理模拟器pybullet,并希望使用以下两行代码在我的模拟中保存来自“虚拟摄影机”的图像 camera1 = pybullet.getCameraImage(900,600) im1 = Image.fromarray(camera1[2]) 第一行使用pybullet的getCameraImage函数返回未处理的图像camera1[2]是RGBA格式的像素颜色列表,每种颜色的范围为[0..255] 第二行应该获取该数组并将其转换为图像,然后保存并查看 运行代码时,我收到以下错误消
camera1 = pybullet.getCameraImage(900,600)
im1 = Image.fromarray(camera1[2])
第一行使用pybullet的getCameraImage函数返回未处理的图像camera1[2]
是RGBA格式的像素颜色列表,每种颜色的范围为[0..255]
第二行应该获取该数组并将其转换为图像,然后保存并查看
运行代码时,我收到以下错误消息:
Traceback (most recent call last):
File "generate_dataset.py", line 43, in <module>
im1 = Image.fromarray(camera1[2], "RGBA")
File "/usr/lib/python3/dist-packages/PIL/Image.py", line 2140, in
fromarray
arr = obj.__array_interface__
AttributeError: 'tuple' object has no attribute '__array_interface__'
将最后一行更改为:im1=Image.fromarray(imarray.astype('uint8'))
导致:
Traceback (most recent call last):
File "generate_dataset.py", line 42, in <module>
im1 = Image.fromarray(imarray)
File "/usr/local/lib/python2.7/dist-packages/PIL/Image.py", line 2431, in fromarray
raise TypeError("Cannot handle this data type")
TypeError: Cannot handle this data type
Traceback (most recent call last):
File "generate_dataset.py", line 42, in <module>
im1 = Image.fromarray(imarray.astype('uint8'))
File "/usr/lib/python3/dist-packages/PIL/Image.py", line 2165, in fromarray
size = shape[1], shape[0]
IndexError: tuple index out of range
回溯(最近一次呼叫最后一次):
文件“generate_dataset.py”,第42行,在
im1=Image.fromarray(imarray.astype('uint8'))
fromarray中的文件“/usr/lib/python3/dist packages/PIL/Image.py”,第2165行
大小=形状[1],形状[0]
索引器错误:元组索引超出范围
额外信息,如果需要
Pybullet文档:
PIL文件:
我的完整代码:
import pybullet as p
import pybullet_data
import time
from PIL import Image
from random import *
import numpy as np
nExamples = 200
for n in range(0, nExamples):
print ("Running example " + str(n))
physicsClient = p.connect(p.DIRECT) #or p.GUI for graphical version
p.setAdditionalSearchPath(pybullet_data.getDataPath()) #optionally
p.setGravity(0,0,-10)
planeId = p.loadURDF("ground.urdf")
p.resetDebugVisualizerCamera( cameraDistance=1, cameraYaw=0, cameraPitch=-30, cameraTargetPosition=[0,0,0])
x1 = uniform(-0.03,0.03)
y1 = uniform(-0.03,0.03)
x2 = x1 + uniform(-0.03,0.03)
y2 = y1 + uniform(-0.03,0.03)
cubeStartPos = [0.0,0,0.025]
cubeStartPos1 = [x1,y1,0.075]
cubeStartPos2 = [x2,y2,0.125]
yaw0 = uniform(0,np.pi/2)
yaw1 = uniform(0,np.pi/2)
yaw2 = uniform(0,np.pi/2)
cubeStartOrientation0 = p.getQuaternionFromEuler([0,0,yaw0])
cubeStartOrientation1 = p.getQuaternionFromEuler([0,0,yaw1])
cubeStartOrientation2 = p.getQuaternionFromEuler([0,0,yaw2])
boxId = p.loadURDF("red_block.urdf",cubeStartPos, cubeStartOrientation0)
boxId1 = p.loadURDF("green_block.urdf",cubeStartPos1, cubeStartOrientation1)
boxId2 = p.loadURDF("blue_block.urdf",cubeStartPos2, cubeStartOrientation2)
#saving the initial image...
camera1 = p.getCameraImage(900,600)
imarray = np.asarray(camera1[2])
im1 = Image.fromarray(imarray.astype('uint8'))
for i in range (250):
p.stepSimulation()
time.sleep(1./20.)
camera2 = p.getCameraImage(900,600)
#saving the image after blocks movement --> if stable this image is equal to the initial...
im2 = Image.fromarray(camera2[2])
#Are the images different? (Is it unstable?) --> if yes then diff is large, otherwise, diff is negligible
diff = (camera2[2] - camera1[2]).sum()
print("DIFFERENCE =", diff)
if abs(diff) < 100000:
im1.save("images/stable/image_%d.png" % n)
else:
im1.save("images/unstable/image_%d.png" % n)
#cropping images
cropped = im1.crop((350,200,550,400))
cropped.save("images/cropped/image_%d.png" % n)
p.disconnect()
print ("Reached end of loop\n")
将pybullet作为p导入
导入PYU数据
导入时间
从PIL导入图像
从随机导入*
将numpy作为np导入
例如:200
对于范围内的n(0,示例):
打印(“运行示例”+str(n))
physicclient=p.connect(p.DIRECT)#或p.GUI用于图形版本
p、 setAdditionalSearchPath(pybullet_data.getDataPath())#可选
p、 设定重力(0,0,-10)
planeId=p.loadURDF(“ground.urdf”)
p、 ResetDebugVisualizationRCAMera(CameradInstance=1,cameraYaw=0,CameraPictch=-30,CameratTargetPosition=[0,0,0])
x1=均匀(-0.03,0.03)
y1=均匀(-0.03,0.03)
x2=x1+均匀(-0.03,0.03)
y2=y1+均匀(-0.03,0.03)
cubeStartPos=[0.0,0,0.025]
cubeStartPos1=[x1,y1,0.075]
cubeStartPos2=[x2,y2,0.125]
yaw0=均匀(0,np.pi/2)
yaw1=均匀(0,np.pi/2)
yaw2=均匀(0,np.pi/2)
cubeStartOrientation0=p.getQuaternionFromEuler([0,0,yaw0])
cubeStartOrientation1=p.getQuaternionFromEuler([0,0,yaw1])
cubeStartOrientation2=p.getQuaternionFromEuler([0,0,yaw2])
boxId=p.loadURDF(“red_block.urdf”,cubeStartPos,cubeStartOrientation0)
boxId1=p.loadURDF(“green_block.urdf”,cubeStartPos1,cubeStartOrientation1)
boxId2=p.loadURDF(“蓝色块,urdf”,立方星定位2,立方星定位2)
#正在保存初始图像。。。
camera1=p.getCameraImage(900600)
imarray=np.asarray(camera1[2])
im1=Image.fromarray(imarray.astype('uint8'))
对于范围(250)内的i:
p、 步骤模拟()
时间。睡眠(1/20)
camera2=p.getCameraImage(900600)
#块移动后保存图像-->如果此图像等于初始值。。。
im2=Image.fromarray(camera2[2])
#图像不同吗?(是否不稳定?-->如果是,则差异较大,否则差异可忽略不计
diff=(camera2[2]-camera1[2]).sum()
打印(“差异=”,差异)
如果abs(差值)<100000:
im1.保存(“images/stable/image\uu%d.png”%n)
其他:
im1.保存(“图像/不稳定/图像\uu%d.png”%n)
#裁剪图像
裁剪=im1.裁剪((350200550400))
剪切。保存(“图像/剪切/图像\u%d.png”%n)
p、 断开连接()
打印(“已到达循环的末尾\n”)
从您的描述中不清楚camera1[2]
是连续R、G、B、a值的平面列表,还是RGBA元组的列表。因此,我将向您展示如何阅读这两个选项
您的主要问题是,您的数据不包含宽度和高度信息,因此我们需要以某种方式提供这些信息。一种方法是将数据读入正确形状的3D Numpy数组。但我们也可以通过使用适当的图像方法直接在PIL中进行
在我的演示中,我使用Python循环来创建一些简单的RGBA数据
此脚本创建RGBA元组列表
from PIL import Image
maxval = 255
width, height = 400, 300
# Display size info
size = width * height
fmt = 'Width: {}, Height: {}, Pixels: {}, Bytes: {}'
print(fmt.format(width, height, size, size * 4))
# Make a 2D gradient that starts at black in the top left corner,
# with red & green increasing horizontally, blue increasing vertically.
# This would be much faster using Numpy instead of Python loops.
pixels = []
# Make all pixels fully opaque
alpha = maxval
for y in range(height):
blu = maxval * y // height
for x in range(width):
red = gre = maxval * x // width
# Make a single RGBA pixel as a tuple
pix = red, gre, blu, alpha
# And save it
pixels.append(pix)
# Show that the size of `pixels` is correct and show the first few pixels
print('Size:', len(pixels))
print(pixels[:8])
# Make a new image object. All pixels are set to black.
img = Image.new('RGBA', (width, height))
# Copy the pixel data to the Image
img.putdata(pixels)
img.show()
img.save('test1.png')
输出
Width: 400, Height: 300, Pixels: 120000, Bytes: 480000
Size: 120000
[(0, 0, 0, 255), (0, 0, 0, 255), (1, 1, 0, 255), (1, 1, 0, 255), (2, 2, 0, 255), (3, 3, 0, 255), (3, 3, 0, 255), (4, 4, 0, 255)]
Width: 400, Height: 300, Pixels: 120000, Bytes: 480000
Size: 480000
[0, 0, 0, 255, 0, 0, 0, 255, 1, 1, 0, 255, 1, 1, 0, 255, 2, 2, 0, 255, 3, 3, 0, 255, 3, 3, 0, 255, 4, 4, 0, 255]
test1.png
此脚本创建一个R、G、B、a值的平面列表。它使用Python3
bytes
对象,因此无法在Python2上正常工作
from PIL import Image
maxval = 255
width, height = 400, 300
# Display size info
size = width * height
fmt = 'Width: {}, Height: {}, Pixels: {}, Bytes: {}'
print(fmt.format(width, height, size, size * 4))
# Make a 2D gradient that starts at black in the top left corner,
# with red & green increasing horizontally, blue increasing vertically.
# This would be much faster using Numpy instead of Python loops.
rgba = []
# Make all pixels fully opaque
alpha = maxval
for y in range(height):
blu = maxval * y // height
for x in range(width):
red = gre = maxval * x // width
# Make a single RGBA pixel as a tuple
pix = red, gre, blu, alpha
# And save each of red, gre, blu, alpha to rgba.
# By using `.extend` we create a flat list
rgba.extend(pix)
# Show that the size of `rgba` is correct and show the first few values.
print('Size:', len(rgba))
print(rgba[:32])
# Convert the rgba list to bytes.
rgba = bytes(rgba)
# Make a new image object from the bytes
img = Image.frombytes('RGBA', (width, height), rgba)
img.show()
img.save('test2.png')
输出
Width: 400, Height: 300, Pixels: 120000, Bytes: 480000
Size: 120000
[(0, 0, 0, 255), (0, 0, 0, 255), (1, 1, 0, 255), (1, 1, 0, 255), (2, 2, 0, 255), (3, 3, 0, 255), (3, 3, 0, 255), (4, 4, 0, 255)]
Width: 400, Height: 300, Pixels: 120000, Bytes: 480000
Size: 480000
[0, 0, 0, 255, 0, 0, 0, 255, 1, 1, 0, 255, 1, 1, 0, 255, 2, 2, 0, 255, 3, 3, 0, 255, 3, 3, 0, 255, 4, 4, 0, 255]
文件“test2.png”与“test1.png”完全相同。您说过“
camera1[2]
是RGBA格式的像素颜色列表”(虽然从错误消息中可以看出,它实际上是一个元组,但在这里不会有什么区别)。但是它是一个整型值的平面列表,还是一个RGBA元组的嵌套列表?顺便说一句,看起来您同时使用了Python2和Python3。当您试图调试东西时,这可能会让人困惑。我建议您坚持使用Python3,除非您需要使用一些尚未移植到Python3的古老库。这就解决了它!将数组转换为字节,然后使用frombytes
方法(如第二个示例中所示),处理图像时不会出现错误。非常感谢你!