[STM32]开源光流定点 四轴 PIX

本文介绍了一种基于STM32F407VET6的光流算法实现过程,详细展示了通过检测特征点并计算相邻帧间像素变化来估计物体运动的方法,并分享了实际的代码实现。

废话不多说先上图:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

硬件配置:
STM32F407VET6
MPU6050
VL53L0X

光流的概念是Gibson在1950年首先提出来的。它是空间运动物体在观察成像平面上的像素运动的瞬时速度,是利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的对应关系,从而计算出相邻帧之间物体的运动信息的一种方法。一般而言,光流是由于场景中前景目标本身的移动、相机的运动,或者两者的共同运动所产生的。其计算方法可以分为三类:
(1)基于区域或者基于特征的匹配方法;(L-K的方法)
(2)基于频域的方法;
(3)基于梯度的方法;
简单来说,光流是空间运动物体在观测成像平面上的像素运动的“瞬时速度”。光流的研究是利用图像序列中的像素强度数据的时域变化和相关性来确定各自像素位置的“运动”。研究光流场的目的就是为了从图片序列中近似得到不能直接得到的运动场。
光流法的前提假设:
(1)相邻帧之间的亮度恒定;
(2)相邻视频帧的取帧时间连续,或者,相邻帧之间物体的运动比较“微小”;
(3)保持空间一致性;即,同一子图像的像素点具有相同的运动。

一样的手工焊接,焊的丑,就别在意那个了,功能实现最重要。
之前一直是用的PIXFLOW和匿名的光流 所以一直想自己做一个理解一下其中的过程
匿名的只是为了赚钱 所以不开源 只有看pixflow的源码了
其中截取了一部分复制到了自己的工程里

///////////////////////////////////////////////////////
//函数功能:检测某点是否是特征点
///////////////////////////////////////////////////////
static inline uint32_t compute_diff(uint8_t *image, uint16_t offX, uint16_t offY, uint16_t row_size)
{
        uint16_t off = (offY + 2) * row_size + (offX + 2); // we calc only the 4x4 pattern
        uint32_t acc;
        //4*4像素向下求差,再累加
        acc = __USAD8 (*((uint32_t*) &image[off + 0 + 0 * row_size]), *((uint32_t*) &image[off + 0 + 1 * row_size]));
        acc = __USADA8(*((uint32_t*) &image[off + 0 + 1 * row_size]), *((uint32_t*) &image[off + 0 + 2 * row_size]), acc);
        acc = __USADA8(*((uint32_t*) &image[off + 0 + 2 * row_size]), *((uint32_t*) &image[off + 0 + 3 * row_size]), acc);
        //4*4像素向右求差,再累加
        uint32_t col1 = (image[off + 0 + 0 * row_size] << 24) | image[off + 0 + 1 * row_size] << 16 | image[off + 0 + 2 * row_size] << 8 | image[off + 0 + 3 * row_size];
        uint32_t col2 = (image[off + 1 + 0 * row_size] << 24) | image[off + 1 + 1 * row_size] << 16 | image[off + 1 + 2 * row_size] << 8 | image[off + 1 + 3 * row_size];
        uint32_t col3 = (image[off + 2 + 0 * row_size] << 24) | image[off + 2 + 1 * row_size] << 16 | image[off + 2 + 2 * row_size] << 8 | image[off + 2 + 3 * row_size];
        uint32_t col4 = (image[off + 3 + 0 * row_size] << 24) | image[off + 3 + 1 * row_size] << 16 | image[off + 3 + 2 * row_size] << 8 | image[off + 3 + 3 * row_size];
        //全部累加
        acc = __USADA8(col1, col2, acc);
        acc = __USADA8(col2, col3, acc);
        acc = __USADA8(col3, col4, acc);
        return acc;
}

