首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带Teensy和Python的LED条纹

带Teensy和Python的LED条纹
EN

Stack Overflow用户
提问于 2019-02-21 16:16:14
回答 2查看 220关注 0票数 0

我目前正在进行一个项目,以控制LED条纹,这是连接到一个Teensy 3.2板,这是连接到Windows PC。它在技术上是基于这个项目:OctoWS2811.html

还有一个用vvvv实现的项目:https://vvvv.org/contribution/realtime-led-control-with-teensy3.xoctows2811

到目前为止,两人都工作得很好。我要做的是将movie2serial程序(关于pjrc.com上的项目)移植到Python。

所以我发现了这个项目:py

它不是从盒子里出来的,但是经过一些修改,我就可以运行它了。下面是类的代码,它接收图像,将其转换为字节数组,并将其发送到串口:

代码语言:javascript
复制
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。

在这个代码中有两个瓶颈:

  1. 写入串口(方法发送中的self.port.write)。也许它不能加快速度,这是可以接受的。

但更重要的是:

  1. 访问图像数组(方法image2data中的图像[led,pin,orderchannel] )。当我换行时,例如: 如果0x80 >>位& 255:

代码运行速度要快6-7倍(~ 80 FPS)。顺便说一句,orderchannel用于将颜色从BGR转换为GRB。

长话短说:从图像阵列读取颜色非常缓慢。如何在方法image2data中加快图像数组到字节数组的转换?

当你谈到这一点的时候,谢谢你的耐心:-)我很抱歉这么长的职位,但这是一个复杂的项目,不容易向我解释。我非常感谢你的帮助,也许其他人也能从中受益。

谢谢你,艾尔

EN

回答 2

Stack Overflow用户

发布于 2019-02-23 03:25:20

通过将order[channel]提升到内环之外(通过将channel_index = order[channel]保存在order上),第二个热点就可以得到改善。

代码语言:javascript
复制
if 0x80 >> bit & image[led,pin,channel_index]:

这将是一个小小的进步。它还看起来,提升0x80 >> bit的水平,可以节省8次冗余计算。把它保存为mask,然后你就可以

代码语言:javascript
复制
if mask & image[led,pin,channel_index]:

加起来,这些可能值几个FPS。

但是,看看您的代码,这些循环嵌套的方式看上去是错误的。对于180 x 4 RGB LED,我希望您需要发送180 x 4×3字节到Teensy。但是代码正在发送3x180x8,这两个内部循环是否有可能需要倒转呢?

票数 0
EN

Stack Overflow用户

发布于 2019-02-25 16:36:26

谢谢你的回答和改进。稍后我将实现它们,但我想它们不会加快到所需的60个FPS。

代码是发送3x180x8,因为这是板子。LED用以太网电缆连接到板上,以太网电缆有8个引脚,所有8个引脚都需要处理,否则条纹显示出奇怪的结果。另一方面,在以后的配置中,我需要4条以上的数据,所以目前我不愿意将数据发送到8条而不是4条,而且我认为代码不会运行得更快。

当我在我的开场白中赚钱时,这段代码看起来非常慢,我不明白为什么:图像(led,pin,orderchannel)

下面是处理草图中的代码,它的运行速度至少是Python脚本的10倍:

代码语言:javascript
复制
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数组的像素有什么问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54811645

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档