STM32摄像头实验相关源码分享[一、颜色识别]

Emily ·
更新时间:2024-11-13
· 952 次阅读

要每天养成写博客的习惯,可是,苦于最近学习没有进展啊。
无奈把自己去年学习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; } } }
作者:Abby_QI



摄像 源码分享 摄像头 源码 stm32

需要 登录 后方可回复, 如果你还没有账号请 注册新账号