用OpenMV自动识别颜色序列

新年假期过去啦~

主控:OpenMV3 M7摄像头(STM32F765)

IDE:OPENMV官方IDE

我将Capstone期间做的代码上传到Gitee啦,后续还会陆续上传代码上去的,地址:Capstone,如果对你有帮助的话不妨点个支持一下~

OpenMV需要识别颜色顺序的位置是第一个区域,区域中的物料摆放如下图所示

对于OpenMV识别颜色,很大一部分人都是采用了使用阈值调节,通过拍回来的照片修改阈值得到想要的区域,这种情况一般都会存在调试时间长,受光照影响大的限制。

通过分析本项目的颜色识别部分,小车到达粗加工区后开始颜色识别,识别到序列之后在开始抓取,车子在识别颜色时的位置是大致不变的,所以本文将阈值->颜色识别的流程转化为区域->颜色的识别,可以减少调试时间,但解决不了受光照影响的问题。

OpenMV使用的是LAB色域,如下图所示

根据任务要求,物料颜色分别有红绿蓝三色,则对上图进行观察对比,可以发现红绿蓝三色均在球形的外端,有非明显的区别,比如红色的a值为正数蓝色的b值为负数绿色的a值为负数。因此可以根据这些特征筛选出所需颜色。

在实际运行过程中,我们将OpenMV的画面分成上下两部分,然后在每次运行到粗加工区位置时都运行一遍识别程序,避免因颜色识别不全卡在粗加工区。

在此处放出获取区域颜色的代码

function:GetColor

def GetColor(Rev_Num):
global Left_x
global Middle_x
global Right_x
global Left_y
global Middle_y
global Right_y
global LeftMean_Shang
global MiddleMean_Shang
global RightMean_Shang
global LeftMean_Xia
global MiddleMean_Xia
global RightMean_Xia
if (Rev_Num == 1):
#获取左中右三个位置的X坐标和Y坐标
Left_x = LeftROI_Shang[0] + (LeftROI_Shang[2] / 2)
Middle_x = MiddleROI_Shang[0] + (MiddleROI_Shang[2] / 2)
Right_x = RightROI_Shang[0] + (RightROI_Shang[2] / 2)
Left_y = LeftROI_Shang[1] + (LeftROI_Shang[3] / 2)
Middle_y = MiddleROI_Shang[1] + (MiddleROI_Shang[3] / 2)
Right_y = RightROI_Shang[1] + (RightROI_Shang[3] / 2)
for i in range(100):
img = sensor.snapshot()
img.draw_rectangle(LeftROI_Shang)
img.draw_rectangle(MiddleROI_Shang)
img.draw_rectangle(RightROI_Shang)
img.draw_cross(int(Left_x), int(Left_y))
img.draw_cross(int(Middle_x), int(Middle_y))
img.draw_cross(int(Right_x), int(Right_y))
Left_Stat = img.get_statistics(roi = LeftROI_Shang)
Middle_Stat = img.get_statistics(roi = MiddleROI_Shang)
Right_Stat = img.get_statistics(roi = RightROI_Shang)
#获取上层左侧ROI的LAB均值
LeftMean_Shang[0] = LeftMean_Shang[0] + (Left_Stat.l_mean() / 100)
LeftMean_Shang[1] = LeftMean_Shang[1] + (Left_Stat.a_mean() / 100)
LeftMean_Shang[2] = LeftMean_Shang[2] + (Left_Stat.b_mean() / 100)
#获取上层中间ROI的LAB均值
MiddleMean_Shang[0] = MiddleMean_Shang[0] + (Middle_Stat.l_mean() / 100)
MiddleMean_Shang[1] = MiddleMean_Shang[1] + (Middle_Stat.a_mean() / 100)
MiddleMean_Shang[2] = MiddleMean_Shang[2] + (Middle_Stat.b_mean() / 100)
#获取上层右侧ROI的LAB均值
RightMean_Shang[0] = RightMean_Shang[0] + (Right_Stat.l_mean() / 100)
RightMean_Shang[1] = RightMean_Shang[1] + (Right_Stat.a_mean() / 100)
RightMean_Shang[2] = RightMean_Shang[2] + (Right_Stat.b_mean() / 100)
elif (Rev_Num == 2):
#获取左中右三个位置的X坐标和Y坐标
Left_x = LeftROI_Xia[0] + (LeftROI_Xia[2] / 2)
Middle_x = MiddleROI_Xia[0] + (MiddleROI_Xia[2] / 2)
Right_x = RightROI_Xia[0] + (RightROI_Xia[2] / 2)
Left_y = LeftROI_Xia[1] + (LeftROI_Xia[3] / 2)
Middle_y = MiddleROI_Xia[1] + (MiddleROI_Xia[3] / 2)
Right_y = RightROI_Xia[1] + (RightROI_Xia[3] / 2)
for i in range(100):
img = sensor.snapshot()
img.draw_rectangle(LeftROI_Xia)
img.draw_rectangle(MiddleROI_Xia)
img.draw_rectangle(RightROI_Xia)
img.draw_cross(int(Left_x), int(Left_y))
img.draw_cross(int(Middle_x), int(Middle_y))
img.draw_cross(int(Right_x), int(Right_y))
Left_Stat = img.get_statistics(roi = LeftROI_Xia)
Middle_Stat = img.get_statistics(roi = MiddleROI_Xia)
Right_Stat = img.get_statistics(roi = RightROI_Xia)
#获取下层左侧ROI的LAB均值
LeftMean_Xia[0] = LeftMean_Xia[0] + (Left_Stat.l_mean() / 100)
LeftMean_Xia[1] = LeftMean_Xia[1] + (Left_Stat.a_mean() / 100)
LeftMean_Xia[2] = LeftMean_Xia[2] + (Left_Stat.b_mean() / 100)
#获取下层中间ROI的LAB均值
MiddleMean_Xia[0] = MiddleMean_Xia[0] + (Middle_Stat.l_mean() / 100)
MiddleMean_Xia[1] = MiddleMean_Xia[1] + (Middle_Stat.a_mean() / 100)
MiddleMean_Xia[2] = MiddleMean_Xia[2] + (Middle_Stat.b_mean() / 100)
#获取下层右侧ROI的LAB均值
RightMean_Xia[0] = RightMean_Xia[0] + (Right_Stat.l_mean() / 100)
RightMean_Xia[1] = RightMean_Xia[1] + (Right_Stat.a_mean() / 100)
RightMean_Xia[2] = RightMean_Xia[2] + (Right_Stat.b_mean() / 100)

