随想 20210712
天上星河转,人间幕帘垂。凉生枕蕈泪痕滋。起解罗衣聊问何其。

晚上,额或者说凌晨2:42了。好像还没睡。

最近在调车,我是做图像的。

其实挺奇怪的,我本来是做控制的,转组后算是跟队做硬件。五月份的时候,突然被要求做图像处理,就稀里糊涂的变成了图像处理的队员,然后学长学姐不知道为啥先后退出,又稀里糊涂的成了正式队员。

其实其他队员开始似乎挺抱期望的,因为他们借到了杨一鸣学长的图像处理代码,认为只要稍加修改就可以使用。

但是我明白,因为有了前事的经验。所以知道做这种事最容易、也最忌讳把事情想简单。做双车的时候就是,认为二月初就可以基本完成,但实际上进度远远落后。

说到杨一鸣学长,我觉得他很像是熟悉的人,感觉比较亲切,然后业务能力也确实强。我觉得这些能力是需要在课堂外额外花时间去积累的。

说回来,反正现在七月十二号了,进度依然不乐观。稳定性和速度,甚至完全比不上使用麦克姆轮的全向行进组的小车(杨一鸣学长做的图像处理)

图像处理代码是自己一行一行敲出来的,一方面是因为学长只给了旧版的代码,执行尚存问题。并且5000行的代码阅读起来不是很通畅,耦合性也稍有些严重。

现在的图像处理代码里使用了大量的色块比较(就算是简单的模板比较吧),前天把算法小改了下,算是减少了一些运算量。使用这种方式,一方面是因为对特征点的识别不是很擅长,并且使用的是水平扫线法而非八领域生长,边缘的误判比较严重;另一方面是得益于RT1064的高性能,可以比较任性的使用资源而不用担心运算速度和内存空间的问题(相比之前使用的mm32spin27ps好多了)。

但是也色块识别有一些比较严重的问题,一是对于变化的环境适应性较差(即所谓“鲁棒性”较差),二是反而增加了计算开销。

色块识别在图像中的位置是固定的,因此对于每个特征的不同表现形式不会特别适应。比如三岔入口,正对和斜入会有完全不同的表现形式,原本正对时所呈现的白区,在斜入时很可能就是黑区,如果采用色块识别就会失效。

耗费算力的问题,色块识别在图像中要逐像素比较,即使使用了快速模板比较的写法,也仍然存在较大的计算量。以每帧必然比较的T形路为例,如果符合条件的话最多需要比较188*3个像素点。这还仅仅是一个特征...

为了减少不必要的状态判断,我认为需要先完善状态互斥的内容。即有限状态机中列出互斥的状态,使状态识别更像是串行而非并行的,就像在环岛状态中不必识别十字一样。

另外对一个元素分段处理也是很必要的。以前使用学长的代码时总是卡在入环阶段,所以对这种链式的有限状态机有些怀疑,但其实是因为没有找到比较合适的错误状态的处理机制。毕竟链式状态要简洁的多。

    //------环岛检测 <head>---------//

    switch(Round_Status)
    {
        case 0:
            if(flag_Y_Road || Feature_Verify_Color(83,9,20,40,Black,10))
            {
                break;
            }
        
            if(!RoundOutCount && Feature_Verify_Color(10,10,50,8,White,90) && !Feature_Verify_Color(127,10,50,3,White,90))
            {
                Round_Status=1;

                flag_Normal_Lose_L=1; //避免打偏
            }
            else if(!RoundOutCount && Feature_Verify_Color(127,10,50,8,White,90) && !Feature_Verify_Color(10,10,50,3,White,90))
            {
                Round_Status=2;

                flag_Normal_Lose_R=1;
            }
        
            break;

        case 1:
            if(ad_value_all>Round_ad_limit && Feature_Verify_Color(0,10,20,10,Black,90))
            {
                if(ad_value_all<Round_ad_limit)
                {
                    Round_Status=0;
                    break;
                }

                Round_Status=3;
            }
            break;

        case 2:
            if(ad_value_all>Round_ad_limit && Feature_Verify_Color(167,10,20,10,Black,90))
            {
                if(ad_value_all<Round_ad_limit)
                {
                    Round_Status=0;
                    break;
                }

                Round_Status=4;
            }
            break;

        case 3:
            if(!RoundInCount && Feature_Verify_Color(0,10,50,10,White,90))
            {
                RoundInCount=25;
            }

            if(RoundInCount==1)
            {
                Round_Status=5;
            }

            flag_Normal_Lose_L=1;

            break;

        case 4:
            if(!RoundInCount && Feature_Verify_Color(137,10,50,10,White,90))
            {
                RoundInCount=25;
            }

            if(RoundInCount==1)
            {
                Round_Status=6;
            }

            flag_Normal_Lose_R=1;

            break;
        case 5:
            if(Feature_Verify_Color(167,39,20,10,White,90))
            {
                Round_Status=7;
            }

            flag_Normal_Lose_L=1;   //否则在大环内容易晃
            break;

        case 6:
            if(Feature_Verify_Color(0,39,20,10,White,90))
            {
                Round_Status=8;
            }
            
            flag_Normal_Lose_R=1;
            break;

        case 7:
            if(1)
            {
                Round_Status=9;

                flag_Normal_Lose_L=1;
            }
            break;

        case 8:
            if(1)
            {
                Round_Status=10;

                flag_Normal_Lose_R=1;
            }
            break;

        case 9:
            /*
            if(!RoundOutCount && Feature_Verify_Color(0,10,50,10,White)>=90)
            {
                Round_Status=10;

                RoundOutCount=40;
                flag_Normal_Lose_L=1;
            }
            */

            if(!RoundOutCount)
            {
                Round_Status=11;

                RoundOutCount=50;
                flag_Normal_Lose_L=1;
            }
            break;

        case 10:
            /*
            if(!RoundOutCount && Feature_Verify_Color(137,10,50,10,White)>=90)
            {
                Round_Status=11;
                RoundOutCount=40;
                flag_Normal_Lose_R=1;
            }
            break;
            */

            if(!RoundOutCount)
            {
                Round_Status=12;
                RoundOutCount=50;
                flag_Normal_Lose_R=1;
            }
            break;

        case 11:
            if(RoundOutCount==1)
            {
                Round_Status=0;
            }
            break;

        case 12:
            if(RoundOutCount==1)
            {
                Round_Status=0;
            }
            break;
    }

    if((flag_Y_Road || flag_Y_Road_IN) && Round_Status<3)    //防止三岔误识别为环岛
    {
        Round_Status=0;
    }

    if(RoundOutCount && Round_Status<=8)
    {
        Round_Status=0;
    }
    //------环岛检测 <bottom>---------//

↑我写的环岛状态机,可以看出使用了很多色块比较,所以存在小车跑偏无法入环的情况。

写这还花了不少时间,暂且这样。3:32分,该睡觉了。

附一张小车的图