【问题标题】:Expanding 8-bit color to 24-bit color将 8 位颜色扩展到 24 位颜色
【发布时间】:2012-10-12 15:41:51
【问题描述】:

设置

我有几百个 Sparkfun LED 像素(类似于 https://www.sparkfun.com/products/11020)连接到 Arduino Uno,并希望使用 Arduino 的内置 Serial-over-USB 连接从 PC 控制像素。

像素可单独寻址,每个像素都有 24 位颜色 (RGB)。由于我希望能够非常快速地更改每个像素的颜色,因此从 pc 到 Arduino 的数据传输必须非常高效(从 Arduino 到像素的数据进一步传输已经非常快了)。

问题

我尝试直接将所需的 RGB 值直接发送到 Arduino,但这会导致明显的延迟,例如,当我想同时打开所有 LED 时。我最小化数据量的直接想法是将可用颜色从 24 位减少到 8 位,这对于我的应用程序来说已经绰绰有余了。

如果这样做,我必须将 PC 上的 8 位值扩展为 Arduino 上的 24 位值,以设置像素上的实际颜色。这里明显的解决方案是一个调色板,它包含所有可用的 8 位值和相应的 24 位颜色。不过,我希望有一个没有调色板的解决方案,主要是出于内存空间的原因。

问题

将 8 位颜色扩展到 24 位颜色的有效方法是什么,最好是准确保留颜色信息的方法?这个任务有标准算法吗?

可能的解决方案

我正在考虑一种格式,每个 R 和 B 为 2 位,G 为 3 位。这些值将被打包成一个字节,然后传输到 Arduino,然后使用位移解包并使用map() 函数 (http://arduino.cc/en/Reference/Map)。

对这个解决方案有什么想法吗?有什么更好的方法来做到这一点?

【问题讨论】:

  • 您的 2-3-2 方案实际上是一种调色板。调色板是一般的方式。问题是每张图像都有其最佳调色板,而使用一个通用调色板会显着降低显示质量。
  • 如果您的图像是相对静态的,您可以预先计算最佳调色板并使用它,可能质量可以接受。
  • 你用什么来通过串口驱动arduino?处理,java,还有什么?
  • 我正在使用自定义 Java 应用程序,它将 Midi 信号转换为控制信号,然后发送到 arduino。我不是想显示图像,它是串上的 LED。
  • 你在 Java 中使用什么库?如果您使用 rxtx,这可能对您有用:neophob.com/2011/04/serial-latency-teensy-vs-arduino

标签: algorithm colors arduino


【解决方案1】:

R2B2G3 会给你很少的颜色(实际上还剩下一点)。我不知道这是否足以满足您的申请。您可以使用dithering technique 使 8 位图像看起来更好一些。

或者,如果您有任何首选的颜色集,您可以将已知的调色板存储在您的设备上,并且永远不要通过网络发送它。您还可以针对不同情况存储多个调色板,并指定使用小整数索引的调色板。

除此之外,还可以实现一些简单的压缩算法,如RLELZW 并在接收后解压缩。

还有一些非常快速且占用空间小的压缩库可供您使用:SnappyminiLZO

【讨论】:

    【解决方案2】:

    关于您的问题“有什么更好的方法来做到这一点?”,首先要做的事情之一(如果尚未完成)是提高串行数据速率。 Arduino Forum 建议使用 115200 bps 作为标准速率,并尝试使用 230400 bps。在这些速率下,您需要编写接收软件,以便它将数据从相对较小的接收缓冲区快速传输到较大的缓冲区中,而不是尝试从较小的接收缓冲区中处理数据。

    第二种可能性是将激活时间放入您的数据包中。假设 F1、F2、F3... 是您将在 LED 阵列上显示的一系列帧。提前从 PC 发送这些帧,或者在空闲或等待时间内发送这些帧,并让 Arduino 缓冲它们直到它们被安排出现。当给定帧的激活时间到达时,让 Arduino 打开它。如果您事先知道帧但不知道激活时间,请发送和缓冲帧,并在适当的时间仅发送激活码。

    第三,您可以拥有多个动态调色板和动态调色板,并且可以使用像素地址或像素列表以及像素图。也就是说,您可能会在不同的时间使用不同的协议。协议 3 可能会下载整个调色板,协议 4 可能会更改调色板的一个元素,协议 5 可能会发送一个 24 位值 v、一个时间 t、一个计数 n,以及一个在时间 t 设置为 v 的 n 个像素的列表, 6 可能会发送像素设置的位图,等等。位图可以是指示开或关的简单的每像素 1 位图,也可以是每像素 k 位图,其中 k 位条目可以指定像素的调色板编号或帧编号。这有点模糊,因为有很多可能性;但简而言之,定义适用于您所显示的任何内容的协议。

    第四,鉴于 ATmega328P 的 RAM 较小 (2KB),但闪存较大 (32KB),请考虑将多个调色板、帧和宏硬编码到程序中。通过宏,我的意思是生成图形元素的例程,如弧线、线条、开放或填充的矩形。任何预先知道的显示元素都是闪存而不是 RAM 存储的候选者。

    【讨论】:

    • 感谢您富有洞察力的评论。我将尝试进一步提高数据速率,但理想情况下,系统也可以在低 bps 条件下工作。至于预缓冲的帧,恐怕Arduino(2k iirc)上的少量RAM无法缓冲那么多。
    • @user643813,添加了一个段落。但是,如果您可以缓冲 2 帧并使用时间码,则允许在后台发送数据,不可见,而不是由于 USB 时序特性而出现明显的抖动。
    【解决方案3】:

    您的 (2, 3, 2) 位想法被“广泛使用”。尝试起来应该非常简单。质量会很低,但请尝试一下,看看它是否满足您的需求。

    如果查找表随着时间的推移保持不变,那么与 256 色查找表相比,任何其他解决方案似乎都不太可能节省大量内存。我认为任何成功的事情都必须利用您发送到像素的图像类型中的模式。

    【讨论】:

      【解决方案4】:

      无论你怎么看,你真正想要的是图像压缩。因此,我建议您查看 PNG 和 JPG 压缩之类的方法,看看它们是否足够快,适合您的应用程序。

      如果没有,那么您可以考虑自己滚动。到目前为止,您只能进行逐像素压缩;在尺寸方面,您的 (2,3,2) 想法与您预期的一样好。您可以尝试使用四叉树类型的格式:取 4 像素块的平均值,传输差异的压缩(有损)表示,然后将相同的操作应用于平均值的半分辨率图像......

      正如其他人指出的那样,抖动会使您的图像在 (2,3,2) 处看起来更好。对您的应用程序进行抖动的最简单方法可能是为每个像素的每种颜色选择不同的(随机或准随机)固定量化阈值偏移。 PC 和 Arduino 都会有这个阈值表的副本;阈值的分布会阻止分色,而 Arduino 边表将有助于保持准确性。

      【讨论】:

        猜你喜欢
        • 2022-11-25
        • 1970-01-01
        • 1970-01-01
        • 2016-10-09
        • 2014-12-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-28
        • 1970-01-01
        相关资源
        最近更新 更多