点击这里找小助理0元领取:扫码进群领资料
一、正文在平凡的摄像头刷新图像之后,加上鼻祖的第三方文件库,调用个中的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 u8LMODE_TBL[5]={"Auto","Sunny","Cloudy","Office","Home"};//5种光照模式 const u8EFFECTS_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)//有帧中断更新?{......} 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); //串口初始化为 115200LCD_Init(); //初始化LCD while(OV7670_Init())//初始化OV7670..... 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_MIN110, //目标最大色度,H_MAX 45, //目标最小饱和度,S_MIN110, //目标最大饱和度,S_MAX 90, //目标最小亮度,L_MIN210, //目标最大亮度,L_MAX 40, //目标最小宽度,WIDTH_MIN40, //目标最小高度,HEIGHT_MIN 240, //目标最大宽度,WIDTH_MAX320 //目标最大高度,HEIGHT_MAX};//蓝色.....};#define minOf3Values( v1, v2, v3 )( (v1<v2) ? ( (v1<v3) ? (v1) : (v3) ) : ( (v2<v3) ? (v2) : (v3) ) )//取rgb中的最小值 #define maxOf3Values( v1, v2, v3 )( (v1>v2) ? ( (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{//打算色度..........}}//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;}elsereturn 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/3SpaceY = condition->HEIGHT_MIN / 3;//最小高度 40/3for(i=area->Y_Start; i<area->Y_End; i+=SpaceY){for(j=area->X_Start; j<area->X_End; j+=SpaceX){FailCount = 0;for(k=0; k<SpaceX+SpaceY; k++){if(k<SpaceX)ReadColor( j+k, i+SpaceY/2, &rgb );elseReadColor( j+SpaceX/2, i+k-SpaceX, &rgb );RGB2HSL( &rgb, &hls );if(!ColorMatch( &hls, condition ))FailCount++;if(FailCount>( (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<IMG_X+IMG_W; i++){..........}Xmax=i;//y上FailCount=0;for(i=oldY; i>IMG_Y; i--){..........}Ymin=i;//y下FailCount=0;for(i=oldY; i<IMG_Y+IMG_H; 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;}..........} 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; i<ITERATER_NUM; i++){Corrode(result.x, result.y, condition, &result);//从堕落中央向外堕落,得到新的堕落中央}if( Corrode(result.x, result.y, condition, &result) ){x0 = result.x;y0 = result.y;result_final->x = 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{..........//}COLOR_RGB;//RGB格式颜色 //typedef struct{..........//}COLOR_HSL;//HSL格式颜色 //typedef struct{..........//}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;//..........//} 匹配颜色//static int ColorMatch(const COLOR_HSL Hsl,const TARGET_CONDITION Condition)//{..........//} 搜索堕落中央//static int SearchCentre(unsigned int x,unsigned int y,const TARGET_CONDITION Condition,const SEARCH_AREA Area)//{..........//} 从堕落中央向外堕落,得到新的堕落中央//static int Corrode(unsigned int oldx,unsigned int oldy,const TARGET_CONDITION Condition,RESULT Resu)//{..........//} 唯一的API,用户将识别条件写入Condition指向的构造体中,该函数将返回目标的x,y坐标和长宽返回1识别成功,返回1识别失落败//int Trace(const TARGET_CONDITION Condition,RESULT Resu)//{..........//} //}
完全代码可进群免费领取!
!
!
嵌入式物联网的学习之路非常漫长,不少人由于学习路线不对或者学习内容不足专业而错失落高薪offer。不过别担心,我为大家整理了一份150多G的学习资源,基本上涵盖了嵌入式物联网学习的所有内容。点击上方链接,0元领取学习资源,让你的学习之路更加顺畅!
记得点赞、关注、收藏、转发哦!