要每天养成写博客的习惯,可是,苦于最近学习没有进展啊。
无奈把自己去年学习STM32以及做相关项目时的代码发出来水水博客吧!
本代码在原子哥摄像头实验基础上做了相关更改。
color.c部分[用于设定颜色值、匹配颜色等]:
#include "color.h"
#include "sys.h"
#include "lcd.h"
#include
RESULT result;
TARGET_CONDITION condition={
60, //目标最小色度,H_MIN
110, //目标最大色度,H_MAX
50, //目标最小饱和度,S_MIN
240, //目标最大饱和度,S_MAX
60, //目标最小亮度,L_MIN
190, //目标最大亮度,L_MAX
40, //目标最小宽度,WIDTH_MIN
40, //目标最小高度,HEIGHT_MIN
320, //目标最大宽度,WIDTH_MAX
240 //目标最大高度,HEIGHT_MAX蟾叨龋琀EIGHT_MAX
};
typedef struct //HLS颜色
{
unsigned char Hue; //色度 ,[0,240]
unsigned char Lightness; //亮度,[0,240]
unsigned char Saturation; //饱和度,[0,240]
}COLOR_HLS;
typedef struct //RGB
{
unsigned char Red; // [0,255]
unsigned char Green; // [0,255]
unsigned char Blue; // [0,255]
}COLOR_RGB;
/**************************************/
//读取某点的颜色
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 ) <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;
}
else if( min == g )//h介于200到240
{
h = 40 * ( g - b ) / dif + 240;
}
}
else if( max == g )
{
h = 40 * ( b - r ) / dif + 80;
}
else if( max == b )
{
h = 40 * ( r - g ) / dif + 160;
}
//计算饱和度
if( l == 0 )
{
s = 0;
}
else if( l Hue = h; //色度
color_hls->Lightness = l; //亮度
color_hls->Saturation = s; //饱和度
}
/************************************************/
// 颜色匹配
//color_hls :COLOR_HLS结构体,存储HLS格式颜色数据
// condition :TARGET_CONDITION结构体,存放希望的颜色数据阈值
// 1:像素点颜色在目标范围内;0:像素点颜色不在目标范围内。
static int ColorMatch(const COLOR_HLS* color_hls, const TARGET_CONDITION* condition )
{
if(
color_hls->Hue > condition->H_MIN &&
color_hls->Hue H_MAX &&
color_hls->Lightness > condition->L_MIN &&
color_hls->Lightness L_MAX &&
color_hls->Saturation > condition->S_MIN &&
color_hls->Saturation S_MAX
)
return 1;
else
return 0;
}
/****************************************************/
// 寻找腐蚀中心
// x :腐蚀中心x坐标
// y :腐蚀中心y坐标
// condition :TARGET_CONDITION结构体,存放希望的颜色数据阈值
// area :SEARCH_AREA结构体,查找腐蚀中心的区域
// 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;
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; k++)
{
if(k( (SpaceX+SpaceY) >> ALLOW_FAIL_PER ))
break;
}
if(k == SpaceX+SpaceY)
{
*x = j + SpaceX / 2;
*y = i + SpaceY / 2;
return 1;
}
}
}
return 0;
}
/***************************************************/
// 从腐蚀中心向外腐蚀,得到新的腐蚀中心
// oldX :先前的腐蚀中心x坐标
// oldX :先前的腐蚀中心y坐标
// condition :TARGET_CONDITION结构体,存放希望的颜色数据阈值
// result :RESULT结构体,存放检测结果
// 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;
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;
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);
RGB2HSL(&rgb, &hls);
if(!ColorMatch(&hls, condition))
FailCount++;
if(FailCount>(((condition->HEIGHT_MIN+condition->HEIGHT_MAX)>>2)>>ALLOW_FAIL_PER))
break;
}
Ymin=i;
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 WIDTH_MAX) &&
(result->h > condition->HEIGHT_MIN) && (result->h 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;
if(Flag == 0)
{
if(SearchCenter(&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(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;
}
}
main.c部分:
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"
#include "string.h"
#include "ov7670.h"
#include "tpad.h"
#include "timer.h"
#include "exti.h"
#include "usmart.h"
#include "color.h"
/************************************************
ALIENTEK精英STM32开发板实验33
摄像头OV7670 实验
技术支持:www.openedv.com
淘宝店铺:http://eboard.taobao.com
关注微信公众平台微信号:"正点原子",免费获取STM32资料。
广州市星翼电子科技有限公司
作者:正点原子 @ALIENTEK
************************************************/
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里面定义
//更新LCD显示
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;jIDR&0XFF; //读数据
OV7670_RCK_H;
color<IDR&0XFF; //读数据
OV7670_RCK_H;
// if(color>25500)
// color=0x0000;
// else
// color=0xffff;
LCD->LCD_RAM=color;
}
ov_sta=0; //清零帧中断标记
ov_frame++;
LCD_Scan_Dir(DFT_SCAN_DIR); //恢复默认扫描方向
if(Trace(&condition, &result))
{
LCD_DrawRectangle( result.x-result.w/2, result.y-result.h/2, result.x-result.w/2+result.w, result.y-result.h/2+result.h);
LCD_DrawRectangle( result.x-2, result.y-2,result.x+2, result.y+2);
}
}
}
int main(void)
{
//u8 key;
u8 lightmode=0,saturation=2,contrast=2;
u8 effect=0;
u8 i=0;
u8 msgbuf[15]; //消息缓存区
u8 tm=0;
// u16 t=0;
// u16 a,b,c;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为 115200
usmart_dev.init(72); //初始化USMART
LED_Init(); //初始化与LED连接的硬件接口
KEY_Init(); //初始化按键
LCD_Init(); //初始化LCD
TPAD_Init(6); //触摸按键初始化
POINT_COLOR=RED; //设置字体为红色
LCD_ShowString(30,50,200,16,16,"ELITE STM32F103 ^_^");
LCD_ShowString(30,70,200,16,16,"OV7670 TEST");
LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,110,200,16,16,"2015/1/18");
LCD_ShowString(30,130,200,16,16,"KEY0:Light Mode");
LCD_ShowString(30,150,200,16,16,"KEY1:Saturation");
LCD_ShowString(30,170,200,16,16,"KEY_UP:Contrast");
LCD_ShowString(30,190,200,16,16,"TPAD:Effects");
LCD_ShowString(30,210,200,16,16,"OV7670 Init...");
// while(OV7670_Init())//初始化OV7670
OV7670_Init();//初始化OV7670
{
LCD_ShowString(30,210,200,16,16,"OV7670 Error!!");
delay_ms(200);
LCD_Fill(30,210,239,246,WHITE);
delay_ms(200);
}
LCD_ShowString(30,210,200,16,16,"OV7670 Init OK");
delay_ms(1500);
OV7670_Light_Mode(lightmode);
OV7670_Color_Saturation(saturation);
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)
{
POINT_COLOR=BLUE;
// key=KEY_Scan(0);//不支持连按
// if(key)
// {
// tm=20;
// switch(key)
// {
// case KEY0_PRES: //灯光模式Light Mode
// lightmode++;
// if(lightmode>4)lightmode=0;
// OV7670_Light_Mode(lightmode);
// sprintf((char*)msgbuf,"%s",LMODE_TBL[lightmode]);
// break;
// case KEY1_PRES: //饱和度Saturation
// saturation++;
// if(saturation>4)saturation=0;
// OV7670_Color_Saturation(saturation);
// sprintf((char*)msgbuf,"Saturation:%d",(signed char)saturation-2);
// break;
// case WKUP_PRES: //对比度Contrast
// contrast++;
// if(contrast>4)contrast=0;
// OV7670_Contrast(contrast);
// sprintf((char*)msgbuf,"Contrast:%d",(signed char)contrast-2);
// break;
// }
// }
// if(TPAD_Scan(0))//检测到触摸按键
// {
// effect++;
// if(effect>6)effect=0;
// OV7670_Special_Effects(effect);//设置特效
// sprintf((char*)msgbuf,"%s",EFFECTS_TBL[effect]);
// tm=20;
// }
camera_refresh();//更新显示
if(tm)
{
LCD_ShowString((lcddev.width-240)/2+30,(lcddev.height-320)/2+60,200,16,16,msgbuf);
tm--;
}
i++;
if(i==15)//DS0闪烁.
{
i=0;
LED0=!LED0;
}
}
}