Queue 了一篇 CaPiano. 上午展示完. 人智课生产力低下. 把它 Dequeue 了罢.

这个项目的最初设想是造一个识别指尖的算法, 然后用它来弹钢琴并发出声音. 还有一个完全没有开动的二期工程是把它变成一个音游 / 录音机.

蓝图是美好的, 实现是丑陋的.

摄像头

过去一个半月的主要工作就是和这个 OV7670 (AL422B) 的摄像头做斗争. AL422B 是一个 DRAM 的 FIFO 队列, 通过巧妙地接 7670 和 422 的管脚可以实现把 422 作为 7670 的一个输出缓冲. 422 本来是用于简化这件事的. 在国外大学的 PA 文档里也是这么说的. 然而 422 这个东西最大的毛病就是没有 dataready 这个信号, 所以根本没法成功探索出什么时候可以读. 挣扎了很久之后我选择买了一个不带 422 的 7670.

7670 通过 SCCB 协议来进行配置, 有一些寄存器. 主要有用的是控制彩色的 12 和控制输出格式的 40. 本来想要 RGB565 加 QVGA 爽歪歪. 然而我的配置模块跑出来结果完全不对, 最后发现根本没设起. 降频到手工时钟都没有办法正常工作. 于是只好放弃, 使用默认的 YUV + VGA.

另外在网上看到有一个输出彩色条的 80 寄存器. 然而因为同上原因也没有用上.

YUV格式是一个相邻两个像素共用四字节的奇怪格式. 按照时间读进来的四个字节是 Y1 U Y2 V. 其中Y是灰度, U和V是奇怪的参数. wikipedia 上有一个通过线性变换把它变到 RGB 彩色空间上的矩阵. 然而我发现我只有G是能判断出来的, 而且屏幕上的G其实是红色…

这些问题都没解决也不打算解决了. 红色, 够用了.

识别算法

最初想的识别算法是连通块判定blabla. 选这个题也是想用这个 CV 的问题充分发挥 FPGA 逻辑单元的并行性.

然后噩耗是, 摄像头和VGA都是扫描的.

于是最后变成了直接 Threshold. 因为 Threshold 太难调所以又加了个拿 PS2 键盘调 threshold 的小功能.

然后就变成了识别一个像素点的 绿 红 蓝 分别大于或者小于某个值.

真 简单粗暴.

当然直接用手指是效果不好的

于是我就去淘宝买了三盒红色橡胶指套.

这指套也不是正红而是粉红.

于是又去文具店买了根红色记号笔.

终于能让它稍微效果好点了.

琴键按下

同上. 直接判断某个屏幕区域里有多少个像素点是被识别成手指的. 然后用个 threshold.

本来这块也是想并行做的, 然而. 扫描的.

讲道理只要 30fps 的话并行也不错. 然而实在是懒得写状态姬了. 于是yy了一个动态维护的方法, 直接减去旧值加上新值 (都是0或者1).

后来发现竟然会减成负的. 毕竟这个识别的准确性和 ram 读写都不是特别靠谱.

索性过一段时间清零一次这个 count 寄存器组.

然后意外发现这个东西顺便解决了长按弹起的问题, 鲁棒性大大地加强了. 非常开心.

别的部分

剩下和 pc 通信并发现钢琴声的部分就全靠队友 bakser 同学了.

bakser 同学干活还是很靠谱的.

用了别人的 python 库. 来发声. 竟然还有 fft 和弦这种高级玩意.

最后其实用起来效果也蛮奇怪的. 不过大家都是弹弹玩, 也没有谁认真地弹琴的. 也就乐呵呵地糊过去了.

差点搞死我的数设 project 也就是这样了啦.

以后有机会希望能拿 fpga 造点真正有用的东西. (比如网卡? 交换机? 硬件压缩算法? DL infer?)

代码库也是乱七八糟没救了. (顺便感激一下 github 上找到的 submodule 让我抄都懒得抄了)

https://github.com/laekov/capiano


Historical Comments

laekov at 2018-06-12T22:05:42

突然产生了自己寨一个 strava 的想法… 然而除了画图有什么好玩之处呢? 思考