精华内容
下载资源
问答
  • 恩智浦智能车摄像头组图像处理以及寻线程序..智能车摄像头图像处理
  • 恩智浦智能车摄像头图像处理以及寻线程序
  • 智能车摄像头图像处理部分(一)动态阈值之大津法 (参考了逐飞提供的例程) /*##########蓝多多老爷车大津法计算阈值部分########*/ uint8 my_adapt_threshold(uint8 *image, uint16 col, uint16 row) //注意计算...

    智能车摄像头图像处理部分(一)动态阈值之大津法
    (参考了逐飞提供的例程)

    /*##########蓝多多老爷车大津法计算阈值部分########*/
    
    uint8 my_adapt_threshold(uint8 *image, uint16 col, uint16 row)   //注意计算阈值的一定要是原图像
    {
       #define GrayScale 256
        uint16 width = col;
        uint16 height = row;
        int pixelCount[GrayScale];
        float pixelPro[GrayScale];
        int i, j, pixelSum = width * height/4;
        uint8 threshold = 0;
        uint8* data = image;  //指向像素数据的指针
        for (i = 0; i < GrayScale; i++)
        {
            pixelCount[i] = 0;
            pixelPro[i] = 0;
        }
        
        uint32 gray_sum=0;
        //统计灰度级中每个像素在整幅图像中的个数  
        for (i = 0; i < height; i+=2)
        {
            for (j = 0; j < width; j+=2)
            {
                pixelCount[(int)data[i * width + j]]++;  //将当前的点的像素值作为计数数组的下标
                gray_sum+=(int)data[i * width + j];       //灰度值总和
            }
        }
                          
        //计算每个像素值的点在整幅图像中的比例  
      
        for (i = 0; i < GrayScale; i++)
        {
            pixelPro[i] = (float)pixelCount[i] / pixelSum;
            
        }
    
        //遍历灰度级[0,255]  
        float w0, w1, u0tmp, u1tmp, u0, u1, u, deltaTmp, deltaMax = 0;
            w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;
            for (j = 0; j < GrayScale; j++)         
            {
                
                    w0 += pixelPro[j];  //背景部分每个灰度值的像素点所占比例之和   即背景部分的比例
                    u0tmp += j * pixelPro[j];  //背景部分 每个灰度值的点的比例 *灰度值 
               
                   w1=1-w0;
                   u1tmp=gray_sum/pixelSum-u0tmp;
            
                    u0 = u0tmp / w0;              //背景平均灰度
                    u1 = u1tmp / w1;              //前景平均灰度
                    u = u0tmp + u1tmp;            //全局平均灰度
                    deltaTmp = w0 * pow((u0 - u), 2) + w1 * pow((u1 - u), 2);//平方
                    if (deltaTmp > deltaMax)
                    {
                        deltaMax = deltaTmp;//最大类间方差法
                        threshold = j;
                    }
                    if (deltaTmp < deltaMax)
                    {
                    break;
                    }
              
             }
        return threshold;
    }
    

    本文章仅为学习过程随手记,如有批评指正欢迎留言。

    展开全文
  • 适合智能车初学者了解摄像头处理
  • 此上位机既可以对智能车摄像头组跑完一圈所存的原始图像进行动态显示,又可以对单片机处理后的图像进行动态显示;还可以扩展将摄像头算法在上位机中进行运算后再动态显示,这样就可以不用一直跑就可以试验不同的处理...
  • 整理智能车中使用到的摄像头图像处理算法

    千次阅读 多人点赞 2020-10-15 13:56:08
    整理智能车中使用到的摄像头图像处理算法 19年的智能车竞赛给我留下了很深远的影响,不管是算法思路还是解决问题的方法对我来说都受益匪浅。今天整理资料时又翻出这些代码,回忆起做车时不分日夜地在赛道上调试,...

    整理智能车中使用到的摄像头图像处理算法

    19年的智能车竞赛给我留下了很深远的影响,不管是算法思路还是解决问题的方法对我来说都受益匪浅。今天整理资料时又翻出这些代码,回忆起做车时不分日夜地在赛道上调试,回忆起尽管小车已经完整跑完赛道却依旧想着如何去优化得更快更好的自己。
    现在把自己的整理分享给有用的人,希望能少走写弯路吧。
    注意单片机性能有限,在执行一些算法时效率会很低。

    S_CV.h

    #ifndef _S_CV_H
    #define _S_CV_H
    #include "include.h"
    
    //图像大小定义
    /*
    #define S_img_H		120
    #define S_img_W		188*/
    #define S_img_H		60
    #define S_img_W		94
    
    #define S_S_Custom	0xAA
    
    void S_BinaryImage(uint8_t in_IMG[S_img_H][S_img_W], uint8_t out_IMG[S_img_H][S_img_W], uint8_t ThresholdV);
    void S_SE_Operation(uint8_t in_IMG[S_img_H][S_img_W], uint8_t out_IMG[S_img_H][S_img_W]);
    void S_SE_OperationBIG(uint8_t in_IMG[120][188], uint8_t out_IMG[120][188]);
    
    /**********************************形态学处理**************************************/
    //腐蚀
    void S_Erode(uint8_t in_IMG[S_img_H][S_img_W], uint8_t out_IMG[S_img_H][S_img_W]);
    //膨胀
    void S_Dilate(uint8_t in_IMG[S_img_H][S_img_W], uint8_t out_IMG[S_img_H][S_img_W]);
    //开操作
    void S_Open(uint8_t in_IMG[S_img_H][S_img_W], uint8_t out_IMG[S_img_H][S_img_W]);
    //关操作
    void S_Close(uint8_t in_IMG[S_img_H][S_img_W], uint8_t out_IMG[S_img_H][S_img_W]);
    
    
    /**********************************图像显示**************************************/
    #define S_MINI	0
    #define S_BIG		1
    //显示小图像到TFT模块
    void S_Draw_TFT_MINI(uint8_t in_IMG[S_img_H][S_img_W]);
    //60*94图像显示成188*120
    void S_DisplayMINI_Big(uint8_t in_IMG[PixMini_H][PixMini_W]);
    //显示大图像到TFT模块
    void S_Draw_TFT_BIG(uint8_t in_IMG[IMAGEH][IMAGEW]);
    //显示灰度图像60*90	可选大小
    void S_Gray_DisplayMINI(uint8_t in_IMG[PixMini_H][PixMini_W], u8 size);
    //显示灰度图像120*188	
    void S_Gray_Display(uint8_t in_IMG[IMAGEH][IMAGEW]);
    //三线图显示
    void S_DisplayRunWay(RunWay_* in_Array);
    //三线图显示	大图
    void S_DRW_Big(RunWay_* in_Array);
    
    
    
    /**********************************其他操作**************************************/
    // 图像  抽取压缩188X120 to 94X60
    void S_Image_zip(uint8_t in_IMG[IMAGEH][IMAGEW], uint8_t out_IMG[S_img_H][S_img_W]);
    // 图像 填充放大 94X60  to  188X120 
    void S_Image_larger(uint8_t in_IMG[S_img_H][S_img_W], uint8_t out_IMG[IMAGEH][IMAGEW]);
    //三线图检测
    void DetectionLine(uint8_t in_IMG[PixMini_H][PixMini_W], RunWay_ * out_Array, u8 LMP, u8 Mod);
    //三线图定制
    void DetectionLine_Custom(uint8_t in_IMG[PixMini_H][PixMini_W], RunWay_* out_Array, u8 LMP);
    
    
    
    /*********************************求阈值***************************************/
    //大津法求阈值
    uint8_t S_GetOSTU(uint8_t tmImage[S_img_H][S_img_W]);		//修改
    uint8 S_Other_OSTU(int width, int height, uint8* Image);
    //均值比例求阈值
    u8 S_Get_01_Value(uint8_t tmImage[S_img_H][S_img_W]);
    
    /*********************************滤波***************************************/
    //加权滤波
    void S_WeightedFiltering(uint8_t in_IMG[S_img_H][S_img_W], uint8_t out_IMG[S_img_H][S_img_W]);
    //注入填充算法(Flood Fill Algorithm)
    void S_FloodSeedFill(uint8_t in_IMG[S_img_H][S_img_W], u8 x, u8 y, u8 old_color, u8 new_color);
    //修改注入填充算法		使用for循环  非递归  不溢出
    void SX_FloodSeedFill(uint8_t in_IMG[40][63], u8 x, u8 y, u8 old_color, u8 new_color);
    //在一幅图像中判定  横穿图像的白块			未实现
    u8 S_Linear(u8 height, u8 width, uint8* in_IMG);
    
    /**********************************图像边缘检测算法**************************************/
    //Robert算子
    void S_Robert(uint8_t in_IMG[PixMini_H][PixMini_W], uint8_t out_IMG[PixMini_H][PixMini_W]);
    //S_Sobel算子
    void S_Sobel(uint8_t in_IMG[PixMini_H][PixMini_W], uint8_t out_IMG[PixMini_H][PixMini_W], u8 Threshold);
    //sobel 定制
    void S_Sobel_Custom(uint8_t in_IMG[PixMini_H][PixMini_W], uint8_t out_IMG[PixMini_H][PixMini_W], u8 Threshold);
    
    
    
    #endif
    

    S_CV.c

    //#include <cv.h>
    //#include <highgui.h>
    #include "S_CV.h"
    
    
    u8 temp_IMG[S_img_H][S_img_W];	//过渡图像
    
    /***************************************************************
    *
    * 函数名称:void S_BinaryImage(uint8_t tmImage[IMAGEH][IMAGEW], uint8_t ThresholdV)
    * 功能说明:图像数据二值化
    * 参数说明:tmImage 二值化数据存储、 ThresholdV 阈值
    * 函数返回:void
    * 修改时间:2019年4月6日
    * 备 注:
    ***************************************************************/
    void S_BinaryImage(uint8_t in_IMG[S_img_H][S_img_W], uint8_t out_IMG[S_img_H][S_img_W], uint8_t ThresholdV)
    {
    	int i = 0, j = 0;
    	for (i = 0; i < S_img_H; i++)
    		for (j = 0; j < S_img_W; j++)
    		{
    			if (in_IMG[i][j] > ThresholdV)
    				out_IMG[i][j] = 1;
    			else
    				out_IMG[i][j] = 0;
    		}
    }
    
    //SE	操作
    //			1
    //		1	X	1
    //			1
    void S_SE_Operation(uint8_t in_IMG[S_img_H][S_img_W], uint8_t out_IMG[S_img_H][S_img_W])
    {
    	u8 i, j;
    	//限制长宽避免溢出     使用图像小一圈
    	u8 img_H = S_img_H - 1;
    	u8 img_W = S_img_W - 1;
    	u8 S_UP, S_DN, S_LL, S_RR;
    	//输出数据初始化
    	for (i = 0; i < S_img_H; i++)
    		for (j = 0; j < S_img_W; j++)
    			out_IMG[i][j] = 0;
    	for (i = 1; i < img_H; i++)
    	{
    		S_UP = i - 1;
    		S_DN = i + 1;
    		for (j = 1; j < img_W; j++)
    		{
    			S_LL = j - 1;
    			S_RR = j + 1;
    			if (in_IMG[i][j])
    			{
    				out_IMG[i][j]++;
    				out_IMG[S_UP][j]++;		//UP
    				out_IMG[S_DN][j]++;		//DN
    				out_IMG[i][S_LL]++;		//LL
    				out_IMG[i][S_RR]++;		//RR
    			}
    		}
    	}
    }
    
    void S_SE_OperationBIG(uint8_t in_IMG[120][188], uint8_t out_IMG[120][188])
    {
    	u8 i, j;
    	//限制长宽避免溢出     使用图像小一圈
    	u8 img_H = 120 - 1;
    	u8 img_W = 188 - 1;
    	u8 S_UP, S_DN, S_LL, S_RR;
    	//输出数据初始化
    	for (i = 0; i < 120; i++)
    		for (j = 0; j < 188; j++)
    			out_IMG[i][j] = 0;
    	for (i = 1; i < img_H; i++)
    	{
    		S_UP = i - 1;
    		S_DN = i + 1;
    		for (j = 1; j < img_W; j++)
    		{
    			S_LL = j - 1;
    			S_RR = j + 1;
    			if (in_IMG[i][j])
    			{
    				out_IMG[i][j]++;
    				out_IMG[S_UP][j]++;		//UP
    				out_IMG[S_DN][j]++;		//DN
    				out_IMG[i][S_LL]++;		//LL
    				out_IMG[i][S_RR]++;		//RR
    			}
    		}
    	}
    }
    
    //腐蚀
    void S_Erode(uint8_t in_IMG[S_img_H][S_img_W], uint8_t out_IMG[S_img_H][S_img_W])
    {
    	S_SE_Operation(in_IMG, out_IMG);
    	S_BinaryImage(out_IMG, out_IMG, 3);				//交集
    }
    
    //膨胀
    void S_Dilate(uint8_t in_IMG[S_img_H][S_img_W], uint8_t out_IMG[S_img_H][S_img_W])
    {
    	S_SE_Operation(in_IMG, out_IMG);
    	S_BinaryImage(out_IMG, out_IMG, 0);				//并集
    }
    
    //开操作
    void S_Open(uint8_t in_IMG[S_img_H][S_img_W], uint8_t out_IMG[S_img_H][S_img_W])
    {
    	S_Erode(in_IMG, temp_IMG);				//腐蚀
    	S_Dilate(temp_IMG, out_IMG);			//膨胀
    }
    
    //关操作
    void S_Close(uint8_t in_IMG[S_img_H][S_img_W], uint8_t out_IMG[S_img_H][S_img_W])
    {
    	S_Dilate(in_IMG, temp_IMG);				//膨胀
    	S_Erode(temp_IMG, out_IMG);				//腐蚀 
    }
    
    
    //显示大图像到TFT模块
    void S_Draw_TFT_BIG(uint8_t in_IMG[IMAGEH][IMAGEW])
    {
    	u8 i = 0, j = 0;
    	//二值化图像显示
    	TFTSPI_Set_Pos(0, 0, 160 - 1, 120 - 1);          //定位字符显示区域              
    	for (i = 0; i < 120; i++)
    	{
    		for (j = 0; j < 160; j++)
    		{
    			if (in_IMG[i][j])
    				TFTSPI_Write_Word(0xffff);
    			else
    				TFTSPI_Write_Word(0x0000);
    		}
    	}
    }
    
    //显示小图像到TFT模块
    void S_Draw_TFT_MINI(uint8_t in_IMG[S_img_H][S_img_W])
    {
    	u8 i, j;
    	//二值化图像显示
    	TFTSPI_Set_Pos(0, 0, S_img_W - 1, S_img_H - 1);          //定位字符显示区域              
    	for (i = 0; i < S_img_H; i++)
    	{
    		for (j = 0; j < S_img_W; j++)
    		{
    			if (in_IMG[i][j])
    				TFTSPI_Write_Word(0xffff);
    			else
    				TFTSPI_Write_Word(0x0000);
    		}
    	}
    }
    
    
    // 图像 抽取压缩188X120 to 94X60
    void S_Image_zip(uint8_t in_IMG[IMAGEH][IMAGEW], uint8_t out_IMG[S_img_H][S_img_W])
    {
    	u8 i, j;
    	for (i = 0; i < S_img_H; i++)  //120行,每2行采集一行,
    		for (j = 0; j < S_img_W; j++)  //188,
    			out_IMG[i][j] = in_IMG[i * 2][j * 2];
    }
    
    // 图像 填充放大 94X60  to  188X120 
    void S_Image_larger(uint8_t in_IMG[S_img_H][S_img_W], uint8_t out_IMG[IMAGEH][IMAGEW])
    {
    	u8 i, j, iq, jq;
    	for (i = 0; i < S_img_H; i++)
    	{
    		iq = i * 2;
    		for (j = 0; j < S_img_W; j++)
    		{
    			jq = j * 2;
    			out_IMG[iq][jq] = out_IMG[iq + 1][jq + 1] =
    			out_IMG[iq][jq + 1] = out_IMG[iq + 1][jq] =
    			in_IMG[i][j];
    		}
    	}
    }
    
    
    /***************************************************************
    *
    * 函数名称:uint8_t GetOSTU(uint8_t tmImage[S_img_H][S_img_W])
    * 功能说明:求阈值大小
    * 参数说明:
    * 函数返回:阈值大小
    * 修改时间:2018年3月27日
    * 备 注:
    参考:https://blog.csdn.net/zyzhangyue/article/details/45841255
    	  https://www.cnblogs.com/moon1992/p/5092726.html
    	  https://www.cnblogs.com/zhonghuasong/p/7250540.html
    Ostu方法又名最大类间差方法,通过统计整个图像的直方图特性来实现全局阈值T的自动选取,其算法步骤为:
    1) 先计算图像的直方图,即将图像所有的像素点按照0~255共256个bin,统计落在每个bin的像素点数量
    2) 归一化直方图,也即将每个bin中像素点数量除以总的像素点
    3) i表示分类的阈值,也即一个灰度级,从0开始迭代
    4) 通过归一化的直方图,统计0~i 灰度级的像素(假设像素值在此范围的像素叫做前景像素) 所占整幅图像的比例w0,并统计前景像素的平均灰度u0;统计i~255灰度级的像素(假设像素值在此范围的像素叫做背景像素) 所占整幅图像的比例w1,并统计背景像素的平均灰度u1;
    5) 计算前景像素和背景像素的方差 g = w0*w1*(u0-u1) (u0-u1)
    6) i++;转到4),直到i为256时结束迭代
    7)将最大g相应的i值作为图像的全局阈值
    缺陷:OSTU算法在处理光照不均匀的图像的时候,效果会明显不好,因为利用的是全局像素信息。
    ***************************************************************/
    uint8_t S_GetOSTU(uint8_t tmImage[S_img_H][S_img_W])
    {
    	int16_t i, j;
    	uint32_t Amount = 0;
    	uint32_t PixelBack = 0;
    	uint32_t PixelIntegralBack = 0;
    	uint32_t PixelIntegral = 0;
    	int32_t PixelIntegralFore = 0;
    	int32_t PixelFore = 0;
    	double OmegaBack, OmegaFore, MicroBack, MicroFore, SigmaB, Sigma; // 类间方差; 
    	int16_t MinValue, MaxValue;
    	uint8_t Threshold = 0;
    	uint8_t HistoGram[256];              //  
    
    	for (j = 0; j < 256; j++)  HistoGram[j] = 0; //初始化灰度直方图 
    
    	for (j = 0; j < S_img_H; j++)
    	{
    		for (i = 0; i < S_img_W; i++)
    		{
    			HistoGram[tmImage[j][i]]++; //统计灰度级中每个像素在整幅图像中的个数
    		}
    	}
    
    	for (MinValue = 0; MinValue < 256 && HistoGram[MinValue] == 0; MinValue++);        //获取最小灰度的值
    	for (MaxValue = 255; MaxValue > MinValue && HistoGram[MinValue] == 0; MaxValue--); //获取最大灰度的值
    
    	if (MaxValue == MinValue)     return MaxValue;         // 图像中只有一个颜色    
    	if (MinValue + 1 == MaxValue)  return MinValue;        // 图像中只有二个颜色
    
    	for (j = MinValue; j <= MaxValue; j++)    Amount += HistoGram[j];        //  像素总数
    
    	PixelIntegral = 0;
    	for (j = MinValue; j <= MaxValue; j++)
    	{
    		PixelIntegral += HistoGram[j] * j;//灰度值总数
    	}
    	SigmaB = -1;
    	for (j = MinValue; j < MaxValue; j++)
    	{
    		PixelBack = PixelBack + HistoGram[j];    //前景像素点数
    		PixelFore = Amount - PixelBack;         //背景像素点数
    		OmegaBack = (double)PixelBack / Amount;//前景像素百分比
    		OmegaFore = (double)PixelFore / Amount;//背景像素百分比
    		PixelIntegralBack += HistoGram[j] * j;  //前景灰度值
    		PixelIntegralFore = PixelIntegral - PixelIntegralBack;//背景灰度值
    		MicroBack = (double)PixelIntegralBack / PixelBack;   //前景灰度百分比
    		MicroFore = (double)PixelIntegralFore / PixelFore;   //背景灰度百分比
    		Sigma = OmegaBack * OmegaFore * (MicroBack - MicroFore) * (MicroBack - MicroFore);//计算类间方差
    		if (Sigma > SigmaB)                    //遍历最大的类间方差g //找出最大类间方差以及对应的阈值
    		{
    			SigmaB = Sigma;
    			Threshold = j;
    		}
    	}
    	return Threshold;                        //返回最佳阈值;
    }
    
    //按照均值的比例进行二值化
    u8 S_Get_01_Value(uint8_t tmImage[S_img_H][S_img_W])
    {
    	int i = 0, j = 0;
    	u8 GaveValue;
    	u32 tv = 0;
    
    	//累加
    	for (i = 0; i < S_img_H; i++)
    	{
    		for (j = 0; j < S_img_W; j++)
    		{
    			tv += tmImage[i][j];   //累加  
    		}
    	}
    	GaveValue = tv / S_img_H / S_img_W;     //求平均值,光线越暗越小,全黑约35,对着屏幕约160,一般情况下大约100 
    	//按照均值的比例进行二值化
    	GaveValue = GaveValue * 8 / 10 + 10;        //此处阈值设置,根据环境的光线来设定 
    	return GaveValue;
    }
    
    
    void S_WeightedFiltering(uint8_t in_IMG[S_img_H][S_img_W], uint8_t out_IMG[S_img_H][S_img_W])
    {
    	s8 i, j;
    	s8 UP, DN, L, R;
    	for (i = 0; i < S_img_H; i++)
    	{
    		//防溢出
    		UP = i - 1;
    		if (UP < 0)	UP = 0;
    		DN = i + 1;
    		if (DN > S_img_H)	DN = S_img_H;
    		for (j = 0; j < S_img_W; j++)
    		{
    			//防溢出
    			L = j - 1;
    			if (L < 0)	UP = 0;
    			R = j + 1;
    			if (R > S_img_W)	DN = S_img_W;
    
    			if ((in_IMG[i][j]) && (in_IMG[i][L] + in_IMG[i][R] + in_IMG[UP][j] + in_IMG[DN][j] + 
    				in_IMG[UP][L] + in_IMG[UP][R] + in_IMG[DN][L] + in_IMG[DN][R] > 4))
    				out_IMG[i][j] = 1;
    			else
    				out_IMG[i][j] = 0;
    		}
    	}
    }
    
    
    
    extern u8 SS_ZipF[40][63];								//压缩图像数组		滤波使用
    /*
    ---------------------
    作者:吹泡泡的小猫
    来源:CSDN
    原文:https://blog.csdn.net/orbit/article/details/7323090
    版权声明:本文为博主原创文章,转载请附上博文链接!*/
    typedef struct tagDIRECTION
    {
    	int x_offset;
    	int y_offset;
    }DIRECTION;
    
    DIRECTION direction_8[] = { {-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1} };
    //DIRECTION direction_4[] = { {-1, 0}, {0, 1}, {1, 0}, {0, -1} };
    DIRECTION direction_4[] = { {-1, 0}, {1, 0}, {0, 1}, {0, -1} };
    #define directionXX	direction_4
    //注入填充算法(Flood Fill Algorithm)
    void S_FloodSeedFill(uint8_t in_IMG[S_img_H][S_img_W], u8 x, u8 y, u8 old_color, u8 new_color)
    {
    	if (x > 58 || y > 92 || x < 1 || y < 1)		return;			//避免溢出
    	if (in_IMG[x][y] == old_color)
    	{
    		in_IMG[x][y] = new_color;
    		//ImgZip_FLU[x][y] = 1;
    		for (int i = 0; i < 4; i++)			// i <COUNT_OF(directionXX)
    		{
    			S_FloodSeedFill(in_IMG, x + directionXX[i].x_offset,
    				y + directionXX[i].y_offset, old_color, new_color);
    		}
    	}
    }
    
    //不使用递归  不会溢出版本
    void SX_FloodSeedFill(uint8_t in_IMG[40][63], u8 x, u8 y, u8 old_color, u8 new_color)
    {
    	u8 i, j, k;
    	u8 return_sign;
    	in_IMG[x][y] = 255;		//过渡颜色
    	for (;;)
    	{
    		return_sign = 0;
    		for (i=0;i<40;i++)
    			for (j = 0; j < 63; j++)
    			{
    				if (in_IMG[i][j] == 255)		//过渡颜色
    				{
    					in_IMG[i][j] = new_color;		//实际赋值
    					SS_ZipF[i][j] = 1;
    					for (k = 0; k < 4; k++)
    					{
    						x = i + directionXX[k].x_offset;		y = j + directionXX[k].y_offset;
    						if (x < 40 && y < 63 && x >= 0 && y >= 0)		//避免溢出
    							if (in_IMG[x][y] == old_color)
    							{
    								in_IMG[x][y] = 255;		//过渡颜色
    								return_sign = 1;
    							}
    					}
    				}
    			}
    
    		if (return_sign == 0)		return;
    	}
    }
    
    
    //在一幅图像中判定  横穿图像的白块			未实现
    u8 S_Linear(u8 height, u8 width, uint8* in_IMG)
    {
    	u8 i, j, m, n, up, dn;
    	u8 getONE = 0;
    
    	u8 LL_h, LL_w;
    	u8 RR_h, RR_w;
    
    	for (i=20;i< height-20;i++)
    	{
    		j = 0;
    		while (j<5)		//在5点内寻得白点
    		{
    			if (in_IMG[i * width + j++])
    			{
    				LL_h = i;		LL_w = j - 1;		//记录左点坐标
    				up = i - 7;			dn = i + 7;
    				for (m = up; m < dn; m++)
    				{
    					n = width - 1;
    					while (n > width + 5)		//在5点内寻得白点
    					{
    						if (in_IMG[m * width + n--])
    						{
    							RR_h = m;		RR_w = n + 1;		//记录右点坐标
    
    							float kk, bb;
    							kk = (float)(LL_h - RR_h) / (LL_w - RR_w);
    							bb = (float)(LL_h - kk * LL_w);
    
    
    							u8 ww, ww_COUNT = 0;
    							for (ww = LL_w + 10; ww < RR_w - 10; ww += 10)
    							{
    								if (!in_IMG[(u8)(kk * ww + bb) * width + ww])			//如果黑
    									ww_COUNT = 1;
    							}
    							if (ww_COUNT == 0)
    								return 1;
    
    							break;
    						}
    					}
    				}		
    				break;
    			}
    		}
    	}
    	return	0;
    }
    
    
    
    //参数解释:宽 高 图像指针 起始行  起始列 处理行大小  处理列大小
    #define GrayScale 256   //frame灰度级
    uint8 pixel[GrayScale];
    uint8 S_Other_OSTU(int width, int height, uint8* Image)
    {
    	int threshold = 0;
    	int32_t sum_gray = 0;
    	int32_t sum_pix_num = 0;
    	int32_t pl_pix_num = 0;
    	int32_t p2_pix_mum = 0;
    	int32_t p1_sum_gray = 0;
    	float m1 = 0;
    	float m2 = 0;
    	float V = 0;
    	float variance = 0;
    	int i, j, k = 0;
    
    	for (i = 0; i < 256; i++)
    		pixel[i] = 0;
    	//统计每个灰度级中像素的个数   
    	for (i = 0; i < height; i++)
    	{
    		for (j = 0; j < width; j++)
    		{
    			pixel[(int)Image[i * width + j]]++;
    		}
    	}
    
    	for (k = 0; k < GrayScale; k++)
    	{
    		sum_gray += k * pixel[k];//灰度直方图质量矩
    		sum_pix_num += pixel[k];//总像素个数
    	}
    
    	for (k = 0; k < GrayScale - 1; k++)
    	{
    		pl_pix_num += pixel[k];//第一部分像素个数
    		p2_pix_mum = sum_pix_num - pl_pix_num;//第二部分像素个数
    		p1_sum_gray += k * pixel[k];   //第一部分质量矩
    		m1 = (float)p1_sum_gray / pl_pix_num;//第一部分灰度均值
    		m2 = (float)(sum_gray - p1_sum_gray) / p2_pix_mum;//第二部分灰度均值
    
    		V = pl_pix_num * p2_pix_mum * (m1 - m2) * (m1 - m2);
    
    		if (V > variance)//将类间方差较大时的灰度值作为阈值
    		{
    			variance = V;
    			threshold = k;
    		}
    	}
    	return threshold;
    }
    
    
    /************************************Robert算子************************************
    **			Gx={	{1,  0},					   Gy={	{  0,  1},
    **				    {0,-1}}						  	    {-1,  0}}
    **		最右、最底边缘舍去		
    **		G(x,y)=abs(f(x,y)-f(x+1,y+1))+abs(f(x,y+1)-f(x+1,y))
    ***********************************************************************************/
    #define Robert_G(addr, y, x)	(abs(addr[y, x] - addr[DN, RR]) + abs(addr[y, RR] - addr[DN, x]))
    void S_Robert(uint8_t in_IMG[PixMini_H][PixMini_W], uint8_t out_IMG[PixMini_H][PixMini_W])
    {
    	u8 i, j;
    	u8 DN, RR;
    	for (i = 0; i < 59; i++)
    	{
    		DN = i + 1;
    		for (j = 0; j < 93; j++)
    		{
    			RR = j + 1;
    			out_IMG[i][j] = Robert_G(in_IMG, i, j);
    		}
    	}
    }
    
    /************************************Sobel算子************************************
    **			Gx={	{-1,  0,  1},					Gy={	{  1,  2,  1},
    **				    {-2,  0,  2},						    {  0,  0,  0},
    **				    {-1,  0,  1}}				   			{ -1, -2, -1}}
    **		最上下左右边缘舍去
    **
    **		Gx = (-1)*f(x-1, y-1) + 0*f(x,y-1) + 1*f(x+1,y-1)
    **			  +(-2)*f(x-1,y) + 0*f(x,y)+2*f(x+1,y)
    **			  +(-1)*f(x-1,y+1) + 0*f(x,y+1) + 1*f(x+1,y+1)
    **		= [f(x+1,y-1)+2*f(x+1,y)+f(x+1,y+1)]-[f(x-1,y-1)+2*f(x-1,y)+f(x-1,y+1)]
    **		
    **		Gy =1* f(x-1, y-1) + 2*f(x,y-1)+ 1*f(x+1,y-1)
    **			  +0*f(x-1,y) 0*f(x,y) + 0*f(x+1,y)
    **			  +(-1)*f(x-1,y+1) + (-2)*f(x,y+1) + (-1)*f(x+1, y+1)
    **		= [f(x-1,y-1) + 2f(x,y-1) + f(x+1,y-1)]-[f(x-1, y+1) + 2*f(x,y+1)+f(x+1,y+1)]
    **		若Threshold=0则输出灰度图		其他则二值化
    ***********************************************************************************/
    #define Sobel_Gx(addr, y, x)	(addr[UP][RR]+2*addr[y][RR]+addr[DN][RR]-(addr[UP][LL]+2*addr[y][LL]+addr[DN][LL]))
    #define Sobel_Gy(addr, y, x)	(addr[UP][LL]+2*addr[UP][x]+addr[UP][RR]-(addr[DN][LL]+2*addr[DN][x]+addr[DN][RR]))
    #define Sobel_G(addr, y, x)		(abs(Sobel_Gx(addr, y, x)) + abs(Sobel_Gy(addr, y, x)))
    void S_Sobel(uint8_t in_IMG[PixMini_H][PixMini_W], uint8_t out_IMG[PixMini_H][PixMini_W],u8 Threshold)
    {
    	u8 i, j;
    	u8 UP, DN, LL, RR;
    	if (Threshold == 0)
    	{
    		for (i = 1; i < 59; i++)
    		{
    			DN = i + 1;		UP = i - 1;
    			for (j = 1; j < 93; j++)
    			{
    				RR = j + 1;		LL = j - 1;
    				out_IMG[i][j] = Sobel_G(in_IMG, i, j);
    			}
    		}
    	}
    	else
    	{
    		for (i = 1; i < 59; i++)
    		{
    			DN = i + 1;		UP = i - 1;
    			for (j = 1; j < 93; j++)
    			{
    				RR = j + 1;		LL = j - 1;
    				out_IMG[i][j] = (Sobel_G(in_IMG, i, j) >= Threshold ? 1 : 0);
    			}
    		}
    	}
    
    }
    //sobel 定制
    //在已有二值化的图像中标记边缘
    void S_Sobel_Custom(uint8_t in_IMG[PixMini_H][PixMini_W], uint8_t out_IMG[PixMini_H][PixMini_W], u8 Threshold)
    {
    	u8 i, j;
    	u8 UP, DN, LL, RR;
    	u16 TempVal;
    	for (i = 1; i < 58; i++)		//HIGH	只计算前50行
    	{
    		DN = i + 1;		UP = i - 1;
    		for (j = 1; j < 93; j++)	//WIDE
    		{
    			RR = j + 1;		LL = j - 1;
    			TempVal = Sobel_G(in_IMG, i, j);
    			if (TempVal >= Threshold)
    			{
    				out_IMG[i][j] = S_S_Custom;
    			}
    		}
    	}
    
    }
    
    
    /******************************60*94图像显示成188*120***********************************
    **
    *******************************************************************************************/
    void S_DisplayMINI_Big(uint8_t in_IMG[PixMini_H][PixMini_W])
    {
    	u8 i, j, k;
    	u16 color;   
    
    	TFTSPI_Set_Pos(0, 0, 188 - 1, 120 - 1);          //定位字符显示区域     
    	for (i = 0; i < PixMini_H; i++)
    	{
    		for (k = 0; k < 2; k++)
    			for (j = 0; j < PixMini_W; j++)
    			{
    				if (in_IMG[i][j] == 1)
    					color = u16WHITE;
    				else if (in_IMG[i][j] == S_S_Custom)
    					color = u16PURPLE;
    				else
    					color = u16BLACK;
    
    				TFTSPI_Write_Word(color);
    				TFTSPI_Write_Word(color);
    			}
    	}
    }
    
    /******************************60*94图像显示灰度图***********************************
    **		size==S_BIG		显示大图																							**
    **		size==S_MINI	显示小图																							**
    ***************************************************************************************/
    void S_Gray_DisplayMINI(uint8_t in_IMG[PixMini_H][PixMini_W], u8 size)
    {
    	u8 i, j, k;
    	u16 color, temp;
    
    	if (size== S_MINI)			//显示小图
    	{
    		TFTSPI_Set_Pos(0, 0, 94 - 1, 60 - 1);          //定位字符显示区域              
    		for (i = 0; i < 60; i++)
    		{
    			for (j = 0; j < 94; j++)
    			{
    				temp = in_IMG[i][j];
    				color = (0x001f & ((temp) >> 3)) << 11;
    				color = color | (((0x003f) & ((temp) >> 2)) << 5);
    				color = color | (0x001f & ((temp) >> 3));
    				TFTSPI_Write_Word(color);
    			}
    		}
    	}
    	else								//显示大图
    	{
    		TFTSPI_Set_Pos(0, 0, 188 - 1, 120 - 1);          //定位字符显示区域              
    		for (i = 0; i < 60; i++)
    		{
    			for (k = 0; k < 2; k++)
    				for (j = 0; j < 94; j++)
    				{
    					temp = in_IMG[i][j];
    					color = (0x001f & ((temp) >> 3)) << 11;
    					color = color | (((0x003f) & ((temp) >> 2)) << 5);
    					color = color | (0x001f & ((temp) >> 3));
    
    					TFTSPI_Write_Word(color);				TFTSPI_Write_Word(color);
    				}
    		}
    	}
    }
    
    /******************************120*188图像显示灰度图************************************
    **		 																			**
    **************************************************************************************/
    void S_Gray_Display(uint8_t in_IMG[IMAGEH][IMAGEW])
    {
    	u8 i, j;
    	u16 color, temp;
    	TFTSPI_Set_Pos(0, 0, 188 - 1, 120 - 1);          //定位字符显示区域              
    	for (i = 0; i < 120; i++)
    	{
    		for (j = 0; j < 188; j++)
    		{
    			temp = in_IMG[i][j];
    			color = (0x001f & ((temp) >> 3)) << 11;
    			color = color | (((0x003f) & ((temp) >> 2)) << 5);
    			color = color | (0x001f & ((temp) >> 3));
    			TFTSPI_Write_Word(color);
    		}
    	}
    }
    
    /*********************************三线图检测识别**************************************
    **								Mod=0	寻二值化	Mod=2	寻sobel														**
    ***************************************************************************************/
    void DetectionLine(	uint8_t in_IMG[PixMini_H][PixMini_W],		//输入图像
    								RunWay_* out_Array, 			//输出数组
    								u8 LMP,							//输入中点
    								u8 Mod)							//检测模式
    {
    	u8 i, j;
    	u8 M_Point, L_Point, R_Point;
    	u8 get_Point;
    
    	M_Point = LMP;                         //取输入的底部中点
    
    	for (i = 58; i > 0; i--)					//行数
    	{
    		/**/
    		//寻左点
    		j = M_Point + 5;
    		if (j < 99 && j>92)       j = 92;
    		while (!((!in_IMG[i][j + Mod]) && in_IMG[i][j + 1]) && (j > 1)) { j--; }
    		L_Point = j;
    		//寻右点
    		j = M_Point - 5;
    		if (j > 99)						j = 1;
    		while (!((!in_IMG[i][j - Mod]) && in_IMG[i][j - 1]) && (j < 92)) { j++; }
    		R_Point = j;
    
    		/*
    		//寻左点
    		get_Point = 0;
    		for (j = M_Point + 5; j > 0; j--)
    		{
    			//防溢出
    			//if (j < 0)         j = 0;
    			//if (j > 187)        j = 187;
    			if (in_IMG[i][j]== Mod)
    			{
    				L_Point = j;
    				get_Point = 1;		//取得点
    				break;
    			}
    		}
    		if (get_Point==0)                    //取最左边的黑点
    		{
    			L_Point = 0;
    		}
    
    		//寻右点
    		get_Point = 0;
    		for (j = M_Point - 5; j < 59; j++)
    		{
    			//防溢出
    			//if (j < 0)        j = 0;
    			//if (j > 187)       j = 187;
    			if (in_IMG[i][j] == Mod)
    			{
    				R_Point = j;
    				get_Point = 1;		//取得点
    				break;
    			}
    		}
    		if (get_Point == 0)						//取最右边的黑点
    		{
    			R_Point = 93;
    		}
    */
    
    
    		M_Point = (L_Point + R_Point) / 2;                         //取上一行中点
    		out_Array->M[i] = M_Point;
    		out_Array->L[i] = L_Point;
    		out_Array->R[i] = R_Point;
    
    		/**/
    		//归线
    		if (i <= 55)
    		{
    			//断开丢线x
    			u8 fg_no_c = 0;
    			if (i <= 30)
    				if (abs(M_Point - out_Array->M[i + 1]) >= 5)			//连续两行中点相差5点以上
    				{
    					if (M_Point >= 50)
    						fg_no_c = 1;
    					else if (M_Point <= 45)
    						fg_no_c = 2;
    				}
    
    
    			if ((M_Point < 25) || (fg_no_c == 2))
    			{
    				for (; i > 0; i--)
    				{
    					out_Array->M[i] = 3;
    					out_Array->L[i] = 3;
    					out_Array->R[i] = 3;
    				}
    				break;
    			}
    			else if ((M_Point > 69) || (fg_no_c == 1))
    			{
    				for (; i > 0; i--)
    				{
    					out_Array->M[i] = 90;
    					out_Array->L[i] = 90;
    					out_Array->R[i] = 90;
    				}
    				break;
    			}
    		}
    	}
    	//TFTSPI_P6X8Int(20, 5, L_Point, u16WHITE, u16BLACK);
    	//TFTSPI_P6X8Int(20, 6, R_Point, u16WHITE, u16BLACK);
    	//S_DisplayRunWay(out_Array);
    }
    
    
    /******************************三线图检测识别结合sobel定制********************************
    **							  														**
    ***************************************************************************************/
    void DetectionLine_Custom(	uint8_t in_IMG[PixMini_H][PixMini_W],		//输入图像
    							RunWay_* out_Array, 			//输出数组
    							u8 LMP)							//输入中点
    {
    	u8 i, j;
    	u8 M_Point, L_Point, R_Point;
    	u8 get_Point;
    
    	M_Point = LMP;                         //取输入的底部中点
    
    	for (i = 57; i > 0; i--)					//行数
    	{
    		/**/
    		//寻左点
    		j = M_Point + 2;
    		if (j < 99 && j>90)       j = 90;		//图像右侧2点像素不可用
    		while (!(in_IMG[i][j] == S_S_Custom) && (j > 1)) { j--; }
    		L_Point = j;
    		//寻右点
    		j = M_Point - 2;
    		if (j > 99)						j = 1;
    		while (!(in_IMG[i][j] == S_S_Custom) && (j < 92)) { j++; }
    		R_Point = j;
    
    		/*
    		//寻左点
    		get_Point = 0;
    		for (j = M_Point + 5; j > 0; j--)
    		{
    			//防溢出
    			//if (j < 0)         j = 0;
    			//if (j > 187)        j = 187;
    			if (in_IMG[i][j]== Mod)
    			{
    				L_Point = j;
    				get_Point = 1;		//取得点
    				break;
    			}
    		}
    		if (get_Point==0)                    //取最左边的黑点
    		{
    			L_Point = 0;
    		}
    
    		//寻右点
    		get_Point = 0;
    		for (j = M_Point - 5; j < 59; j++)
    		{
    			//防溢出
    			//if (j < 0)        j = 0;
    			//if (j > 187)       j = 187;
    			if (in_IMG[i][j] == Mod)
    			{
    				R_Point = j;
    				get_Point = 1;		//取得点
    				break;
    			}
    		}
    		if (get_Point == 0)						//取最右边的黑点
    		{
    			R_Point = 93;
    		}
    */
    
    
    		M_Point = (L_Point + R_Point) / 2;                         //取上一行中点
    		out_Array->M[i] = M_Point;
    		out_Array->L[i] = L_Point;
    		out_Array->R[i] = R_Point;
    
    		/**/
    		//归线
    		if (i <= 55)
    		{
    			//断开丢线x
    			u8 fg_no_c = 0;
    			if (i <= 30)
    				if (abs(M_Point - out_Array->M[i + 1]) >= 5)			//连续两行中点相差5点以上
    				{
    					if (M_Point >= 50)
    						fg_no_c = 1;
    					else if (M_Point <= 45)
    						fg_no_c = 2;
    				}
    
    
    			if ((M_Point < 25) || (fg_no_c == 2))
    			{
    				for (; i > 0; i--)
    				{
    					out_Array->M[i] = 3;
    					out_Array->L[i] = 3;
    					out_Array->R[i] = 3;
    				}
    				break;
    			}
    			else if ((M_Point > 69) || (fg_no_c == 1))
    			{
    				for (; i > 0; i--)
    				{
    					out_Array->M[i] = 90;
    					out_Array->L[i] = 90;
    					out_Array->R[i] = 90;
    				}
    				break;
    			}
    		}
    	}
    	//TFTSPI_P6X8Int(20, 5, L_Point, u16WHITE, u16BLACK);
    	//TFTSPI_P6X8Int(20, 6, R_Point, u16WHITE, u16BLACK);
    	//S_DisplayRunWay(out_Array);
    }
    
    
    RunWay_ TempArray;
    void S_DisplayRunWay(RunWay_* in_Array)
    {
    	u8 i, j;
    
    	for (i = 0; i < 60; i++)
    	{
    		if (i % 10 == 0)		//画线标记  刻度
    		{
    			TFTSPI_Draw_Dot(0, i, u16RED);
    			TFTSPI_Draw_Dot(1, i, u16RED);
    			TFTSPI_Draw_Dot(2, i, u16RED);
    		}
    
    		//抹上次点
    		TFTSPI_Draw_Dot(TempArray.M[i], i, 0x0000);
    		TFTSPI_Draw_Dot(TempArray.L[i], i, 0x0000);
    		TFTSPI_Draw_Dot(TempArray.R[i], i, 0x0000);
    		//记录旧点
    		TempArray.L[i] = in_Array->L[i];
    		TempArray.M[i] = in_Array->M[i];
    		TempArray.R[i] = in_Array->R[i];
    		//显示新点
    		TFTSPI_Draw_Dot(in_Array->M[i], i, u16YELLOW);
    		TFTSPI_Draw_Dot(in_Array->L[i], i, u16YELLOW);
    		TFTSPI_Draw_Dot(in_Array->R[i], i, u16YELLOW);
    	}
    }
    
    void S_DRW_Big(RunWay_* in_Array)
    {
    	u8 i, j, k, kk;
    
    	for (i = 0; i < 60; i++)
    	{
    		for (k = 0; k < 2; k++)
    		{
    			kk = 2 * i + k;
    			if (kk % 10 == 0)		//画线标记  刻度
    			{
    				TFTSPI_Draw_Dot(0, kk, u16RED);
    				TFTSPI_Draw_Dot(1, kk, u16RED);
    				TFTSPI_Draw_Dot(2, kk, u16RED);
    			}
    
    			//抹上次点
    			TFTSPI_Draw_Dot(TempArray.M[i] * 2, kk, 0x0000);
    			TFTSPI_Draw_Dot(TempArray.L[i] * 2, kk, 0x0000);
    			TFTSPI_Draw_Dot(TempArray.R[i] * 2, kk, 0x0000);
    			//显示新点
    			TFTSPI_Draw_Dot(in_Array->M[i] * 2, kk, u16CYAN);
    			TFTSPI_Draw_Dot(in_Array->L[i] * 2, kk, u16ORANGE);
    			TFTSPI_Draw_Dot(in_Array->R[i] * 2, kk, u16GREEN);
    		}
    		//记录旧点
    		TempArray.L[i] = in_Array->L[i];
    		TempArray.M[i] = in_Array->M[i];
    		TempArray.R[i] = in_Array->R[i];
    	}
    }
    
    
    
    
    展开全文
  • 飞思卡尔 智能车 摄像头 图像采集 处理
  • 最近心情有些浮躁,花点时间记录一下做以来学到的一点知识 一、Sobel算子理论基础 梯度:图像中像素点发生跃迁的地方 图像中蓝色箭头标注的地方就是像素点变化较大的地方 传统Sobel算子 3×3的Sobel算子,...

    前言

    	最近心情有些浮躁,花点时间记录一下做车以来学到的一点知识
    

    一、Sobel算子理论基础

    1. 梯度:图像中像素点发生跃迁的地方
      在这里插入图片描述

      图像中蓝色箭头标注的地方就是像素点变化较大的地方
      
    2. 传统Sobel算子
      在这里插入图片描述

      3×3的Sobel算子,分别计算水平方向和垂直方向的梯度,临近所计算像素点的差值权值较大

    二、处理结果

    1.sobel算子直接处理结果

    在这里插入图片描述
    可以看到直接使用传统sobel算子得到图像会得到多余的梯度,因为存在梯度的相邻像素点会计算两次,如果剔除掉白色赛道内像素点内计算得到的梯度得到的图像会好一些

    2.引入边缘细化思想后的处理结果

    在这里插入图片描述
    这里采用极大抑制的思想,或者用阈值代替极大抑制都可以取得不错的效果
    在这里插入图片描述

    总结

    以上均为个人理解,有不对的地方实属正常,希望路过的大佬点拨一二

    展开全文
  • 智能车摄像头组 障碍处理方法

    千次阅读 2016-12-10 22:24:14
    智能车摄像头组中最重要的就是图像处理了,这里面的图像处理包括很多方面,比如十字如何处理,弯道如何处理,起跑线,障碍等等问题,接下来我要讲的就是障碍处理方法。  首先我们先描述一下障碍的形状,在智能车...

       智能车摄像头组中最重要的就是图像处理了,这里面的图像处理包括很多方面,比如十字如何处理,弯道如何处理,起跑线,障碍等等问题,接下来我要讲的就是障碍处理方法。

      首先我们先描述一下障碍的形状,在智能车竞赛中障碍是一个长方形,距离边界有5CM的距离,这样在图像上显示出来时候就是(图1)所显示的样子

    在这里面我们可以看到中线有明显的偏移,右边界也有明显的跳变,那么这个跳变我要怎么去提取呢,我第一步用的就是中心线的方差,通过计算方差来判断是否能够进入障碍程序,当中线的方差满足障碍条件后进入障碍处理程序,但是往往一个判断是不够准确的,进入这一个条件后我去判断边界的连续性,就是通过边界的跳变去查找,程序上如何实现呢,最简单的就是这样一句话。

             if(cha1>=2&&abs(cha3-cha1)<=2&&abs(cha2-cha3)<=2)
    在这里面cha1,cha2,cha3的定义呢就是

            cha1=right_line[1][i-3]-right_line[1][i];
            cha2=right_line[1][i-3]-right_line[1][i+1];
            cha3=right_line[1][i-3]-right_line[1][i+2];
    这里的定义就顾名思义了,就是判断连续点之间的差分,进而可以判断是否有跳变。判断完跳变之后呢还是不能达到100%的准确率。接下来在做的判断就是找到中间这个黑色的障碍,通常这个障碍所占的位置比较大,而且在中线与右边界的中间部分向上搜索一定会有黑色的障碍出现,那么这个时候就可以判断出来这个位置是障碍了,这段程序呢也很简单,就判断黑白就可以了。

       当障碍处理完成后要怎么做呢,接下来就是控制的问题,在我这里控制就是将从障碍开始以后所有的中线都移向左边,这样就可以控制小车很轻松的避开障碍了。以上说的是障碍在赛道右侧的时候,如果在赛道左侧则同理就能得出。并且起跑线处理方法也类似。如果出现剐蹭现象只需改变一下舵机P值就可以得到很好地改善效果了。具体程序见评论中的链接,因为纯属自己编写的程序所以不是免费下载的。如果有其他需求大家可以联系我继续写一些图像处理方法。小车的效果可以在本人QQ空间中观看,有视频。 联系方式见评论。




    展开全文
  • 或许是有幸,参加了第十五届智能车竞赛,在这一年里,经历了很多,少有满意,认识了很多人,感谢相识。 比赛将要结束,我也将离智能车越来越远。但毕竟也曾热爱、付出过,希望能把我的一些经验写下来,至少留下一个...
  • 目前全国大学生智能车竞赛发展越来越快,很多新手入手难,本文介绍了摄像头组的相关软件问题,包括图像处理,控制算法,结构搭建等光机电算各方面的知识。
  • 基于CCD 或者CMOS 模拟摄像头智能车程 序主要包含以下部分: --图像,速度,加速度等数据采集; --数字图象处理,从图像中获取赛道信息; --以赛道信息,速度,加速度等传感器数据为 输入参数进行自动控制,有PID...
  • 第八届智能小车摄像头组程序 包括图像采集,图像处理(黑线提取),舵机控制,电机控制 处理器:XS128 摄像头:ov7620 图像处理包括了黑线提取,赛道还原,虚线处理,十字弯甄别等 电机控制:pid控制速度
  • 智能车图像部分——摄像头寻迹

    千次阅读 多人点赞 2021-01-02 22:23:13
    智能车图像部分(学习笔记) (1)摄像头基本原理 ·中断处理 pclk 每输出一个像素值产生一次 href 每输出完一行产生一次 vsync 每输出一场产生一次 ...(2)摄像头图像处理 (3)摄像头代码框架 ...
  • 浅谈智能车摄像头组斜入十字处理方法

    万次阅读 多人点赞 2017-03-17 17:28:49
    全国大学生智能车竞赛摄像头组中的难点其中之一我认为就是十字路况的一个处理方法,进入十字的情况多种多样,有从直道进入十字的情况这种情况是在十字中最容易处理的情况,通常直接向上搜索边界就可以得到很好的结果...
  • 飞思卡尔之摄像头图像处理——初始化

    千次阅读 多人点赞 2018-03-09 13:15:27
    今天是2018年3月9日,在经过一段时间熟悉赛道和小车特性之后,我正式开始飞思卡尔智能车图像处理学习,并负责我们组 图像算法的编写.首先是图像的二值化处理 二值化算法的思路是:设定一个阈值valve,对于视频...
  • 飞思卡尔智能车大赛摄像头组程序。涉及信号采集、A/D转换、图像处理
  • 恩智浦智能车摄像头循迹部分

    千次阅读 2020-07-10 09:35:53
    恩智浦智能车摄像头循迹部分 对于恩智浦智能车竞赛已经举行了14届,从以往的电磁车已经逐渐转变成了用摄像头进行循迹。与电磁循迹对比,摄像头拥有着诸多优势,但摄像头对于很多新手入门来说却是比较困难的。下面将...
  • 能够通过这个上位机在线的导入图片,对图片进行图像处理
  • 飞思卡尔智能车 摄像头组 第六届 图像采集、图像处理程序,可供参考
  • 关于光电直立组的摄像头处理程序,包含路障判断、起跑检测等。资源为c源文件,是摄像头图像处理的核心文件。
  • 第九届飞思卡尔智能车摄像头平衡组东北赛一等奖源代码,在图像处理和控制方面有独到的思想。
  • MATLAB图像采集:能够通过蓝牙模块接受摄像头图像信息将其使用MATLAB进行处理,程序中接口已经写好,可在相应部分更改图像分辨率、蓝牙名称,就可用于机器人,智能车等的轻量级摄像头图像处理开发文件列表:1.bmp10....
  • 智能车图像处理之透视变换

    千次阅读 多人点赞 2020-09-12 16:52:57
    智能车竞赛中,通过摄像头对赛道信息的采集,在单片机上提取赛道两边的边缘,经过处理后控制小车在赛道边缘内行驶。但由于摄像头与赛道之间存在一定的仰角,使得摄像头采集回来的赛道得两条边缘不再平行,甚至在...
  • 飞思卡尔智能车大赛摄像头组程序,内含信号采集、A/D转换、图像处理相关方法。
  • 其中摄像头模块一向是本比赛的一个强力的导航方式,使用摄像头模块则离不开参赛队员们自己所编写的图像处理程序。图像处理程序的质量直接影响了车子寻迹的性能。试想连车子对图像信息处理都不准确,控制再好又如何...
  • 第X届智能车摄像头组代码全解析 ------(一)前言

    千次阅读 多人点赞 2018-12-13 20:40:17
    还不止这些,而我写这系列博客的原因是着重写那些不变的东西,包括PID啊,图像处理啊,等等。这里我会以一个成熟代码作为介质来讲透,因为我是第十三届选手,所以就以十三届的代码来讲些不变的东西,后面也会模块化...
  • 斯坦福大学设计新型AI摄像头,能更快对图像进行分类当今自动驾驶汽车和航空无人机的图像识别技术都依赖于人工智能:一般是计算机教会自己识别狗、穿过街道的行人或停下来的汽车等物体。问题是,目前运行人工智能算法...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 153
精华内容 61
关键字:

智能车摄像头图像处理