19届智能视觉openart固件开源

前言

感谢 华北电力大学(保定)的Y1ZzLu佬 开源的固件!

感谢 华北电力大学(保定)的Y1ZzLu佬 开源的固件!!

感谢 华北电力大学(保定)的Y1ZzLu佬 开源的固件!!!

这篇文章用于提供自己对修改openart固件来解决无框卡片寻找问题的一个方案,由于本人能力不足,并且第一次写博客,所以诸多纰漏还请读者见谅。


一、为什么选择修改openart固件?

原始算法帧率过低

最开始接触智能视觉的视觉部分的时候,就是先打算解决无框卡片的识别问题,因为我发现用openart的find_blob函数很难去识别出无框卡片,并且有框卡片的识别的帧率不是很高,印象中应该就十几帧或者更低。 具体反应在控制上就是控制的时间周期很长,因为我以前调过四轮,所以很清楚帧率对于控制的重要性,如果能提高帧率,无疑能大大减轻控制的压力。后面我试着采用yolo去跑目标检测用于校正,但是受限于模型精度,不管怎么跑都跑不出精度达到我们结构的精度要求。后来在机缘巧合下找到了智能视觉组的开源项目,在里面找到了openart的开源固件。在基于华北电力大学的开源固件上,修改加入了适合今年场景的一些算法,使得能够用于今年的赛题。在修改后,帧率最高在24帧左右,最低18帧,基本可以满足校正的需求。

二、修改的一些思路和源代码

1.总体思路

因为原来开源固件的矩形检测的帧率和框架都完全满足要求,但是这次的卡片背景并不是纯蓝色,背景较为复杂,所以需要对原有的固件进行一些修改,使得能够满足要求。
在这里插入图片描述

我首先想到的就是把赛道给分割出来,都作为蓝色处理,在实现的过程中发现内存有点不够用,在逐渐理解Y1ZzLu佬的算法后,想到只要把与卡片相交的黑胶的那条线给找出来,用于分割卡片和赛道,就能成功的找到矩形。所以我的算法重点就是放在了怎么去寻找这一条线上。
在这里插入图片描述

2.具体实现和改进

(1).找黑胶

这里模仿Y1ZzLu佬,采用了寻找最大连通域的算法,用于提取出黑胶,并且用于后续的处理。

