|
本帖最后由 lidreamer 于 2014-4-21 21:45 编辑
摄像头本来是能采集出来二值化图像的,
但是加了中线提取算法之后出来的图像就是这样的。
这难道是提取中线的程序太长?我用的是K60,摄像头采集100行40列,,
求指导。
附上我的来自岱默提取中线算法。
#include "common.h"
#include "include.h"
#define BLACK 0x00
#define WHITE 0xfe
#define ThreadHold 0x30
#define rowStart 10 //图像处理起始行数
#define rowEnd 50 //图像处理终止行数
#define rowNum rowEnd-rowStart //有效处理行数,原始采集行数为ROW(在Include.h中定义)
#define proPix 5 //边缘跟踪搜索边界有效像素
#define CENTURE 154 //中心值
#define EDGE WHITE-BLACK //边界值大小
u8 Buffer1[ROW][COL]={0}; //通过DMA采集(在isr.c中行中断中触发DMA采集)二维图像存储于Buffer1数组中,ROW,COL在Include.h中定义
void Send_Image();
u32 zuo[rowNum] = {0}; //存放有效处理行中双线左边缘的列坐标,初始化为0
u32 you[rowNum] = {COL-1}; //存放有效处理行中双线右缘的列坐标,初始化为COL-1
s32 zuoPos = 0; //左边界位置[有符号数]
s32 youPos = 0; //右边界位置[有符号数]
u32 centure = 0; //计算出的当前车体的中心位置[无符号数]
s32 centureErr = 0; //计算出的当前车体位置偏差 [有符号数]
s32 turn = 0; //边界走势 正为向左偏转 负为向右偏转
u8 zuoEdgeFlag = 0; //左边界确认标志,找到后边界置位
u8 youEdgeFlag = 0; //右边界确认标志,找到后边界置位
u8 centure1;
u8 VSYN_Flag = 0; //完成一场标识位 0为未完成;1为完成
u8 time;
u8 Image_Center[ROW]={0};
u8 ImageBuf[ROW][COL];
void ImageProc();
void Send_Image();
volatile u8 VSYN = 1;
volatile u32 rowCnt = 0 ;
void main()
{
DisableInterrupts;
sccb_init();
//----------SCCB寄存器配置---------------//
sccb_regWrite(0x42,0x11,0x03); //地址0X11-中断四分频(640*240) PCLK:166ns HREF:254.6us VSYN:133.6ms
sccb_regWrite(0x42,0x14,0x24); //地址0X14-QVGA(320*120) PCLK:332ns HREF:509.6us VSYN:133.6ms
sccb_regWrite(0x42,0x28,0x20); //地址0X28-连续采集模式(320*240) PCLK:666ns HREF:509.6us VSYN:133.6ms
sccb_wait();
//----初始化图像数组----//
uart_init (UART0, 115200);
exti_init(PORTA, 9, rising_down); //HREF----PORTA3 端口外部中断初始化 ,上升沿触发中断,内部下拉
exti_init(PORTA, 27, falling_down); //VSYN----PORTA5 端口外部中断初始化 ,上升沿触发中断,内部下拉
// EnableInterrupts;
while(1)
{
ImageProc();
Send_Image();
EnableInterrupts;
}
}
void ImageProc()
{
u32 i,j;
//DisableInterrupts; //禁止中断
uart_putchar(UART0,0);
//---------图像二值化,小于阈值为BLACK,大于阈值为WHITE---------
for(i=0; i<ROW; i++)
{
for(j=0;j<COL ;j++)
{
if(ImageBuf[j] <= ThreadHold)
ImageBuf[j]=BLACK;
else
ImageBuf[j]=WHITE;
}
}
//----------------边缘搜索开始-----------------//
//--------搜索rowStart前一行左右边缘点作为基准----------
for(i=rowStart-1,time= 100;time>0 ;time--) //至多搜索100次 防止1次未搜索到边缘
{
for(j=49;j>1;j--) //左边缘搜索
{
if(Buffer1[j]-Buffer1[j-1] == EDGE ) //从白跳变到黑 WHITE-BLACK
{
zuoPos = j;
break;
}
else
{
zuoPos = j; //未搜索到边界
continue;
}
}
//-------------左边缘搜索END------------------
//------------右边缘搜索------------------
for(j=50;j<COL-1;j++) //右边缘搜索
{
if(Buffer1[j]-Buffer1[j+1] == EDGE) //从白跳变到黑 WHITE-BLACK (1-0)
{
youPos = j;
break;
}
else
{
youPos = j; //未搜索到边界
continue;
}
}
//-------------右边缘搜索END-----------------
if( zuoPos == 2 && youPos == COL-2) //未搜到边界 图像异常 继续搜索
continue;
else
break; //搜索到退出
}
//-------------基准点搜索结束----------//
//----搜索未超时,图像正常---------//
if(time > 0)
{
//-----开始边缘跟踪--------
for(i=rowStart;i<rowEnd;i++)
{
//----左边缘跟踪
for(j=zuoPos;j>zuoPos-proPix;j--)//左边缘向左跟踪 减少程序的运行时间,提高效率。
{
if(j<=0) break; //断言
if(Buffer1[j]-Buffer1[j-1] == EDGE ) //EDGE=WHITE-BLACK 黑白变化量。
{
zuo[i-rowStart] = j;
turn--;
zuoEdgeFlag = 1; //左标志位 1
break;
}
else
{
continue; //没找到,继续。
}
}
if( zuoEdgeFlag == 0 )
{
for(j=zuoPos;j<zuoPos+proPix;j++)//左边缘向右跟踪 proPix =5 有什么特殊?这个可能是自己取的经验值
{
if(j>=COL-1) break; //断言
if(Buffer1[j+1]-Buffer1[j] == EDGE ) //EDGE=WHITE-BLACK 黑白变化量。
{
zuo[i-rowStart] = j;
turn++; //turn 弯道
zuoEdgeFlag = 1;
break;
}
else
{
continue;
}
}
}
//---右边缘跟踪
for(j=youPos;j>youPos-proPix;j--)
{
if(j<=0) break; //断言
if(Buffer1[j-1]-Buffer1[j] == EDGE )//右边缘向左搜索 //EDGE=WHITE-BLACK 黑白变化量。
{
you[i-rowStart] = j;
turn --;
youEdgeFlag = 1;
break;
}
else
{
continue;
}
}
if( youEdgeFlag == 0)
{
for(j=youPos;j<youPos+proPix;j++) //右边缘向右搜索
{
if(j>=COL-1) break; //断言
if(Buffer1[j]-Buffer1[j+1] == EDGE) //EDGE=WHITE-BLACK 黑白变化量。
{
you[i-rowStart] = j;
turn++;
youEdgeFlag = 1;
break;
}
else
{
continue;
}
}
}
if( zuoEdgeFlag == 0 ) //左边未找到边缘
//根据趋势预测左边缘值
{
if(turn>0) zuoPos++;
else if(turn<0) zuoPos--;
else;
}
else
zuoPos = zuo[i-rowStart];
if( youEdgeFlag == 0 ) //右边未找到边缘
//根据趋势预测左边缘值
{
if(turn>0) youPos++;
else if(turn<0) youPos--;
else;
}
else
youPos = you[i-rowStart];
if(zuoPos<0) zuoPos = 0; //自己去边缘线?
if(youPos>COL-1) youPos = COL-1;
zuoEdgeFlag = 0;
youEdgeFlag = 0;
//-----结束边缘跟踪--------
//---边缘修正------
for(i=0;i<rowNum;i++)
{
if(zuo == 0 && turn<0) zuo=0; //左边缘到了左边界
if(zuo == 0 && turn>0) zuo=COL-1; //左边缘到了右边界
if(you == COL-1 && turn<0) you=0; //右边缘到了左边界
if(you == COL-1 && turn>0) you=COL-1; //右边缘到了右边界
}
//-----提取当前车体的偏移量
for(i=0;i<rowNum;i++) //rowNum = rowstar-rowstar ==100
{
zuoPos += zuo;
youPos += you;
centure = (zuoPos + youPos)/2; //求车体当前位置 求中线。
}
}
}
}
void Send_Image()
{
EnableInterrupts;
u32 i,j;
uart_putchar(UART0,0xff);
for(i=rowStart; i<rowEnd; i++)
{
for(j=0;j<COL ;j++)
{
if(j==centure)
ImageBuf[centure]=BLACK;
else if(ImageBuf[j] <= ThreadHold)
ImageBuf[j]=BLACK;
else
ImageBuf[j]=WHITE;
}
}
uart_putchar(UART0,ImageBuf[j]);
//DisableInterrupts; //禁止中断
} |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|