嗯,玩一玩ov7725摄像头,看到个帖子有关于图像识别的,就想玩玩
stm32驱动ov7670摄像头识别颜色并追踪_木木so的博客-CSDN博客_stm32f103驱动ov7670摄像头参照这位老哥,这位老哥之上还有鼻祖,嗯
在寻常的摄像头刷新图像之后,加上鼻祖的第三方文件库,调用其中的api函数,即可实现腐蚀中心绘制,识别出想要识别的物体中心和方框,嗯,但是物体如果是彩色的,估计就GG了,这个原理就是根据物体的HSL颜色,具体参考链接或者自行百度,HSL比起RGB更容易被机器识别一些。
#include "delay.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"
#include "string.h"
#include "ov7670.h"
#include "timer.h"
#include "exti.h"
#include "ColorTracer.h"
const u8*LMODE_TBL[5]={"Auto","Sunny","Cloudy","Office","Home"}; //5种光照模式
const u8*EFFECTS_TBL[7]={"Normal","Negative","B&W","Redish","Greenish","Bluish","Antique"}; //7种特效
extern u8 ov_sta; //在exit.c里 面定义
extern u8 ov_frame; //在timer.c里面定义
extern volatile uint8_t Ov7725_Vsync;
//更新LCD显示
u8 R,G,B;
void camera_refresh(void)
{
u32 j;
u16 color;
if(ov_sta)//有帧中断更新?
{
LCD_Scan_Dir(U2D_L2R); //从上到下,从左到右
if(lcddev.id==0X1963)LCD_Set_Window((lcddev.width-240)/2,(lcddev.height-320)/2,240,320);//将显示区域设置到屏幕中央
else if(lcddev.id==0X5510||lcddev.id==0X5310)LCD_Set_Window((lcddev.width-320)/2,(lcddev.height-240)/2,320,240);//将显示区域设置到屏幕中央
LCD_WriteRAM_Prepare(); //开始写入GRAM
OV7670_RRST=0; //开始复位读指针
OV7670_RCK_L;
OV7670_RCK_H;
OV7670_RCK_L;
OV7670_RRST=1; //复位读指针结束
OV7670_RCK_H;
for(j=0;j<76800;j++)
{
OV7670_RCK_L;
color=GPIOC->IDR&0XFF; //读数据
OV7670_RCK_H;
color<<=8;
OV7670_RCK_L;
color|=GPIOC->IDR&0XFF; //读数据
OV7670_RCK_H;
LCD->LCD_RAM=color;
}
ov_sta=0; //清零帧中断标记
LCD_Scan_Dir(DFT_SCAN_DIR); //恢复默认扫描方向
}
}
u8 i=0;
int main(void)
{
u8 lightmode=0,saturation=2,brightness=2,contrast=2;
u8 effect=0;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
uart_init(921600); //串口初始化为 115200
LCD_Init(); //初始化LCD
while(OV7670_Init())//初始化OV7670
{
LCD_ShowString(30,230,200,16,16,"OV7670 Error!!");
delay_ms(200);
LCD_Fill(30,230,239,246,WHITE);
delay_ms(200);
}
POINT_COLOR=RED;
LCD_ShowString(30,230,200,16,16,"OV7670 Init OK");
delay_ms(1500);
OV7670_Light_Mode(lightmode);
OV7670_Color_Saturation(saturation);
OV7670_Brightness(brightness);
OV7670_Contrast(contrast);
OV7670_Special_Effects(effect);
TIM6_Int_Init(10000,7199); //10Khz计数频率,1秒钟中断
EXTI8_Init(); //使能定时器捕获
OV7670_Window_Set(12,176,240,320); //设置窗口
OV7670_CS=0;
LCD_Clear(BLACK);
while(1)
{
camera_refresh();//更新显示
if(Ov7725_Vsync == 2)
{
Ov7725_Vsync = 0;
switch(i)
{
case 0:
if(Trace(&condition0, &result))
{
LCD_DrawRectangle ( result.x-result.w/2, result.y-result.h/2, result.x+result.w/2, result.y+result.h/2);
printf("绿色");
}
else
{
i = 1;
}
break;
case 1:
if(Trace(&condition1, &result))
{
LCD_DrawRectangle ( result.x-result.w/2, result.y-result.h/2, result.x+result.w/2, result.y+result.h/2);
printf("蓝色");
}
else
{
i = 2;
}
break;
case 2:
if(Trace(&condition2, &result))
{
LCD_DrawRectangle ( result.x-result.w/2, result.y-result.h/2, result.x+result.w/2, result.y+result.h/2);
printf("紫色");
}
else
{
i = 3;
}
break;
case 3:
if(Trace(&condition3, &result))
{
LCD_DrawRectangle ( result.x-result.w/2, result.y-result.h/2, result.x+result.w/2, result.y+result.h/2);
printf("黑色");
}
else
{
i = 4;
}
break;
case 4:
if(Trace(&condition4, &result))
{
LCD_DrawRectangle ( result.x-result.w/2, result.y-result.h/2, result.x+result.w/2, result.y+result.h/2);
printf("橙色");
}
else
{
i = 5;
}
break;
case 5:
if(Trace(&condition5, &result))
{
LCD_DrawRectangle ( result.x-result.w/2, result.y-result.h/2, result.x+result.w/2, result.y+result.h/2);
printf("黄色");
}
else
{
i = 6;
}
break;
case 6:
if(Trace(&condition6, &result))
{
LCD_DrawRectangle ( result.x-result.w/2, result.y-result.h/2, result.x+result.w/2, result.y+result.h/2);
printf("棕色");
}
else
{
i = 8;
}
break;
// case 7:
// if(Trace(&condition7, &result))
// {
// LCD_DrawRectangle ( result.x-result.w/2, result.y-result.h/2, result.x+result.w/2, result.y+result.h/2);
// //k = 1;
// }
// else
// {
// i = 8;
// }
// break;
case 8:
if(Trace(&condition8, &result))
{
LCD_DrawRectangle ( result.x-result.w/2, result.y-result.h/2, result.x+result.w/2, result.y+result.h/2);
//k = 1;
printf("红色");
}
else
{
i = 0;
}
break;
}
}
}
}
#include "ColorTracer.h"
#include "lcd.h"
RESULT result;
//TARGET_CONDITION condition={50,80,20,250,20,200,40,40,320,240};
//识别的是绿色
TARGET_CONDITION condition0={
60, //目标最小色度,H_MIN
110, //目标最大色度,H_MAX
45, //目标最小饱和度,S_MIN
110, //目标最大饱和度,S_MAX
90, //目标最小亮度,L_MIN
210, //目标最大亮度,L_MAX
40, //目标最小宽度,WIDTH_MIN
40, //目标最小高度,HEIGHT_MIN
240, //目标最大宽度,WIDTH_MAX
320 //目标最大高度,HEIGHT_MAX
};
//蓝色
TARGET_CONDITION condition1={
110, //目标最小色度,H_MIN
150, //目标最大色度,H_MAX
50, //目标最小饱和度,S_MIN
150, //目标最大饱和度,S_MAX
100, //目标最小亮度,L_MIN
200, //目标最大亮度,L_MAX
40, //目标最小宽度,WIDTH_MIN
40, //目标最小高度,HEIGHT_MIN
240, //目标最大宽度,WIDTH_MAX
320 //目标最大高度,HEIGHT_MAX
};
//紫色
TARGET_CONDITION condition2={
160, //目标最小色度,H_MIN
190, //目标最大色度,H_MAX
15, //目标最小饱和度,S_MIN
100, //目标最大饱和度,S_MAX
15, //目标最小亮度,L_MIN
190, //目标最大亮度,L_MAX
40, //目标最小宽度,WIDTH_MIN
40, //目标最小高度,HEIGHT_MIN
240, //目标最大宽度,WIDTH_MAX
320 //目标最大高度,HEIGHT_MAX
};
//黑色
TARGET_CONDITION condition3={
80, //目标最小色度,H_MIN
160, //目标最大色度,H_MAX
10, //目标最小饱和度,S_MIN
100, //目标最大饱和度,S_MAX
10, //目标最小亮度,L_MIN
100, //目标最大亮度,L_MAX
40, //目标最小宽度,WIDTH_MIN
40, //目标最小高度,HEIGHT_MIN
240, //目标最大宽度,WIDTH_MAX
320 //目标最大高度,HEIGHT_MAX
};
//橙色
TARGET_CONDITION condition4={
1, //目标最小色度,H_MIN
40, //目标最大色度,H_MAX
50, //目标最小饱和度,S_MIN
120, //目标最大饱和度,S_MAX
40, //目标最小亮度,L_MIN
220, //目标最大亮度,L_MAX
40, //目标最小宽度,WIDTH_MIN
40, //目标最小高度,HEIGHT_MIN
240, //目标最大宽度,WIDTH_MAX
320 //目标最大高度,HEIGHT_MAX
};
//黄色
TARGET_CONDITION condition5={
20, //目标最小色度,H_MIN
70, //目标最大色度,H_MAX
30, //目标最小饱和度,S_MIN
200, //目标最大饱和度,S_MAX
70, //目标最小亮度,L_MIN
240, //目标最大亮度,L_MAX
40, //目标最小宽度,WIDTH_MIN
40, //目标最小高度,HEIGHT_MIN
240, //目标最大宽度,WIDTH_MAX
320 //目标最大高度,HEIGHT_MAX
};
//棕色
TARGET_CONDITION condition6={
7, //目标最小色度,H_MIN
22, //目标最大色度,H_MAX
1, //目标最小饱和度,S_MIN
55, //目标最大饱和度,S_MAX
1, //目标最小亮度,L_MIN
160, //目标最大亮度,L_MAX
40, //目标最小宽度,WIDTH_MIN
40, //目标最小高度,HEIGHT_MIN
240, //目标最大宽度,WIDTH_MAX
320 //目标最大高度,HEIGHT_MAX
};
//灰白
TARGET_CONDITION condition7={
60, //目标最小色度,H_MIN
170, //目标最大色度,H_MAX
0, //目标最小饱和度,S_MIN
25, //目标最大饱和度,S_MAX
160, //目标最小亮度,L_MIN
220, //目标最大亮度,L_MAX
40, //目标最小宽度,WIDTH_MIN
40, //目标最小高度,HEIGHT_MIN
240, //目标最大宽度,WIDTH_MAX
320 //目标最大高度,HEIGHT_MAX
};
//红色
TARGET_CONDITION condition8={
200, //目标最小色度,H_MIN
240, //目标最大色度,H_MAX
5, //目标最小饱和度,S_MIN
240, //目标最大饱和度,S_MAX
5, //目标最小亮度,L_MIN
240, //目标最大亮度,L_MAX
40, //目标最小宽度,WIDTH_MIN
40, //目标最小高度,HEIGHT_MIN
240, //目标最大宽度,WIDTH_MAX
320 //目标最大高度,HEIGHT_MAX
};
#define minOf3Values( v1, v2, v3 ) ( (v1v2) ? ( (v1>v3) ? (v1) : (v3) ) : ( (v2>v3) ? (v2) : (v3) ) )//取rgb中的最大值
typedef struct //RGB
{
unsigned char Red; // [0,255]
unsigned char Green; // [0,255]
unsigned char Blue; // [0,255]
}COLOR_RGB;
typedef struct //HLS颜色
{
unsigned char Hue; //色度 ,[0,240]
unsigned char Lightness; //亮度,[0,240]
unsigned char Saturation; //饱和度,[0,240]
}COLOR_HLS;
COLOR_HLS h;
typedef struct //搜寻区域
{
unsigned int X_Start;
unsigned int X_End;
unsigned int Y_Start;
unsigned int Y_End;
}SEARCH_AREA;
/**
* @brief 获取 ILI9341 显示器上某一个坐标点的像素数据
* @param usX :在特定扫描方向下该点的X坐标
* @param usY :在特定扫描方向下该点的Y坐标
* @retval 像素数据
*/
//uint16_t ILI9341_GetPointPixel( uint16_t usX, uint16_t usY )
/**
* @brief 读取某一点颜色数据
* @param usX :该点的X坐标
* @param usY :该点的Y坐标
* @param color_rgb :COLOR_RGB结构体,存储颜色数据
* @retval 无
*/
static void ReadColor( uint16_t usX, uint16_t usY, COLOR_RGB* color_rgb )
{
unsigned short rgb;
rgb = LCD_ReadPoint( usX, usY ); //获取颜色数据
//转换成值域为[0,255]的三原色值
color_rgb->Red = (unsigned char)( ( rgb & 0xF800 ) >> 8 );
color_rgb->Green = (unsigned char)( ( rgb & 0x07E0 ) >> 3 );
color_rgb->Blue = (unsigned char)( ( rgb & 0x001F ) << 3 );
//color_rgb->Blue = (unsigned char)( ( rgb & 0x001F ) );
}
/**
* @brief RGB转HLS
* @param color_rgb :COLOR_RGB结构体,存储RGB格式颜色数据
* @param color_hls :COLOR_HLS结构体,存储HLS格式颜色数据
* @retval 无
*/
u8 H,S,L;
static void RGB2HSL( const COLOR_RGB* color_rgb, COLOR_HLS* color_hls )
{
int r, g, b;
int h, l, s;
int max, min, dif;
r = color_rgb->Red;
g = color_rgb->Green;
b = color_rgb->Blue;
max = maxOf3Values( r, g, b );
min = minOf3Values( r, g, b );
dif = max - min;
//计算l,亮度
l = ( max + min ) * 240 / 255 / 2;
//计算h,色度
if( max == min )//无定义
{
s = 0;
h = 0;
}
else
{
//计算色度
if( max == r )//最大值为红色
{
if( min == b )//h介于0到40 最小值为蓝色
{
h = 40 * ( g - b ) / dif;//h = 40 * ( g - n ) / dif;
}
else if( min == g )//h介于200到240 最小值为绿色
{
h = 40 * ( g - b ) / dif + 240;
}
}
else if( max == g )//最大值为绿色 40到120
{
h = 40 * ( b - r ) / dif + 80;
}
else if( max == b )//最大值为蓝色 120 -200
{
h = 40 * ( r - g ) / dif + 160;
}
//计算饱和度
if( l == 0 )
{
s = 0;
}
else if( l <= 120 )
{
s = dif * 240 / ( max + min );
}
else
{
s = dif * 240 / ( 480 - ( max + min ) );
}
}
// H = h;
// S = s;
// L = l;
color_hls->Hue = h; //色度
color_hls->Lightness = l; //亮度
color_hls->Saturation = s; //饱和度
}
/**
* @brief 颜色匹配
* @param color_hls :COLOR_HLS结构体,存储HLS格式颜色数据
* @param condition :TARGET_CONDITION结构体,存放希望的颜色数据阈值
* @retval 1:像素点颜色在目标范围内;0:像素点颜色不在目标范围内。
*/
static int ColorMatch(const COLOR_HLS* color_hls, const TARGET_CONDITION* condition )
{
if(
color_hls->Hue > condition->H_MIN &&
color_hls->Hue < condition->H_MAX &&
color_hls->Lightness > condition->L_MIN &&
color_hls->Lightness < condition->L_MAX &&
color_hls->Saturation > condition->S_MIN &&
color_hls->Saturation < condition->S_MAX
)
{
H = color_hls->Hue;
S = color_hls->Saturation;
L = color_hls->Lightness;return 1;
}
else
return 0;
}
/**
* @brief 寻找腐蚀中心
* @param x :腐蚀中心x坐标
* @param y :腐蚀中心y坐标
* @param condition :TARGET_CONDITION结构体,存放希望的颜色数据阈值
* @param area :SEARCH_AREA结构体,查找腐蚀中心的区域
* @retval 1:找到了腐蚀中心,x、y为腐蚀中心的坐标;0:没有找到腐蚀中心。
*/
static int SearchCenter(unsigned int* x, unsigned int* y, const TARGET_CONDITION* condition, SEARCH_AREA* area )
{
unsigned int i, j, k;
unsigned int FailCount=0;
unsigned int SpaceX, SpaceY;
COLOR_RGB rgb;
COLOR_HLS hls;
SpaceX = condition->WIDTH_MIN / 3;//最小宽度 40/3
SpaceY = condition->HEIGHT_MIN / 3;//最小高度 40/3
for(i=area->Y_Start; iY_End; i+=SpaceY)
{
for(j=area->X_Start; jX_End; j+=SpaceX)
{
FailCount = 0;
for(k=0; k( (SpaceX+SpaceY) >> ALLOW_FAIL_PER ))
break;
}
if(k == SpaceX+SpaceY)
{
*x = j + SpaceX / 2;
*y = i + SpaceY / 2;
return 1;
}
}
}
return 0;
}
/**
* @brief 从腐蚀中心向外腐蚀,得到新的腐蚀中心
* @param oldX :先前的腐蚀中心x坐标
* @param oldX :先前的腐蚀中心y坐标
* @param condition :TARGET_CONDITION结构体,存放希望的颜色数据阈值
* @param result :RESULT结构体,存放检测结果
* @retval 1:检测成功;0:检测失败。
*/
static int Corrode(unsigned int oldX, unsigned int oldY, const TARGET_CONDITION* condition, RESULT* result )
{
unsigned int Xmin, Xmax, Ymin, Ymax;
unsigned int i;
unsigned int FailCount=0;
COLOR_RGB rgb;
COLOR_HLS hls;
//从中心点查到x最左侧
for(i=oldX; i>IMG_X; i--)
{
ReadColor(i, oldY, &rgb);
RGB2HSL(&rgb, &hls);
if(!ColorMatch(&hls, condition))
FailCount++;
if(FailCount>(((condition->WIDTH_MIN+condition->WIDTH_MAX)>>2)>>ALLOW_FAIL_PER))
break;
}
Xmin=i;
//从中心点查到x最右侧
FailCount=0;
for(i=oldX; i(((condition->WIDTH_MIN+condition->WIDTH_MAX)>>2)>>ALLOW_FAIL_PER))
break;
}
Xmax=i;
//y上
FailCount=0;
for(i=oldY; i>IMG_Y; i--)
{
ReadColor(oldX, i, &rgb);
RGB2HSL(&rgb, &hls);
if(!ColorMatch(&hls, condition))
FailCount++;
if(FailCount>(((condition->HEIGHT_MIN+condition->HEIGHT_MAX)>>2)>>ALLOW_FAIL_PER))
break;
}
Ymin=i;
//y下
FailCount=0;
for(i=oldY; i(((condition->HEIGHT_MIN+condition->HEIGHT_MAX)>>2)>>ALLOW_FAIL_PER))
break;
}
Ymax=i;
FailCount=0;
result->x = (Xmin + Xmax) / 2;
result->y = (Ymin + Ymax) / 2;
result->w = (Xmax - Xmin);
result->h = (Ymax - Ymin);
if( (result->w > condition->WIDTH_MIN) && (result->w < condition->WIDTH_MAX) &&
(result->h > condition->HEIGHT_MIN) && (result->h < condition->HEIGHT_MAX) )
return 1;
else
return 0;
}
int Trace(const TARGET_CONDITION* condition, RESULT* result_final)
{
unsigned int i;
static unsigned int x0, y0, Flag = 0;
static SEARCH_AREA area = {IMG_X, IMG_X+IMG_W, IMG_Y, IMG_Y+IMG_H};//搜索区域
RESULT result;
// for(i = 0;i<2;i++)
// {
if(Flag == 0)
{
if(SearchCenter(&x0, &y0, condition, &area))
{
Flag = 1;
//break;
}
else
{
area.X_Start = IMG_X;
area.X_End = IMG_X+IMG_W;
area.Y_Start = IMG_Y;
area.Y_End = IMG_Y+IMG_H;
if(SearchCenter(&x0, &y0, condition, &area))
{
Flag = 0;
return 0;
}
}
}
//}
result.x = x0;
result.y = y0;
for(i=0; ix = result.x;
result_final->y = result.y;
result_final->w = result.w;
result_final->h = result.h;
Flag = 1;
area.X_Start = result.x - ((result.w)>>1);
area.X_End = result.x + ((result.w)>>1);
area.Y_Start = result.y - ((result.h)>>1);
area.Y_End = result.y + ((result.h)>>1);
return 1;
}
else
{
Flag = 0;
return 0;
}
}
//#define min3v(v1, v2, v3) ((v1)>(v2)? ((v2)>(v3)?(v3):(v2)):((v1)>(v3)?(v3):(v1)))
//#define max3v(v1, v2, v3) ((v1)<(v2)? ((v2)<(v3)?(v3):(v2)):((v1)<(v3)?(v3):(v1)))
//typedef struct{
// unsigned char red; // [0,255]
// unsigned char green; // [0,255]
// unsigned char blue; // [0,255]
//}COLOR_RGB;//RGB格式颜色
//typedef struct{
// unsigned char hue; // [0,240]
// unsigned char saturation; // [0,240]
// unsigned char luminance; // [0,240]
//}COLOR_HSL;//HSL格式颜色
//typedef struct{
// unsigned int X_Start;
// unsigned int X_End;
// unsigned int Y_Start;
// unsigned int Y_End;
//}SEARCH_AREA;//区域
读取RBG格式颜色,唯一需要移植的函数
//extern unsigned short GUI_ReadBit16Point(unsigned short x,unsigned short y);
//static void ReadColor(unsigned int x,unsigned int y,COLOR_RGB *Rgb)
//{
// unsigned short C16;
// C16 = LCD_ReadPoint(x,y);
// Rgb->red = (unsigned char)((C16&0xf800)>>8);
// Rgb->green = (unsigned char)((C16&0x07e0)>>3);
// Rgb->blue = (unsigned char)((C16&0x001f)<<3);
//}
RGB转HSL
//static void RGBtoHSL(const COLOR_RGB *Rgb, COLOR_HSL *Hsl)
//{
// int h,s,l,maxVal,minVal,difVal;
// int r = Rgb->red;
// int g = Rgb->green;
// int b = Rgb->blue;
//
// maxVal = max3v(r, g, b);
// minVal = min3v(r, g, b);
//
// difVal = maxVal-minVal;
//
// //计算亮度
// l = (maxVal+minVal)*240/255/2;
//
// if(maxVal == minVal)//若r=g=b
// {
// h = 0;
// s = 0;
// }
// else
// {
// //计算色调
// if(maxVal==r)
// {
// if(g>=b)
// h = 40*(g-b)/(difVal);
// else
// h = 40*(g-b)/(difVal) + 240;
// }
// else if(maxVal==g)
// h = 40*(b-r)/(difVal) + 80;
// else if(maxVal==b)
// h = 40*(r-g)/(difVal) + 160;
// //计算饱和度
// if(l == 0)
// s = 0;
// else if(l<=120)
// s = (difVal)*240/(maxVal+minVal);
// else
// s = (difVal)*240/(480 - (maxVal+minVal));
// }
// Hsl->hue = (unsigned char)(((h>240)? 240 : ((h<0)?0:h)));
// Hsl->saturation = (unsigned char)(((s>240)? 240 : ((s<0)?0:s)));
// Hsl->luminance = (unsigned char)(((l>240)? 240 : ((l<0)?0:l)));
//}
匹配颜色
//static int ColorMatch(const COLOR_HSL *Hsl,const TARGET_CONDITION *Condition)
//{
// if(
// Hsl->hue > Condition->H_MIN &&
// Hsl->hue < Condition->H_MAX &&
// Hsl->saturation > Condition->S_MIN &&
// Hsl->saturation < Condition->S_MAX &&
// Hsl->luminance > Condition->L_MIN &&
// Hsl->luminance < Condition->L_MAX
// )
// return 1;
// else
// return 0;
//}
搜索腐蚀中心
//static int SearchCentre(unsigned int *x,unsigned int *y,const TARGET_CONDITION *Condition,const SEARCH_AREA *Area)
//{
// unsigned int SpaceX,SpaceY,i,j,k,FailCount=0;
// COLOR_RGB Rgb;
// COLOR_HSL Hsl;
//
// SpaceX = Condition->WIDTH_MIN/3;
// SpaceY = Condition->HEIGHT_MIN/3;
// for(i=Area->Y_Start;iY_End;i+=SpaceY)
// {
// for(j=Area->X_Start;jX_End;j+=SpaceX)
// {
// FailCount=0;
// for(k=0;k((SpaceX+SpaceY)>>ALLOW_FAIL_PER))
// break;
// }
// if(k==SpaceX+SpaceY)
// {
// *x = j+SpaceX/2;
// *y = i+SpaceY/2;
// return 1;
// }
// }
// }
// return 0;
//}
从腐蚀中心向外腐蚀,得到新的腐蚀中心
//static int Corrode(unsigned int oldx,unsigned int oldy,const TARGET_CONDITION *Condition,RESULT *Resu)
//{
// unsigned int Xmin,Xmax,Ymin,Ymax,i,FailCount=0;
// COLOR_RGB Rgb;
// COLOR_HSL Hsl;
//
// for(i=oldx;i>IMG_X;i--)
// {
// ReadColor(i,oldy,&Rgb);
// RGBtoHSL(&Rgb,&Hsl);
// if(!ColorMatch(&Hsl,Condition))
// FailCount++;
// if(FailCount>(((Condition->WIDTH_MIN+Condition->WIDTH_MAX)>>2)>>ALLOW_FAIL_PER))
// break;
// }
// Xmin=i;
// FailCount=0;
//
// for(i=oldx;i(((Condition->WIDTH_MIN+Condition->WIDTH_MAX)>>2)>>ALLOW_FAIL_PER))
// break;
// }
// Xmax=i;
// FailCount=0;
//
// for(i=oldy;i>IMG_Y;i--)
// {
// ReadColor(oldx,i,&Rgb);
// RGBtoHSL(&Rgb,&Hsl);
// if(!ColorMatch(&Hsl,Condition))
// FailCount++;
// if(FailCount>(((Condition->HEIGHT_MIN+Condition->HEIGHT_MIN)>>2)>>ALLOW_FAIL_PER))
// break;
// }
// Ymin=i;
// FailCount=0;
//
// for(i=oldy;i(((Condition->HEIGHT_MIN+Condition->HEIGHT_MIN)>>2)>>ALLOW_FAIL_PER))
// break;
// }
// Ymax=i;
// FailCount=0;
//
// Resu->x = (Xmin+Xmax)/2;
// Resu->y = (Ymin+Ymax)/2;
// Resu->w = Xmax-Xmin;
// Resu->h = Ymax-Ymin;
// if(((Xmax-Xmin)>(Condition->WIDTH_MIN)) && ((Ymax-Ymin)>(Condition->HEIGHT_MIN)) &&\
// ((Xmax-Xmin)<(Condition->WIDTH_MAX)) && ((Ymax-Ymin)<(Condition->HEIGHT_MIN)) )
// return 1;
// else
// return 0;
//}
唯一的API,用户将识别条件写入Condition指向的结构体中,该函数将返回目标的x,y坐标和长宽
返回1识别成功,返回1识别失败
//int Trace(const TARGET_CONDITION *Condition,RESULT *Resu)
//{
// unsigned int i;
// static unsigned int x0,y0,flag=0;
// static SEARCH_AREA Area={IMG_X,IMG_X+IMG_W,IMG_Y,IMG_Y+IMG_H};
// RESULT Result;
//
// if(flag==0)
// {
// if(SearchCentre(&x0,&y0,Condition,&Area))
// flag=1;
// else
// {
// Area.X_Start= IMG_X ;
// Area.X_End = IMG_X+IMG_W ;
// Area.Y_Start= IMG_Y ;
// Area.Y_End = IMG_Y+IMG_H;
// if(SearchCentre(&x0,&y0,Condition,&Area))
// {
// flag=0;
// return 0;
// }
// }
// }
// Result.x = x0;
// Result.y = y0;
//
// for(i=0;ix=Result.x;
// Resu->y=Result.y;
// Resu->w=Result.w;
// Resu->h=Result.h;
// flag=1;
// Area.X_Start= Result.x - ((Result.w)>>1);
// Area.X_End = Result.x + ((Result.w)>>1);
// Area.Y_Start= Result.y - ((Result.h)>>1);
// Area.Y_End = Result.y + ((Result.h)>>1);
// return 1;
// }
// else
// {
// flag=0;
// return 0;
// }
//}
#ifndef __COLORTRACER_H
#define __COLORTRACER_H
#include "stm32f10x.h"
#define IMG_X 0 //图片x坐标
#define IMG_Y 0 //图片y坐标
#define IMG_W 240 //图片宽度
#define IMG_H 320 //图片高度
#define ALLOW_FAIL_PER 3 //容错率
#define ITERATER_NUM 8 //迭代次数
typedef struct //判定为目标的条件
{
unsigned char H_MIN; //目标最小色度
unsigned char H_MAX; //目标最大色度
unsigned char S_MIN; //目标最小饱和度
unsigned char S_MAX; //目标最大饱和度
unsigned char L_MIN; //目标最小亮度
unsigned char L_MAX; //目标最大亮度
unsigned int WIDTH_MIN; //目标最小宽度
unsigned int HEIGHT_MIN; //目标最小高度
unsigned int WIDTH_MAX; //目标最大宽度
unsigned int HEIGHT_MAX; //目标最大高度
}TARGET_CONDITION;
typedef struct //结果
{
unsigned int x; //目标x坐标
unsigned int y; //目标y坐标
unsigned int w; //目标宽度
unsigned int h; //目标高度
}RESULT;
extern RESULT result;
extern TARGET_CONDITION condition0;
extern TARGET_CONDITION condition1;
extern TARGET_CONDITION condition2;
extern TARGET_CONDITION condition3;
extern TARGET_CONDITION condition4;
extern TARGET_CONDITION condition5;
extern TARGET_CONDITION condition6;
extern TARGET_CONDITION condition7;
extern TARGET_CONDITION condition8;
int Trace(const TARGET_CONDITION* condition, RESULT* result_final);
#endif
好用 ,太好用了