static inline int BFS_color(uint8_t *im, uint16_t x, uint16_t y,uint16_t *X, uint16_t *Y, bool *st,uint8_t thresh,image_t *ptr)
{
	  uint16_t area = 0;
	  st[y * IMG_W + x]=true;
    int16_t  arr[4][2] = {{0, 1},
                         {-1, 0},
                         {0, -1},
                         {1, 0}};//四领域
    int16_t queuehead = 0, queuetail = 0;
    queuepush(X, Y, &queuetail, x, y, my_queuesize);
		point_t *pnts = fb_alloc(sizeof(point_t) * pntsize, FB_ALLOC_NO_HINT);
		uint16_t maxx = x, minx = x, maxy = y, miny = y;//定义检索的范围
    while (queue_size(queuehead, queuetail, my_queuesize))
    {
        point_t t = queuefront(X, Y, queuehead);
        queuepop(&queuehead, my_queuesize);
			  area++;
        for (uint8_t i = 0; i < 4; i++)
        {
            int16_t nextx = t.x + arr[i][0], nexty = t.y + arr[i][1];
					   if(im[nexty * IMG_W + nextx]!=thresh)
						 {
							 break;
						 }
            if (nexty < 4 || nextx < 4 || nexty > IMG_H - 4 || nextx > IMG_W - 4)
                continue;//索引超过边界
            if (im[nexty * IMG_W + nextx]==thresh&& st[nexty * IMG_W + nextx]==false)//把满足条件的点加入数组
            {
                queuepush(X, Y, &queuetail, nextx, nexty, my_queuesize);
							  pnts[my_queuesize].x = nextx;
                pnts[my_queuesize].y = nexty;
                maxx = MAX(maxx, nextx);
                minx = MIN(minx, nextx);
                maxy = MAX(maxy, nexty);
                miny = MIN(miny, nexty);
							  st[nexty * IMG_W + nextx]=true;
            }
        }
    }
		//mp_printf(&mp_plat_print, "queuetail = %d\n", queuetail);
		uint16_t dx = maxx - minx, dy = maxy - miny;
    if (dx < 100 && dy < 100)
    {
        fb_free();
        return 0;
    }
    else if (my_queuesize < 200)
    {
        fb_free();
        return 0;
    }
		else
		{
			  fb_free();
				//mp_printf(&mp_plat_print, "dx = %d dy = %d\n", dx,dy);
			  return area;
		}
}



    for (int degree = 0; degree < 360; degree += 30) {
        float x = 160, y = 120;
        float rad = degree * PI / 180;
        float dx = cos(rad), dy = sin(rad);
        int i, j;

        for (;;) {
            x += dx;
            y += dy;
            i = (int)y;
            j = (int)x;
            if (i < 4 || j < 4 || i > IMG_H - 4 || j > IMG_W - 4)  // 图片的边缘不检索
                break;
            if (Img[320 * j + i] == thresh && my_st[320 * j + i] == false) {  // 满足颜色条件并且没有被访问过
                uint16_t area = BFS_color(Img, i, j, my_queueX, my_queueY, my_st, thresh,ptr);
							  if(area>2000)
								{
									area_count++;
								}
								//mp_printf(&mp_plat_print, "area_count = %d\n", area_count);
                if (area > maxArea) {
                    maxArea = area;
                    // 清空之前的最大连通域数据
                    maxQueueHead = 0;
                    maxQueueTail = 0;
                    // 复制当前连通域数据到最大连通域队列
                    memcpy(max_queueX, my_queueX, maxArea * sizeof(uint16_t));
                    memcpy(max_queueY, my_queueY, maxArea * sizeof(uint16_t));
                    maxQueueTail = maxArea;  // 更新最大队列尾部
                }
                // 重置当前队列尾部,准备下一轮搜索
            }
        }
    }
                                  手头没有其他截图,拿一张被数据线截断的演示一下效果。

在这里插入图片描述

(2).找线

找线有很多方法和思路,这里仅提供我试过的可行的方案。我认为提供的方案在稳定性上是还可以的,但是为了一些情况舍弃了速度,并且能改进的地方还有很多很多,仅作为一个能使用的方案供参考。

                                                  先放代码
