赞
踩
感谢@AD1617681854的博客代码及@海喂喂喂的帮助
参考代码(29条消息) 基于openmv的多色块识别并返回色块顺序_Ding_YF的博客-CSDN博客
一:颜色阈值
打开示例helloworld.py文件,运行openmv,在帧缓冲区放置需要颜色的物品,打开机器视觉,打开阈值编辑器,选择帧缓冲区,将目标颜色调白,其他调黑。复制LAB阈值。
二:openmv代码
- import sensor, image, time #引入三个库
- from pyb import UART
-
- red = (21, 61, 9, 127, -2, 127) ###
- green = (9, 87, -67, -11, -18, 66) ## 定义三个颜色的lab值范围格式为(Lmax,Lmin,Amax,Amin,Bmax,Bmin)
- blue = (25, 85, 101, -104, -14, -41) # 以及一个颜色组colour
- colour = [red,green,blue] ### 对应颜色的lab阈值信息,可以通过IDE中的工具→机器视觉→阈值编辑器自行调整和获取
-
- red_blob = None ## 定义三个空的变量,用来盛放下面寻找到的色块的信息
- green_blob = None ## 定义三个空的变量,用来盛放下面寻找到的色块的信息
- blue_blob = None # 以及定义一个色块组blobs_group
- blobs_group = [red_blob,green_blob,blue_blob] ###
-
-
- sensor.reset() #初始化相机传感器
- sensor.set_pixformat(sensor.RGB565) #设置相机模块的像素模式,16 bits/像素
- sensor.set_framesize(sensor.QVGA) #设置相机模块的帧大小 320x240
- sensor.skip_frames(time = 2000) #
- sensor.set_auto_gain(False) #打开(True)或关闭(False)自动增益
- sensor.set_auto_whitebal(False) #打开(True)或关闭(False)自动白平衡,追踪颜色,则需关闭白平衡
- clock = time.clock() ###
-
- uart = UART(3,9600) #定义串口3变量
- uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters
-
- def sending_data(cx,cy,cw,ch): #定义发送数据的串口函数
- global uart;
- #frame=[0x2C,18,cx%0xff,int(cx/0xff),cy%0xff,int(cy/0xff),0x5B];
- #data = bytearray(frame)
- data = ustruct.pack("<bbhhhhb", #格式为俩个字符俩个短整型(2字节)
- 0x2C, #帧头1
- 0x12, #帧头2
- int(cx), # up sample by 4 #数据1
- int(cy), # up sample by 4 #数据2
- int(cw), # up sample by 4 #数据1
- int(ch), # up sample by 4 #数据2
- 0x5B)
- uart.write(data); #必须要传入一个字节数组
-
- def Find_group(): ###定义寻找色块的函数
- t = 0 ## 这里是重点,定义一个发现色块组的函数
- while t < 3: # find_blobs函数会寻找对应阈值内颜色的色块,例如t=0时寻找的是红色,并将
- blobs_group[t] = img.find_blobs([colour[t]]) # 它找的信息赋值给blobs_group中的red_blobl
- if len(blobs_group[t]) > 0: # 判断是否找到色块,找到色块会对色块进行一系列操作
- for b in blobs_group[t]: # 先判断色块的b[4],即像素数,对应的b几代表什么可以在星瞳科技的'10分钟快速上手'里找到
- if 12000 > b[4] > 3000: # 利用画图函数,根据寻找到的色块的信息,分别画出外边框,中心十字,在左上角写对应色块的名称
- img.draw_rectangle(b[0:4]) # 然后将b[5]追加到tool中储存起来。最后会让t+1,就会对绿色的色块进行这一系列操作
- img.draw_cross(b[5], b[6]) # 这个函数的目的就是依次寻找红绿蓝色块
- #img.draw_string(b[0], b[1])
- print(colour[t]) #找到之后打印出来色块的阈值
- print(t+1) #打印出色块的数字
- #串口的程序
- Num = t + 1
- FH = bytearray([0x2C,0x12,Num,0, 0, 0,0x5B])
- uart.write(FH)
-
- t+=1
-
- while (True): ###
- clock.tick() ## 这是一个大的循环,可以说前面的都是准备工作,主要是为这个循环
- img = sensor.snapshot() # 逻辑是,抓取画面,然后用前面定义的好的Find_group函数抓取出画面中的色块
-
- Find_group() #调用寻找色块的函数
-
-
- #blob.x() 返回色块的外框的x坐标(int),也可以通过blob[0]来获取。
-
- #blob.y() 返回色块的外框的y坐标(int),也可以通过blob[1]来获取。
-
- #blob.w() 返回色块的外框的宽度w(int),也可以通过blob[2]来获取。
-
- #blob.h() 返回色块的外框的高度h(int),也可以通过blob[3]来获取。
-
- #blob.pixels() 返回色块的像素数量(int),也可以通过blob[4]来获取。
-
- #blob.cx() 返回色块的外框的中心x坐标(int),也可以通过blob[5]来获取。
-
- #blob.cy() 返回色块的外框的中心y坐标(int),也可以通过blob[6]来获取。
-
-
-
-
三:stm32代码
1.设置CubeMx
我使用的是串口三,也可以设置其他的。
2.在main函数添加接收串口中断函数
HAL_UART_Receive_IT(&huart3,&uart3_rxbuff,1);//openmv通信串口
3.openmv代码及接收中断回调函数
- #include "openmv.h"
- #include "usart.h"
- #include "gpio.h"
- #include "stm32f1xx.h"
-
- int GetOpenmvDataCount = 0;
-
- uint8_t uart3_rxbuff;
- uint8_t Num=0, LoR =0, Finded_flag = 0, FindTask = 0; //()
-
-
-
- void Openmv_Receive_Data(uint8_t com_data)
- {
- uint8_t i;
- static uint8_t RxCounter1=0;//计数
- static uint16_t RxBuffer1[10]={0};
- static uint8_t RxState = 0;
- static uint8_t RxFlag1 ;
-
- if(RxState==0&&com_data==0x2C) //0x2c帧头
- {
-
- RxState=1;
- RxBuffer1[RxCounter1++]=com_data;
- }
-
- else if(RxState==1&&com_data==0x12) //0x12帧头
- {
- RxState=2;
- RxBuffer1[RxCounter1++]=com_data;
- }
-
- else if(RxState==2)
- {
-
- RxBuffer1[RxCounter1++]=com_data;
- if(RxCounter1>=10||com_data == 0x5B) //RxBuffer1接受满了,接收数据结束
- {
- RxState=3;
- RxFlag1=1;
-
- //正常情况下,运行到这RxCounter1 == 7? 7-5 = 2 openmv发送过来的一个数据包有8个
- Num = RxBuffer1[RxCounter1-5]; //2
- LoR = RxBuffer1[RxCounter1-4]; //3 //-1是左, 1是右,0表示还没有识别到任何数字
- Finded_flag = RxBuffer1[RxCounter1-3]; //4
- FindTask = RxBuffer1[RxCounter1-2];//5
-
- //RxCounter1-1是帧尾
-
- //greenLED_Toggle; //用来看是否接收数据的,电平翻转一次则成功接收一个数据,跟下面的一个意思
- GetOpenmvDataCount++;
- //用来看1秒内成功解码多少个数据包的 需要在1s钟的延时中清除,帧率越高越准确,个位数的话偏差就大了
- //不如改一下解码代码,将openmv那里的帧率直接传过来
-
- }
- }
-
- else if(RxState==3) //检测是否接受到结束标志
- {
- if(RxBuffer1[RxCounter1-1] == 0x5B)
- {
-
- RxFlag1 = 0;
- RxCounter1 = 0;
- RxState = 0;
-
- }
- else //接收错误
- {
- RxState = 0;
- RxCounter1=0;
- for(i=0;i<10;i++)
- {
- RxBuffer1[i]=0x00; //将存放数据数组清零
- }
- }
- }
-
- else //接收异常
- {
- RxState = 0;
- RxCounter1=0;
- for(i=0;i<10;i++)
- {
- RxBuffer1[i]=0x00; //将存放数据数组清零
- }
- }
- }
-
-
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
- {
-
-
- uint8_t tem;// 这里的是无符号的
-
- //RedSignal_Toggle; //用来看是否接收数据的, 这里要随时都没效果的话就代表连串口3的中断都没进来
- if(huart->Instance== USART3) //这里只能这样大写USART3
- {
-
- //RedSignal_Toggle; //用来看是否接收数据的, 这里要随时都没效果的话就代表连串口3的中断都没进来
-
- tem=uart3_rxbuff;
- Openmv_Receive_Data(tem);
-
- }
- HAL_UART_Receive_IT(&huart3,&uart3_rxbuff,1);
-
- }
四:成果展示
stm32部分用oled显示数字
有什么错误的地方,望指正。
谢谢大家!!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。