[color=rgb(51, 102, 153) !important]复制代码
///////////////////////////////////////////////////////
//函数功能:比较两副8X8像素图片的相似度
///////////////////////////////////////////////////////
static inline uint32_t compute_sad_8x8(uint8_t *image1, uint8_t *image2, uint16_t off1X, uint16_t off1Y, uint16_t off2X, uint16_t off2Y, uint16_t row_size)
{
        uint16_t off1 = off1Y * row_size + off1X; // image1
        uint16_t off2 = off2Y * row_size + off2X; // image2
        //两副8*8像素对应相减,再累加
        uint32_t acc;
        //第一行相减,再累加
        acc = __USAD8 (*((uint32_t*) &image1[off1 + 0 + 0 * row_size]), *((uint32_t*) &image2[off2 + 0 + 0 * row_size]));
        acc = __USADA8(*((uint32_t*) &image1[off1 + 4 + 0 * row_size]), *((uint32_t*) &image2[off2 + 4 + 0 * row_size]), acc);
        //第二行相减,再累加,依次类推
        acc = __USADA8(*((uint32_t*) &image1[off1 + 0 + 1 * row_size]), *((uint32_t*) &image2[off2 + 0 + 1 * row_size]), acc);
        acc = __USADA8(*((uint32_t*) &image1[off1 + 4 + 1 * row_size]), *((uint32_t*) &image2[off2 + 4 + 1 * row_size]), acc);
        acc = __USADA8(*((uint32_t*) &image1[off1 + 0 + 2 * row_size]), *((uint32_t*) &image2[off2 + 0 + 2 * row_size]), acc);
        acc = __USADA8(*((uint32_t*) &image1[off1 + 4 + 2 * row_size]), *((uint32_t*) &image2[off2 + 4 + 2 * row_size]), acc);
        acc = __USADA8(*((uint32_t*) &image1[off1 + 0 + 3 * row_size]), *((uint32_t*) &image2[off2 + 0 + 3 * row_size]), acc);
        acc = __USADA8(*((uint32_t*) &image1[off1 + 4 + 3 * row_size]), *((uint32_t*) &image2[off2 + 4 + 3 * row_size]), acc);
        acc = __USADA8(*((uint32_t*) &image1[off1 + 0 + 4 * row_size]), *((uint32_t*) &image2[off2 + 0 + 4 * row_size]), acc);
        acc = __USADA8(*((uint32_t*) &image1[off1 + 4 + 4 * row_size]), *((uint32_t*) &image2[off2 + 4 + 4 * row_size]), acc);
        acc = __USADA8(*((uint32_t*) &image1[off1 + 0 + 5 * row_size]), *((uint32_t*) &image2[off2 + 0 + 5 * row_size]), acc);
        acc = __USADA8(*((uint32_t*) &image1[off1 + 4 + 5 * row_size]), *((uint32_t*) &image2[off2 + 4 + 5 * row_size]), acc);
        acc = __USADA8(*((uint32_t*) &image1[off1 + 0 + 6 * row_size]), *((uint32_t*) &image2[off2 + 0 + 6 * row_size]), acc);
        acc = __USADA8(*((uint32_t*) &image1[off1 + 4 + 6 * row_size]), *((uint32_t*) &image2[off2 + 4 + 6 * row_size]), acc);
        acc = __USADA8(*((uint32_t*) &image1[off1 + 0 + 7 * row_size]), *((uint32_t*) &image2[off2 + 0 + 7 * row_size]), acc);
        acc = __USADA8(*((uint32_t*) &image1[off1 + 4 + 7 * row_size]), *((uint32_t*) &image2[off2 + 4 + 7 * row_size]), acc);
        return acc;
}

[color=rgb(51, 102, 153) !important]复制代码


然后每隔4个像素来找特征点
                        //上下左右循环移动4个像素对比图片相似度
                        for(int8_t yy=winmin; yy<=winmax; yy++)
                        {
                                for(int8_t xx=winmin; xx<=winmax; xx++)
                                {
                                        //计算匹配度
                                        temp_match = compute_sad_8x8(image_new, image_old, x, y, x + xx, y + yy, wid);
                                        //寻找最小值,越小越相似
                                        if (temp_match < match_min)
                                        {
                                                sumx = xx;
                                                sumy = yy;
                                                match_min = temp_match;
                                        }
                                }
                        }

最后实际的效果还不错 激光芯片VL53L0X一样可以正常工作,对自己的焊工自豪一波

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值