简单介绍一下函数,函数内容挺简单的,将画面中三个区域中的LAB阈值提出来做均分再相加,就得到了三个区域中L、A、B三个通道的颜色均值,后面再做对比就行

还有调试用的函数,这个函数是用来调试找到三个区域的

function:Get_ROI

def Get_ROI(Rev_Num):
global Left_x
global Middle_x
global Right_x
global Left_y
global Middle_y
global Right_y
if (Rev_Num == 1):
#裁剪窗口
sensor.set_windowing(ROI_Shang)
#获取左中右三个位置的X坐标和Y坐标
Left_x = LeftROI_Shang[0] + (LeftROI_Shang[2] / 2)
Middle_x = MiddleROI_Shang[0] + (MiddleROI_Shang[2] / 2)
Right_x = RightROI_Shang[0] + (RightROI_Shang[2] / 2)
Left_y = LeftROI_Shang[1] + (LeftROI_Shang[3] / 2)
Middle_y = MiddleROI_Shang[1] + (MiddleROI_Shang[3] / 2)
Right_y = RightROI_Shang[1] + (RightROI_Shang[3] / 2)
img = sensor.snapshot()
img.draw_rectangle(LeftROI_Shang)
img.draw_rectangle(MiddleROI_Shang)
img.draw_rectangle(RightROI_Shang)
img.draw_cross(int(Left_x), int(Left_y))
img.draw_cross(int(Middle_x), int(Middle_y))
img.draw_cross(int(Right_x), int(Right_y))
elif (Rev_Num == 2):
#裁剪窗口
#sensor.set_windowing(ROI_Xia)
#获取左中右三个位置的X坐标和Y坐标
Left_x = LeftROI_Xia[0] + (LeftROI_Xia[2] / 2)
Middle_x = MiddleROI_Xia[0] + (MiddleROI_Xia[2] / 2)
Right_x = RightROI_Xia[0] + (RightROI_Xia[2] / 2)
Left_y = LeftROI_Xia[1] + (LeftROI_Xia[3] / 2)
Middle_y = MiddleROI_Xia[1] + (MiddleROI_Xia[3] / 2)
Right_y = RightROI_Xia[1] + (RightROI_Xia[3] / 2)
img = sensor.snapshot()
img.draw_rectangle(LeftROI_Xia)
img.draw_rectangle(MiddleROI_Xia)
img.draw_rectangle(RightROI_Xia)
img.draw_cross(int(Left_x), int(Left_y))
img.draw_cross(int(Middle_x), int(Middle_y))
img.draw_cross(int(Right_x), int(Right_y))

完整的代码发在了Gitee上

程序的运行结果如下图,可以成功的识别得到颜色的序列

手上没有openmv,测试图就这一张