*******************************判断一个点的下面是不是与白色相邻->用于判断是不是想要的线内的点****************************
bool pix_around_white(image_t *ptr,int x,int y)
{
		uint8_t h, s, v;
	  bool white_flag=0;
	  bool other_flag=0;
	  for(int i=x;i<=x;i++)
	 {
		for(int j=y+1;j<=y+5;j++)
		{
			uint16_t pix = IMAGE_GET_RGB565_PIXEL_FAST(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(ptr, j), i);
		  uint8_t R = COLOR_RGB565_TO_R8(pix), G = COLOR_RGB565_TO_G8(pix), B = COLOR_RGB565_TO_B8(pix);
	    get_hsv(pix,&h,&s,&v);
      if(!(h >= 100 && h <= 124)&&!((B < 50 &&  G < 50 && R < 50)||((B < 100 &&  G < 100 && R < 100)&&my_abs(B,G)<15&&my_abs(B,R)<15&&my_abs(R,G)<15)&&(((B > 160 &&  G > 160 && R > 160 && my_abs(B, G) < 25 && my_abs(B, R) < 25 && my_abs(R, G) < 25)
				|| (B > 100 && G > 100 && R > 100&&my_abs(B,G)<15&&my_abs(B,R)<15&&my_abs(R,G)<15)
				||(B > 190 && G > 190 && R > 190)))))//白色
			{
				 white_flag=1;
				 break;//只要此黑色下面五个点有一个为白色便判断为有白色
			}
			else
			{
				white_flag=0;
			}
		}
	 }
	 if(white_flag==0)
	 {
		 return true;
	 }         
	 else
	 {
		 return false;
	 }
}
**********************************具体找线代码,在连通域的基础上做处理,并且加入曲线拟合****************************
    for (int i = 0; i <=maxArea; i++) {
       if(max_Y[max_queueX[i]]<max_queueY[i])
			 {
				 max_Y[max_queueX[i]]=max_queueY[i];
			 }//找到连通域每一列最下面的黑色
    }
    for (int i = 21; i < 299; i++) {
			if(max_Y[i]==0)
				{
					 error_count++;
				}//如果没被赋值,说明这一列没有想要的点
			else if((max_Y[i]!=0&&pix_around_white(ptr,i,max_Y[i]))==true||max_Y[i]>220)
				{
					X[count] = i;
         		    Y[count] = max_Y[i];
					count++;
				}//满足被赋值(说明该列有黑胶),并且是固定赛道的黑胶
    }
		for(int i =0;i< count;i++)
		{
			 if(threshold%10==2)
				{
			    imlib_set_pixel(ptr,X[i],Y[i],255);
				}	
		}
		if (error_count > 0&&count > 3)// 有断点用曲线拟合(一般不会出现这种情况,但是加入可以提升鲁棒性)
		{ 
    double sumX = 0, sumX2 = 0, sumX3 = 0, sumX4 = 0, sumX5 = 0, sumX6 = 0;
    double sumY = 0, sumXY = 0, sumX2Y = 0;

    // 计算所需的各项和
    for (int i = 0; i < count; i++) {
        double xi = X[i];
        double yi = Y[i];
        double xi2 = xi * xi;
        double xi3 = xi2 * xi;
        double xi4 = xi3 * xi;
        double xi5 = xi4 * xi;
        double xi6 = xi5 * xi;
        sumX += xi;
        sumX2 += xi2;
        sumX3 += xi3;
        sumX4 += xi4;
        sumX5 += xi5;
        sumX6 += xi6;
        sumY += yi;
        sumXY += xi * yi;
        sumX2Y += xi2 * yi;
    }

    // 构建矩阵 A 和向量 B
    double A[3][3] = {
        {sumX4, sumX3, sumX2},
        {sumX3, sumX2, sumX},
        {sumX2, sumX, count}
    };
    double B[3] = {sumX2Y, sumXY, sumY};

    // 使用高斯消元法求解线性方程组
    gaussian_elimination(A, B, 3); 
    a = B[0], b = B[1], c = B[2];
    // 画线部分
    for (int x = 0; x < IMG_W; x++) {
        int y = (int)(a * x * x + b * x + c);  // 计算二次曲线上每个 x 对应的 y
        if (y >= 0 && y < IMG_H) 
				{
					if(threshold%10==2)
					{
						imlib_set_pixel(ptr,x,y,100);
					}	 // 使用绿色绘制点
        }
    }
    //mp_printf(&mp_plat_print, "Fitted quadratic curve: y = %.5fx^2 + %.2fx + %.2f\n", a, b, c);
	}
		else {
    //mp_printf(&mp_plat_print, "Not enough points to fit a quadratic curve.\n");
}

具体的就是在找到了一个满足连通域条件的基础上,去找到这条线。因为黑胶的宽度是基本一致的,并且下面的一条与白赛道相接的线图像会比较稳定,因为只有白色的赛道,所以我选择去找下面的这条线,然后再往上平移。找这条线的方法很多,可以找最长的黑白相接连通的线,也可以像我这样比较简单的就是找每一列最下面的黑色。因为我们的车是一直都在赛道上的,所以图像方面比较稳定,可以确保这样找到的就是想要的点。如果方案比较复杂,这种算法就不适用了,需要找别的方法。然后这样找到了点,一般情况都是直接构成能满足要求的线,但是在受反光和一些奇奇怪怪的影响下,可能会导致连通域的寻找和黑线上的点的寻找出问题,所以我加入了二次曲线拟合,可以提供图像的鲁棒性。
在这里插入图片描述

