感谢@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(" 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显示数字
有什么错误的地方,望指正。
谢谢大家!!!!