![e851f213f1450b1de61bf9e535f26264.png](https://i-blog.csdnimg.cn/blog_migrate/72177fbf90d6f165fd6bff5c32ee5819.png)
首先,请自行安装好软件
https://processing.org/reference/libraries/video/
「Part1 : 颜色追踪原理分析」
这里我们可以分为三点来分析:
1.获取坐标
计算颜色的相似度
判断并记录符合条件的像素的x,y坐标
我们选取某一帧进行图像分析。首先我们在这里调用一个用于存储图像的数据类型pixels[ ],它储存了一副画面的每个像素的颜色信息。然后我们需要将这一帧画面中的每一个pixel颜色进行对比判断,看颜色是否符合我们想要展示出来的颜色,将符合一定范围的颜色判断是跟踪的颜色,即trackcolor。
以宽度width为5为例:
如果我们想获取坐标为(3,2)这一点的颜色信息就是pixels[13]。
这个计算公式为 : pixels[ ]=纵坐标(y) * 宽度(width)+横坐标(x)
![55e04473dd6151bcd0904e02818a7516.png](https://i-blog.csdnimg.cn/blog_migrate/c1dc4ebdc6108c31148d65f6e1939e82.jpeg)
2.相似度
计算颜色与目标颜色(trackColor)之间的相似度
这里我们将color(R,G,B)转换为三维坐标(x,y,z),将currentColor(当前颜色)与trackColor(跟踪颜色)看成两个点,当两点之间距离最短,也是亮点的颜色最为相近的时候,所以我们用dis表示颜色相似度。
![20c76abf3fe3a0f6bd54dd5ac026f384.png](https://i-blog.csdnimg.cn/blog_migrate/9433aaf80ebb16a65d29842d91ddcdb6.jpeg)
![4b4ca7b6fc8c88f0b924dadde2d191ec.gif](https://i-blog.csdnimg.cn/blog_migrate/73ac94f7bed09f743953a81125dfa182.gif)
3.试点
整理符合条件的(x,y)
计算出跟踪颜色的范围和稳定的位置
当第一次检测到trackcolor(跟踪颜色),我们用坐标为(minx,miny)(maxx,maxy)两点创建一个矩形(Box),属性来计算这个Box的大小,distThreshold 来存储距离临界值。
若每次检测到的trackcolor(跟踪颜色)的点坐标与Box的中心点坐标之间的距离小于distThreshold 则添加进Box范围,更新(minx,miny)(maxx,maxy)重新计算box的大小。
distThreshold 决定的box的最大size。
最后box的中心点就是我们跟踪颜色的位置。
![f4927c58d0281659c3aa6a0403f912d8.gif](https://i-blog.csdnimg.cn/blog_migrate/9436e2bcc1b76b5beb6321acf750133c.gif)
「Part2 : 彩带生成原理分析」
这里我们先用鼠标模拟一下颜色跟踪,为了轨迹生成图形做准备,我们需要一个队列来记录鼠标位置的历史信息。
![3c26dd6e345abdcc889dd8ba31afa091.gif](https://i-blog.csdnimg.cn/blog_migrate/74d352b617665b0a66d35a93dc4fa3c7.gif)
1.队列
ArrayList存储可变数量的对象
这里面,我们一共记录的30帧鼠标的历史位置,在循环中,每当记录新的位置,就会将最将“老”的信息,挤出队列。
以限制长度10为例:
如果size( )<10时,将所有的元素添加到数组队列;size( )>10时,就会先remove(0),移除掉最老的元素,也就是第一个(index为0的元素),然后add( )新的元素。
就像水管一样,数组列表里的数据不断地在更新。
![98246ea9631bd1fc8132e5144ecf2830.gif](https://i-blog.csdnimg.cn/blog_migrate/5b2f1ff35810e65269e1c0737a01e47e.gif)
▲ArrayList存储原理
再把轨迹在原坐标的基础上添加上一个随机量,做成5条,我们的彩带就更具有交互性了。
![34a3e156671cfc426a2db5f32619909d.gif](https://i-blog.csdnimg.cn/blog_migrate/9065a170b58802d456e1f688db8cb9e0.gif)
2.直线轨迹变曲线
利用bezierVertex() 贝塞尔曲线
使画面更生动
![8c02c96f7a89359ad9e08162e64a7c03.gif](https://i-blog.csdnimg.cn/blog_migrate/d56390a9152f133e56483928479b7846.gif)
这个过程可以简单分为两步:
确定曲线方向和确定曲线宽度
第一步:确定曲线的方向
首先定义几个参数:
pos——当前点的位置坐标
'pos——上一个点的位置坐标
pos'——下一个点的位置坐标
leftMid——线段pos'pos的中点
rightMid——线段pospos'的中点
![985d94e733f0964d79971fe7ae12fbac.gif](https://i-blog.csdnimg.cn/blog_migrate/ac7d5265e1b5ae0b420082c64706b9d1.gif)
然后我们把点pos的运动方向设定为leftMid指向rightMid的连线方向,向量长度定义为单位长度1,记向量为dir。
第二步:确定曲线的宽度
在我们模拟曲线运动的过程受到速度影响,速度越快,曲线越长。所以我们用radius表示曲线半径。
![f6415b52fd88b233aa3f06711eb63aff.png](https://i-blog.csdnimg.cn/blog_migrate/ed40005ad33e70ecc65abc2a4bc8f1d7.jpeg)
接下来我们将向量dir分别顺时针、逆时针旋转90°,得到两个新的单位向量。
以下图为例:
点leftside为单位向量逆时针旋转90°得到新的单位向量,记为dir'。dir'乘以radius得到新的向量长度,最后加上点pos的位置坐标即可得到点leftside的位置坐标。
而这段向量长度我们用计算公式表示为:
|leftSide|=pos+dir.rotate(-90°)mult(radius),rightSide同理
![19517875d156278a854c4dfefbd0dcc1.gif](https://i-blog.csdnimg.cn/blog_migrate/3a8a9355c7e45f62792b678e1f74e0f3.gif)
接下来我们用同样的方法把前后的leftSide与rightSide都连接起来,找到各个线段的中点,得到了pos连线的轮廓扩展,接连起来就是绘制曲线bezier。
![1e5441d1ec4e76013b0c75439de27dd4.gif](https://i-blog.csdnimg.cn/blog_migrate/718eb9974aa7bdda4fe893ff0ca63692.gif)
贝赛尔曲线的点类似于钢笔的锚点,只不过是用计算机绘制出来,我们同样需要让曲线闭合。
在beginShape()里,先绘制的左侧的边,
确定第一个锚点(上一个的nextLeftSideMid),
依次是两个控制点(leftSide与当前的nextLeftSideMid),
最后一个锚点(nextLeftSideMid),
因为我们只需要3个顶点,所以将最后的锚点和第二个控制点设置成同一个。
右侧边绘制也是相同的原理。
![ca7385eb732a16f5d72bfcf2fd792bda.gif](https://i-blog.csdnimg.cn/blog_migrate/58d079c7cb878067070bba994751737b.gif)
【最终效果展示】
![4f46548cdaf19a041511abf0ea9ec7c7.gif](https://i-blog.csdnimg.cn/blog_migrate/27f4f3ce2ec762362719cde140602b7f.gif)
▲让我们看一下杨总的宝贵影像
![20c21d8e3c15fed0536e2f5c7870159a.gif](https://i-blog.csdnimg.cn/blog_migrate/c847d1c1452128b0d8795af809404bb4.gif)
【源代码获取】
https://mp.weixin.qq.com/s?__biz=MzU4MDg4Mzg4MQ==&mid=2247484347&idx=1&sn=0f4854eedff6478f828f6718e6f74336&chksm=fd51477dca26ce6b5be0dc4c7eaa90305ed78f798821a19ae5c75b72db2bf5cf9ccbd64da734&token=1865694520&lang=zh_CN#rd