(3).找矩形

找矩形的主要部分直接使用了Y1ZzLu佬的。当卡片是黑色的时候,会与黑胶相连接。我做的是把找到线后的图像进行二次处理,我把找到的连通域中,在这条线上面的黑色作为有效数据处理,把下面的则就当做蓝色,不做处理。

	for(int width=threshold/10;width<threshold/10+10;width++)
	{
	 if(error_count==0)
	 {
		 		for (int i = 0; i < maxArea; i++) 
			{
				if(max_queueY[i]<=max_Y[max_queueX[i]]-width)//在黑胶上的黑色部分
				{
           *(Img + 320 * max_queueY[i] + max_queueX[i]) = 0;
					 //imlib_set_pixel(ptr,max_queueX[i],max_queueY[i],100);
				}//把线上并且是最大连通域内的设置为0,所以如果卡片没和黑胶联通,则不用担心
			else
			  {
					*(Img + 320 * max_queueY[i] + max_queueX[i]) = 255;
		    }//当做黑胶不做处理
			}
	 }
	 else if(error_count>0&&count>3)
	 {
		 	for (int i = 0; i < maxArea; i++) 
			{
			if(max_queueY[i]<=a * max_queueX[i] * max_queueX[i] + b * max_queueX[i] + c-width)
				{
           *(Img + 320 * max_queueY[i] + max_queueX[i]) = 0;
					 //imlib_set_pixel(ptr,max_queueX[i],max_queueY[i],100);
				}//把线上并且是最大连通域内的设置为0,所以如果卡片没和黑胶联通,则不用担心
			else
			  {
					*(Img + 320 * max_queueY[i] + max_queueX[i]) = 255;
		    }//当做黑胶不做处理
			}
	 }
    //mp_printf(&mp_plat_print, "maxarea = %d\n", maxArea);
		struct quad Rect;
    list_init(out, sizeof(find_rects_list_lnk_data_t));
    if (Find_Rect(&im, 5, &Rect,quality))
    {
        uint16_t x, y, w, h, minx = IMG_W - 1, maxx = 0, miny = IMG_H - 1, maxy = 0, min_sum = IMG_W + IMG_H;
        uint8_t idx = 0;
			  uint16_t distance=0;
        find_rects_list_lnk_data_t lnk_data;

        for (uint8_t i = 0; i < 4; i++)
        {
            minx = MIN(minx, (uint16_t)Rect.p[i][0]);
            maxx = MAX(maxx, (uint16_t)Rect.p[i][0]);
            miny = MIN(miny, (uint16_t)Rect.p[i][1]);
            maxy = MAX(maxy, (uint16_t)Rect.p[i][1]);
            if (Rect.p[i][0] + Rect.p[i][1] < min_sum)
            {
                min_sum = Rect.p[i][0] + Rect.p[i][1];
                idx = i;
            }
        }
        x = minx, y = miny, w = maxx - minx, h = maxy - miny;
        lnk_data.corners[3].x = Rect.p[idx][0];
        lnk_data.corners[3].y = Rect.p[idx][1];
        lnk_data.corners[2].x = Rect.p[(idx + 3) % 4][0];
        lnk_data.corners[2].y = Rect.p[(idx + 3) % 4][1];
        lnk_data.corners[1].x = Rect.p[(idx + 2) % 4][0];
        lnk_data.corners[1].y = Rect.p[(idx + 2) % 4][1];
        lnk_data.corners[0].x = Rect.p[(idx + 1) % 4][0];
        lnk_data.corners[0].y = Rect.p[(idx + 1) % 4][1];
        // if (check_yellow(ptr, lnk_data.corners[3], lnk_data.corners[1], quality) && check_yellow(ptr, lnk_data.corners[1], lnk_data.corners[3], quality) && check_yellow(ptr, lnk_data.corners[2], lnk_data.corners[0], quality) && check_yellow(ptr, lnk_data.corners[0], lnk_data.corners[2], quality))
            // mp_printf(&mp_plat_print, "kuang!\n");
        rectangle_init(&(lnk_data.rect), x, y, w, h);	
				if(error_count==0)
				{
					  distance=(int)(max_Y[x+h/2]-(y+h/2));
				}
				else if(error_count>0&&count>3)
				{
					 distance=(int)(a*(x+h/2)*(x+h/2)+b*(x+h/2)+c-(y+h/2));
				}
				//mp_printf(&mp_plat_print, "dis= %d\n", distance);
				if(distance>80)//离赛道较远的卡片忽略(防止环岛卡片离道路过近)
				{
					fb_free();
					fb_free();
					fb_free();
					fb_free();
					fb_free();
					fb_free();
					break;
				}
				list_push_back(out, &lnk_data);
				fb_free();
				fb_free();
				fb_free();
				fb_free();
				fb_free();
				fb_free();
				break;
    }

这里有一个for循环,是为了解决黑胶宽度不均匀的问题,因为我是在找到下面的线的基础上向上平移指定距离,所以鲁棒性不高,加入该段代码牺牲了算法速度,但是提高了一定的鲁棒性。但是我觉得这段代码写的还是很粗略,改进的空间很大。

(4).art与rt1064的通讯

import pyb
import sensor, image, time, math
import os, tf
from machine import UART
######此为老车右sd卡main函数
pi=3.1415926
NET_SIZE = 80#网络大小
BORDER_WIDTH = (NET_SIZE + 9) // 10
CROP_SIZE = NET_SIZE + BORDER_WIDTH * 2
pic_x=160#标准的中心坐标
pic_y=120
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA) # we run out of memory if the resolution is much bigger...
sensor.set_brightness(800)
sensor.skip_frames(time = 20)
sensor.set_auto_gain(False)  # must turn this off to prevent image washout...
sensor.set_auto_whitebal(False,(0,0,0))  # must turn this off to prevent image washout...
sensor.set_auto_exposure(False)
uart = UART(1, baudrate=115200)     # 初始化串口 波特率设置为115200 TX是B12 RX是B13
do_classify=False
do_line = False
rect_flag = False
model_select=False
#255是蓝色b阈值,看场上情况调整(已经废除不用),这个主要是和rt1064通信的部分,用来区分环岛和常规元素
rect_select=12550#检查是否为12550
clock = time.clock()
net_path1 = "kapian.tflite"
labels1 = [line.rstrip() for line in open("/sd/lables_kapian.txt")]
net_path2 = "zimu.tflite"
labels2 = [line.rstrip() for line in open("/sd/lables_zimu.txt")]
net1 = tf.load(net_path1, load_to_fb=True)
net2 = tf.load(net_path2, load_to_fb=True)
#20是黑胶宽度,0,1,2调试选项,0的话是正常跑的时候,1是显示图像中的蓝色白色和黑色,一定要确保符合实际,有部分噪点也不影响,一般不会有,2是显示提取的线,一般换场地跑前会全检查一下
threshold=200#检查是否为200
result_index=-1
count=0
def check_a_b(a,b,k):

    if(a-b<=k and a-b>=-k):
        return 1
    else:
        return 0

