使用numpy和mencoder直接绘制到电影中
这段话本来是想作为对这个讨论帖的评论,但那个帖子已经关闭了,所以我就直接在这里说了。我最近在使用matplotlib、numpy和mencoder方面玩得很开心,效果也不错,正如大家所建议的那样。我现在使用的是Voki Codder的缓冲区到标准输入的解决方案,这个方法大大加快了整个过程。不过,我找不到关于命令中-format="bgra"部分的任何文档。这个意思是字节的顺序是从右到左,分别是蓝色、绿色、红色和透明度,对吧?那这些字节必须是uint32类型,还是其他什么类型?问题是我在绘制浮点数的颜色图,所以我想把它们转换成灰度图,但我得到了很多奇怪的图案,这让我觉得我可能做错了什么。我写了一个函数来把浮点数转换成uint32,并且在一个范围内进行转换。但是结果并不是我预期的那样,我是不是做了什么特别傻的事情?
def grayscale(x, min, max):
return np.uint32((x-min)/(max-min)*0xffffff)
1 个回答
5
我觉得你可能对 uint32
的意思有点搞混了。它其实是由四个 uint8
整数组成的。
如果你有浮点数的数据,想把它转换成灰度图像,你不需要把它缩放到完整的32位范围,而是应该缩放到8位范围,然后对红色、绿色和蓝色通道重复这个过程(然后可能还要加一个固定的透明度通道)。
你也可以选择不同的字节顺序。Y8
只是一个单一的8位灰度通道,而 Y16
是一个单一的16位灰度通道。(可以查看 mencoder -rawvideo format=help
的输出,虽然有点复杂,但会列出所有格式。)
为了说明如何用numpy把一个32位整数视作四个8位整数的通道:
import numpy as np
height, width = 20,20
# Make an array with 4 bands of uint8 integers
image = np.zeros((height, width, 4), dtype=np.uint8)
# Filling a single band (red)
b,g,r,a = image.T
r.fill(255)
# Fill the image with yellow and leave alpha alone
image[...,:3] = (255, 255, 0)
# Then when we want to view it as a single, 32-bit band:
image32bit = image.reshape(-1).view(np.uint32).reshape(height, width)
# (Note that this is a view. In other words, we could change "b" above
# and it would change "image32bit")
不过在你的情况下,你可能想做的更像这样:
import numpy as np
from videosink import VideoSink
height, width = 20,20
numframes = 1000
data = np.random.random((height, width, numframes))
# Rescale your data into 0-255, 8-bit integers
# (This could be done in-place if you need to conserve memory)
d ata_rescaled = 255.0 / (data.max() - data.min()) * (data - data.min())
data_rescaled = data_rescaled.astype(np.uint8)
# The key here is the "Y8" format. It's 8-bit grayscale.
video = VideoSink((height,width), "test", rate=20, byteorder="Y8")
# Iterate over last axis
for frame in data.T:
video.run(frame.T)
video.close()