我目前正在进行一个项目,以控制LED条纹,这是连接到一个Teensy 3.2板,这是连接到Windows PC。它在技术上是基于这个项目:OctoWS2811.html
还有一个用vvvv实现的项目:https://vvvv.org/contribution/realtime-led-control-with-teensy3.xoctows2811
到目前为止,两人都工作得很好。我要做的是将movie2serial程序(关于pjrc.com上的项目)移植到Python。
所以我发现了这个项目:py
它不是从盒子里出来的,但是经过一些修改,我就可以运行它了。下面是类的代码,它接收图像,将其转换为字节数组,并将其发送到串口:
import serial
import numpy as np
class Teensy:
def __init__(self, port='COM3', baudrate=115200, stripes=4, leds=180):
self.stripes = stripes
self.leds = leds
self.connected = True
try:
self.port = serial.Serial(port, baudrate)
except:
self.connected = False
def close(self):
if not self.connected:
return
self.black_out()
self.port.close()
def send(self, image):
data = list(self.image2data(image))
data.insert(0, 0x00)
data.insert(0, 0x00)
data.insert(0, ord('*'))
if not self.connected:
return
self.port.write(''.join(chr(b) for b in data).encode())
def black_out(self):
self.send(np.zeros((self.leds,self.stripes,3), np.uint8))
def image2data(self, image):
buffer = np.zeros((8*self.leds*3), np.uint8)
byte_count = 0
order = [1,2,0]
for led in range(self.leds):
for channel in range(3):
for bit in range(8):
bits_out = 0
for pin in range(self.stripes):
if 0x80 >> bit & image[led,pin,order[channel]]:
bits_out |= 1 << pin
buffer[byte_count] = bits_out
byte_count += 1
return buffer它正在工作,但速度很慢(在我的计算机上是13 FPS )。
为了解释代码:我用cv2创建了一个简单的动画,并将图像(4x180个像素的numpy ndarray,因为我有4个LED条纹,每个带180个LED)发送到Teensy实例的发送方法。发送方法将图像发送到image2data方法,将图像转换为字节数组,在开头放置几个字节,并将整个过程发送给Teensy。
在这个代码中有两个瓶颈:
但更重要的是:
代码运行速度要快6-7倍(~ 80 FPS)。顺便说一句,orderchannel用于将颜色从BGR转换为GRB。
长话短说:从图像阵列读取颜色非常缓慢。如何在方法image2data中加快图像数组到字节数组的转换?
当你谈到这一点的时候,谢谢你的耐心:-)我很抱歉这么长的职位,但这是一个复杂的项目,不容易向我解释。我非常感谢你的帮助,也许其他人也能从中受益。
谢谢你,艾尔
发布于 2019-02-23 03:25:20
通过将order[channel]提升到内环之外(通过将channel_index = order[channel]保存在order上),第二个热点就可以得到改善。
if 0x80 >> bit & image[led,pin,channel_index]:这将是一个小小的进步。它还看起来,提升0x80 >> bit的水平,可以节省8次冗余计算。把它保存为mask,然后你就可以
if mask & image[led,pin,channel_index]:加起来,这些可能值几个FPS。
但是,看看您的代码,这些循环嵌套的方式看上去是错误的。对于180 x 4 RGB LED,我希望您需要发送180 x 4×3字节到Teensy。但是代码正在发送3x180x8,这两个内部循环是否有可能需要倒转呢?
发布于 2019-02-25 16:36:26
谢谢你的回答和改进。稍后我将实现它们,但我想它们不会加快到所需的60个FPS。
代码是发送3x180x8,因为这是板子。LED用以太网电缆连接到板上,以太网电缆有8个引脚,所有8个引脚都需要处理,否则条纹显示出奇怪的结果。另一方面,在以后的配置中,我需要4条以上的数据,所以目前我不愿意将数据发送到8条而不是4条,而且我认为代码不会运行得更快。
当我在我的开场白中赚钱时,这段代码看起来非常慢,我不明白为什么:图像(led,pin,orderchannel)
下面是处理草图中的代码,它的运行速度至少是Python脚本的10倍:
void image2data(PImage image, byte[] data, boolean layout) {
int offset = 3;
int x, y, xbegin, xend, xinc, mask;
int linesPerPin = image.height / 8;
int pixel[] = new int[8];
for (y = 0; y < linesPerPin; y++) {
if ((y & 1) == (layout ? 0 : 1)) {
xbegin = 0;
xend = image.width;
xinc = 1;
} else {
xbegin = image.width - 1;
xend = -1;
xinc = -1;
}
for (x = xbegin; x != xend; x += xinc) {
for (int i=0; i < 8; i++) {
pixel[i] = image.pixels[x + (y + linesPerPin * i) * image.width];
pixel[i] = colorWiring(pixel[i]);
}
for (mask = 0x800000; mask != 0; mask >>= 1) {
byte b = 0;
for (int i=0; i < 8; i++) {
if ((pixel[i] & mask) != 0) b |= (1 << i);
}
data[offset++] = b;
}
}
}
}我不敢相信Python比Java慢得多。我仍然希望任何人都知道访问numpy数组的像素有什么问题。
https://stackoverflow.com/questions/54811645
复制相似问题