#计算两点角度值
def get_point_point_angle(p0,p1):
    x1,y1=p0
    x2,y2=p1
    if(y2!=y1):
        theta=math.atan((x2-x1)/(y2-y1))
        theta=theta/pi*180
        return int(theta)
    return 0

#矩形四点获取距离
def get_distance(p0,p1,p2,p3):
    x1,y1=p0
    x2,y2=p1
    x3,y3=p2
    x4,y4=p3

    dis1=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)#得到距离
    dis2=(x2-x3)*(x2-x3)+(y2-y3)*(y2-y3)
    dis3=(x3-x4)*(x3-x4)+(y3-y4)*(y3-y4)
    dis4=(x4-x1)*(x4-x1)+(y4-y1)*(y4-y1)

    dis1=math.sqrt(dis1)
    dis2=math.sqrt(dis2)
    dis3=math.sqrt(dis3)
    dis4=math.sqrt(dis4)

    return int(dis1),int(dis2),int(dis3),int(dis4)

#两点长度计算
def get_point_point_distance(p0, p1):
    line_s_x, line_s_y=p0
    line_e_x, line_e_y=p1
    line_long = math.sqrt(pow(line_s_x - line_e_x, 2) + pow(line_s_y - line_e_y, 2))
    return line_long

#点到直线距离公式
def get_point_line_distance(point, p0, p1):
    point_x = point[0]
    point_y = point[1]
    line_s_x, line_s_y=p0
    line_e_x, line_e_y=p1
    #若直线与y轴平行,则距离为点的x坐标与直线上任意一点的x坐标差值的绝对值
    if line_e_x - line_s_x == 0:
        return math.fabs(point_x - line_s_x)
    #若直线与x轴平行,则距离为点的y坐标与直线上任意一点的y坐标差值的绝对值
    elif line_e_y - line_s_y == 0:
        return math.fabs(point_y - line_s_y)
    else:
        #斜率
        k = (line_e_y - line_s_y) / (line_e_x - line_s_x)
        #截距
        b = line_s_y - k * line_s_x
        #带入公式得到距离dis
        dis = math.fabs(k * point_x - point_y + b) / math.pow(k * k + 1, 0.5)
        return dis