用OpenMV自动识别颜色序列的更多相关文章

  1. cojs 疯狂的魔法树 疯狂的颜色序列 题解报告

    疯狂的魔法树 一个各种操作大杂烩的鬼畜数据结构题目 首先我们注意到树的形态是半随机的 我们可以树分块,对树分成若干个块 对于每个块我们维护一个add标记表示增量 维护一个vis标记表示覆盖量 注意标记 ...

  2. 用Arduino显示颜色序列(u8g2,OLED)

    目录 用Arduino显示颜色序列(u8g2,OLED) 用Arduino显示颜色序列(u8g2,OLED) 提前祝大家新年快乐! 主控:Arduino Mega 2560 硬件:126×64 OLE ...

  3. [四校联考P3] 区间颜色众数 (主席树)

    主席树 Description 给定一个长度为 N 颜色序列A,有M个询问:每次询问一个区间里是否有一种颜色的数量超过了区间的一半,并指出是哪种颜色. Input 输入文件第一行有两个整数:N和C 输 ...

  4. Uva 1625,颜色的长度

    类似于LCS的动态规划,指标函数的分解. 题目链接:https://uva.onlinejudge.org/external/16/1625.pdf 题目大意:两个颜色序列,将他们合并,合并的时候,每 ...

  5. shell之echo与printf和颜色

    在用户的bashrc中添加一行export来修改提示符.

  6. bzoj5011: [Jx2017]颜色

    Description 可怜有一个长度为n的正整数序列Ai,其中相同的正整数代表着相同的颜色. 现在可怜觉得这个序列太长了,于是她决定选择一些颜色把这些颜色的所有位置都删去. 删除颜色i可以定义为把所 ...

  7. UVa 1625 颜色的长度

    https://vjudge.net/problem/UVA-1625 题意: 输入两个长度分别为n和m的颜色序列,要求按顺序合并成同一个序列,即每次可以把一个序列开头的颜色放到新序列的尾部.对于每个 ...

  8. opencv产生随机的颜色

    //将HSV颜色空间值转换成RGB值,参考这里cv::Scalar HSV2RGB(const float h, const float s, const float v) { ); - h_i; - ...

  9. [JXOI2017]颜色 线段树求点对贡献

    [JXOI2017]颜色 题目链接 https://www.luogu.org/problemnew/show/P4065 题目描述 可怜有一个长度为 n 的正整数序列 Ai,其中相同的正整数代表着相 ...

随机推荐

  1. .NET程序设计实验三

    实验三  Windows 应用程序开发 一.实验目的 1. 掌握窗口控件的使用方法: 2. 掌握Windows 的编程基础. 二.实验要求 根据要求,编写 C#程序,并将程序代码和运行结果写入实验报告 ...

  2. CCF201709-2公共钥匙盒改进版

    问题描述 有一个学校的老师共用N个教室,按照规定,所有的钥匙都必须放在公共钥匙盒里,老师不能带钥匙回家.每次老师上课前,都从公共钥匙盒里找到自己上课的教室的钥匙去开门,上完课后,再将钥匙放回到钥匙盒中 ...

  3. 关于#pragma 和 _pragma

    首先要明确 #pragma 和_Pragma 是什么 这两个都是出自于c/c++ 的 ,其中#pragma 是预处理指令(preProcess directive ) ,#pragma是用来向编译器传 ...

  4. 【论文阅读】ICLR 2022: Scene Transformer: A unified architecture for predicting future trajectories of multiple agents

    ICLR 2022: Scene Transformer: A unified architecture for predicting future trajectories of multiple ...

  5. Oracle数据库包括两个部分数据库和数据库实例

    olsnodes,这个命令用来显示集群点列表(grid即oracle rac的第三个安装包内的软件,可找到) //集群名称[grid@shdb02 ~]$ olsnodes -cshfpdb-clus ...

  6. linux中find与三剑客之grep用法

    find用法 find一般用来用来查找文件名称 根据文件的名称或者属性查找文件. 语法格式: find [查找范围] [参数] 参数: -name : 按照文件的名字查找文件 * :通配符 -inam ...

  7. 学习打卡——CentOS 7安装

    本来今天是要学习redis的,但是redis官方又不支持在win下运行,windows版本目前都是微软官方在维护.redis最新版都已经更新到7.0了,windows却还是只有3.x版本.所以随性就去 ...

  8. this的指向问题及改变this指向

    概念: this是运行环境下的一个系统变量, 由于this在不同的执行环境下有不同的值, 所以在使用this时,多加注意 (使用this之前,先打印) 1,在全局作用域下,this默认指向window ...

  9. Java实现平滑加权轮询算法--降权和提权

    上一篇讲了普通轮询.加权轮询的两种实现方式,重点讲了平滑加权轮询算法,并在文末留下了悬念:节点出现分配失败时降低有效权重值:成功时提高有效权重值(但不能大于weight值). 本文在平滑加权轮询算法的 ...

  10. python中的嵌套

    嵌套:将一系列字典存储在列表中,或将列表作为值存储在字典中,这称为嵌套.既可以在列表中嵌套字典,也可以在字典中嵌套列表,甚至在字典中嵌套字典. 一.列表中嵌套字典 1)一般创建方式: student_ ...