【GD32450I-EVAL】+ 08图像识别-彩色物体跟踪
本帖最后由 DDZZ669 于 2020-10-8 21:34 编辑<p cid="n0" mdtype="paragraph"> 上篇文章<a href="https://bbs.eeworld.com.cn/thread-1143651-1-1.html" target="_blank">【GD32450I-EVAL】+ 07摄像头全屏显示测试</a>介绍了摄像头的使用,本篇利用摄像头采集的图像,进行简单的图像识别,借助EasyTrace彩色物体检测算法,实现对彩色物体的跟踪检测。</p>
<p cid="n2" mdtype="paragraph"> 先看一下最终的效果:</p>
<p></p>
<p> </p>
<h1 cid="n4" mdtype="heading">1 EasyTrace简介</h1>
<p cid="n5" mdtype="paragraph">使用EasyTrace可以对单一颜色物体进行实时跟踪识别。</p>
<h2 cid="n6" mdtype="heading">1.1 EasyTrace特点</h2>
<p cid="n7" mdtype="paragraph" style="margin-left: 40px;">1.代码只有300行,非常简单</p>
<p cid="n8" mdtype="paragraph" style="margin-left: 40px;">2.识别一次只需要2至5毫秒,实时性强</p>
<p cid="n9" mdtype="paragraph" style="margin-left: 40px;">3.只有1个API,使用方便</p>
<p cid="n10" mdtype="paragraph" style="margin-left: 40px;">4.可配置”容错率“ ”迭代次数“等参数,可在”时间“实时性”“ ”准确度“ ”识别率“ ”误识率“ 之间寻找平衡点</p>
<h2 cid="n11" mdtype="heading">1.2 使用举例</h2>
<p cid="n12" mdtype="paragraph"> 使用EasyTrace,首先需要自己提供一个指定位置的颜色读取函数:</p>
<pre>
<code class="language-cpp">//读取RBG格式颜色,唯一需要移植的函数
extern unsigned short GUI_ReadBit16Point(unsigned short x,unsigned short y);</code></pre>
<p> </p>
<p> 然后使用如下3行就可以识别彩色物体了:</p>
<pre>
<code class="language-cpp">RESULT Resu;//识别的结果
TARGET_CONDI Condition={60,100,20,120,10,160,40,40,320,240};//识别的条件
Trace(&Condition,&Resu);//彩色物体检测API</code></pre>
<p> </p>
<p> 识别条件与识别结果的结构体定义为:</p>
<pre>
<code class="language-cpp">typedef struct{
unsigned charH_MIN;//目标最小色调
unsigned charH_MAX;//目标最大色调
unsigned charS_MIN;//目标最小饱和度
unsigned charS_MAX;//目标最大饱和度
unsigned charL_MIN;//目标最小亮度
unsigned charL_MAX;//目标最大亮度
unsigned intWIDTH_MIN;//目标最小宽度
unsigned intHIGHT_MIN;//目标最小高度
unsigned intWIDTH_MAX;//目标最大宽度
unsigned intHIGHT_MAX;//目标最大高度
}TARGET_CONDI;//判定为的目标条件
typedef struct{
unsigned int x;//目标的x坐标
unsigned int y;//目标的y坐标
unsigned int w;//目标的宽度
unsigned int h;//目标的高度
}RESULT;//识别结果
//这里是图像搜索范围的定义
#define IMG_X 0 //图片x坐标
#define IMG_Y 0 //图片y坐标
#define IMG_W 480 //图片宽度
#define IMG_H 272 //图片高度</code></pre>
<h1 cid="n18" mdtype="heading"> </h1>
<h1 cid="n18" mdtype="heading">2 HSL色彩空间</h1>
<p cid="n19" mdtype="paragraph"> EasyTrace识别彩色物体使用的是HSL色彩空间,即色调,饱和度,亮度。</p>
<p> <strong>色调(Hue)</strong>是色彩的基本属性,就是平常所说的颜色名称,如红色、黄色等。</p>
<p></p>
<p> <strong>饱和度(Saturation</strong>)是指色彩的纯度,越高色彩越纯,低则逐渐变灰。</p>
<p></p>
<p> <strong>亮度(Lightness)</strong>是指颜色的明亮程度。</p>
<p></p>
<p> 关于色彩空间的具体细节,可以参考知乎问答: <a href="https://www.zhihu.com/question/22077462" target="_blank">色彩空间中的 HSL、HSV、HSB 有什么区别?</a></p>
<p> </p>
<h1 cid="n33" mdtype="heading">3 EasyTrace移植</h1>
<h2 cid="n34" mdtype="heading">3.1 GUI_ReadBit16Point函数</h2>
<p cid="n35" mdtype="paragraph"> EasyTrace仅仅只有一个c文件和一个h文件,添加到自己的工程中即可,对于需要自己提供的“GUI_ReadBit16Point()"函数,资料例程中有一个lcd_point_get函数可以直接使用,封装一下即可:</p>
<pre>
<code class="language-cpp">//用于EasyTracer
unsigned short GUI_ReadBit16Point(unsigned short x,unsigned short y)
{
return lcd_point_get(x,y);
}</code></pre>
<h2 cid="n37" mdtype="heading"> </h2>
<h2 cid="n37" mdtype="heading">3.2 颜色阈值确定</h2>
<p cid="n38" mdtype="paragraph"> 本实验准备识别蓝色物体,但蓝色物体的HSL值如何确定呢,一种方法是网上查找蓝色对于的HSL的值,另一种方式是直接用摄像头拍摄要识别的物体,并通过程序将RGB转换为HSL,因为EasyTrace里有现成的颜色转换函数,我们改造一下来用:</p>
<pre>
<code class="language-cpp">while (1)
{
ReadColor(50,50,&testRGB);
RGBtoHSL(&testRGB,&testHSL);
printf("H=%d,S=%d,L=%d\r\n",testHSL.hue,testHSL.saturation,testHSL.luminance);
}</code></pre>
<p> </p>
<p cid="n40" mdtype="paragraph"> 上面的我程序的主函数,摄像头采集的图像显示在LCD上,将要识别的物体放到摄像头前面,并使物体的中心大致位于(50,50)的位置,然后读取该位置的像素值,并转换为HSL,通过串口输出,这样,就能确定要识别的物体的HSL的大致范围了。</p>
<p cid="n40" mdtype="paragraph"> </p>
<h2 cid="n41" mdtype="heading">3.3 物体识别</h2>
<p cid="n42" mdtype="paragraph"> 然后,就是写一个识别与画矩形圈住物体的函数:</p>
<pre>
<code class="language-cpp"> while (1)
{
if(Trace(&Condition1,&Resut)) //检测到了物体
{
if((lastResut.x!=Resut.x)&&(lastResut.y!=Resut.y)&&(lastResut.w!=Resut.w)&&(lastResut.h!=Resut.h))
{
lastResut.x = Resut.x;
lastResut.y = Resut.y;
lastResut.w = Resut.w;
lastResut.h = Resut.h;
lcd_layer_set(LCD_LAYER_FOREGROUND); //指定当前层为前景层(识别到物体后,在前景层画矩形块)
lcd_clear(LCD_COLOR_CYAN);//ARGB155模式下,LCD_COLOR_CYAN就是透明色
lcd_rectangle_line(lastResut.x-(lastResut.w/2),lastResut.y-(lastResut.h/2),lastResut.w,lastResut.h); //画矩形框
lcd_layer_set(LCD_LAYER_BACKGROUND); //再切换到背景层,用于物体识别(摄像头的图像在背景层显示)
}
delay_1ms(100);
}
else //没有检测到
{
delay_1ms(100);
if(10 == ++t) //等了1秒一直没检测到
{
t=0;
lcd_layer_set(LCD_LAYER_FOREGROUND);
lcd_clear(LCD_COLOR_CYAN); //清屏 (清除上次的矩形框块)
lcd_layer_set(LCD_LAYER_BACKGROUND);
}
}
}</code></pre>
<p> </p>
<p cid="n44" mdtype="paragraph"> 这个程序中,摄像头的图像在背景层显示,识别到物体后,在前景层画矩形框,因为前景层使用了ARGB1555这种带透明度的格式,所以虽然有前景层,也能看到摄像头的图像,关于液晶屏的分层显示,可以先参考:<a href="https://bbs.eeworld.com.cn/thread-1141942-1-1.html" target="_blank">【GD32450I-EVAL】+ 04液晶屏层叠显示与透明度调整测试</a></p>
<p cid="n45" mdtype="paragraph"> </p>
<h1 cid="n46" mdtype="heading">4 物体识别效果展示</h1>
<p cid="n47" mdtype="paragraph"> 演示视频:</p>
<p cid="n47" mdtype="paragraph"><iframe allowfullscreen="true" frameborder="0" height="450" src="//player.bilibili.com/player.html?bvid=1pf4y1B71S&page=1" style="background:#eee;margin-bottom:10px;" width="750"></iframe><br />
</p>
<p>感谢分享!!!</p>
<p>感谢分享</p>
<p>感谢分享</p>
<p><a href="https://bbs.eeworld.com.cn/thread-1140981-1-1.html" target="_blank">兆易GD32450I-EVAL</a></p>
<p>汇总贴:<a href="https://bbs.eeworld.com.cn/thread-1140981-1-1.html">https://bbs.eeworld.com.cn/thread-1140981-1-1.html</a></p>
页:
[1]