# 这个示例演示如何加载tflite模型并运行
# 这个示例演示如何加载tflite模型并运行
# 这个示例演示如何加载tflite模型并运行
while(True):
    clock.tick()
    msg=uart.read()
    #print(msg)
    rect_flag=False
    do_classify = b"\xf4" in msg or do_classify
    if(b"\xf5" in msg):
        model_select=not model_select
    if(b"\xf5" in msg):
        rect_select=(int)(257-rect_select/10000)*10000+rect_select%10000;
    if(b"\xd3" in msg):
        rect_select = (int)(1 - rect_select % 10) + (int)(rect_select / 10) * 10;
    img = sensor.snapshot()
    for r in img.find_rects(threshold = threshold,quality = rect_select):             # 在图像中搜索矩形
        rect_flag=True
        img_x=(int)((r.rect()[0]+r.rect()[2]/2)/2)              # 图像中心的x值
        img_y=(int)((r.rect()[1]+r.rect()[3]/2)/2)            # 图像中心的y值
        p0, p1, p2, p3 = r.corners()
        dis1, dis2, dis3, dis4 = get_distance(p0, p1, p2, p3)
        blob_angle = get_point_point_angle(p1, p2)
        x_error = img_x - pic_x
        y_error = img_y - pic_y
        #print("img_x:" + str(r.rect()[0]) + ",img_y:" + str(r.rect()[3])+","+str(blob_angle))
        if (x_error < 0):
            x_flag = 0  # 正负标志位
            x_error = -x_error
        else:
            x_flag = 1

        if (y_error < 0):
            y_flag = 0  # 正负标志位
            y_error = -y_error
        else:
            y_flag = 1
        uart_array1 = bytearray([0XE1,0xE2,x_error,y_error,x_flag,y_flag,blob_angle,0XE3])
        uart.write(uart_array1)
        if do_classify:
            corners = r.corners()
            img.rotation_corr(x_translation=CROP_SIZE, y_translation=CROP_SIZE, corners=corners)
            if model_select:
                obj=net2.classify(img,roi=(BORDER_WIDTH, BORDER_WIDTH, NET_SIZE, NET_SIZE))[0]
                res=obj.output()
                m=max(res)
                result_index=labels2[res.index(m)]
                uart_array2 = bytearray([0XBF,0XBF])#没有识别出任何东西
                if result_index== '1':#1
                    uart_array2 = bytearray([0XBF,0xB0])
                if result_index == '2':#2
                    uart_array2 = bytearray([0XBF,0xB1])
                if result_index == '3':#3
                    uart_array2 = bytearray([0XBF,0xB2])

                if result_index == 'A':#A
                    uart_array2 = bytearray([0XBF,0xC0])
                if result_index == 'B':#B
                    uart_array2 = bytearray([0XBF,0xC1])
                if result_index == 'C':#C
                    uart_array2 = bytearray([0XBF,0xC2])

                if result_index == 'D':#D
                    uart_array2 = bytearray([0XBF,0xC3])
                if result_index == 'E':#E
                    uart_array2 = bytearray([0XBF,0xC4])
                if result_index == 'F':#F
                    uart_array2 = bytearray([0XBF,0xC5])

                if result_index == 'G':#G
                    uart_array2 = bytearray([0XBF,0xC6])
                if result_index == 'H':#H
                    uart_array2 = bytearray([0XBF,0xC7])
                if result_index == 'I':#I
                    uart_array2 = bytearray([0XBF,0xC8])

                if result_index == 'J':#J
                    uart_array2 = bytearray([0XBF,0xC9])
                if result_index == 'K':#K
                    uart_array2 = bytearray([0XBF,0xCA])
                if result_index == 'L':#L
                    uart_array2 = bytearray([0XBF,0xCB])

                if result_index == 'M':#M
                    uart_array2 = bytearray([0XBF,0xCC])
                if result_index == 'N':#N
                    uart_array2 = bytearray([0XBF,0xCD])
                if result_index == 'O':#O
                    uart_array2 = bytearray([0XBF,0xCE])
                #print("1")
                #print("%s: %f" % (result_index, m))
                uart.write(uart_array2)
                do_classify=False
            else:
                obj=net1.classify(img,roi=(BORDER_WIDTH, BORDER_WIDTH, NET_SIZE, NET_SIZE))[0]
                res=obj.output()
                m=max(res)
                result_index=labels1[res.index(m)]
                uart_array2 = bytearray([0XBF,0XBF])#没有识别出任何东西
                #中0
                if result_index== 'firearms':#枪
                    uart_array2 = bytearray([0XBF,0xA0])
                if result_index == 'explosive':#炸弹
                    uart_array2 = bytearray([0XBF,0xA1])
                if result_index == 'dagger':#匕首
                    uart_array2 = bytearray([0XBF,0xA2])
                #上1
                if result_index == 'spontoon':#警棍
                    uart_array2 = bytearray([0XBF,0xA3])
                if result_index == 'fire_axe':#消防斧
                    uart_array2 = bytearray([0XBF,0xA4])
                if result_index == 'first_aid_kit':#急救包
                    uart_array2 = bytearray([0XBF,0xA5])
                #下2
                if result_index == 'flashlight':#手电筒
                    uart_array2 = bytearray([0XBF,0xA6])
                if result_index == 'intercom':#bb机
                    uart_array2 = bytearray([0XBF,0xA7])
                if result_index == 'bulletproof_vest':#防弹衣
                    uart_array2 = bytearray([0XBF,0xA8])
                #左3
                if result_index == 'telescope':#望远镜
                    uart_array2 = bytearray([0XBF,0xA9])
                if result_index == 'helmet':#头盔
                    uart_array2 = bytearray([0XBF,0xAA])
                if result_index == 'fire_engine':#救火车
                    uart_array2 = bytearray([0XBF,0xAB])
                #右4
                if result_index == 'ambulance':#救护车
                    uart_array2 = bytearray([0XBF,0xAC])
                if result_index == 'armoured_car':#装甲车
                    uart_array2 = bytearray([0XBF,0xAD])
                if result_index == 'motorcycle':#摩托车
                    uart_array2 = bytearray([0XBF,0xAE])
                #print("2")
                #print("%s: %f" % (result_index, m))
                uart.write(uart_array2)
                do_classify=False
        img.draw_rectangle(r.rect(), color = (255, 255, 255))

总结

工程已经上传github,地址https://github.com/gameworld11/openart.git,有问题可以留言,在我能力范围的我会尽力解答。

  • 18
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值