androi、opencv黑线位置识别并使用蓝牙发送
首先声明本人也是安卓开发菜鸟,在这里发帖只是为了跟大家互相学习,交流经验。之前做过一个类似于闹钟的app,花了很长时间,这次因为有了上次的开发经验用的时间会短一些,不过用的都是别人的源代码,距离自己编写还有很长的路要走。
本次我主要使用了两个代码,这里我给出网址,大家可以去下载:
1:http://download.csdn.net/detail/fengdehuhuan122/7810953 蓝牙串口
2:我用的源码地址为
http://www.opencv.org.cn/forum.php?mod=viewthread&tid=31817&extra=page%3D2,不过正如楼主所说的在有些手机上是不能用的,我找到了问题的所在主要是将AutoDriodViewBase中的releaseCamera()函数中if的内容去掉即可。如果大家不想自己新建工程,可以到这里下载工程文件:http://download.csdn.net/detail/fengdehuhuan122/7811023
最后说说我修改以后的代码实现的功能:
最近再做一个机器人跟随黑线行走的功能,为了更加体现创新性,所以使用手机进行识别提取。本代码的功能主要是利用手机提取黑线,将黑线位置利用手机的蓝牙通过蓝牙转串口设备发送给单片机,单片机在进行决策,蓝牙转串口设备淘宝有卖的,我用的是HC-05。现在功能已实现,并且稳定性较好。下载地址: http://download.csdn.net/download/fengdehuhuan122/7811249
部分安卓代码:
/********************数据提取程序******************/
bitmapi0=1;
bitmapi1=1;
bitmapi2=1; //黑点个数清零,之所以为1是因为它会被作为除数,如果置零会报错
for(bitmapx=0;bitmapx<bmp.getWidth();bitmapx++)//循环提取
{
//bmp.getWidth();
//for(int k=100;k<200;k++)
//bmp.setPixel(bitmapx,k,0xFFFFFFFF);
if(bmp.getHeight()>700) //该语句保证下面的正确运行,不然会出错。虽说我的手机分辨率是1280*800,但如果不这样有时会因为读取问题出错
{
if(bmp.getPixel(bitmapx,bmp.getHeight()-600) ==0xFF000000)
{
linecenter0 =linecenter0+bitmapx;//将黑点所在坐标值累加
bitmapi0++;
}
if(bmp.getPixel(bitmapx,bmp.getHeight()-400) ==0xFF000000)
{
linecenter1 =linecenter1+bitmapx;
bitmapi1++;
}
if(bmp.getPixel(bitmapx,bmp.getHeight()-200) ==0xFF000000)
{
linecenter2 =linecenter2+bitmapx;
bitmapi2++;
} //提取第200、400、600行的黑点个数
}
}
linecenter0 =linecenter0/bitmapi0;
linecenter1 =linecenter1/bitmapi1;
linecenter2 =linecenter2/bitmapi2;//求取平均值,算是一个滤波吧
blackpoint0 =bitmapi0;
blackpoint1 =bitmapi1;
blackpoint2 =bitmapi2; //黑点个数赋值
/************************************************/
Runnable runnable = newRunnable()//定时程序
{
@Override
public void run() {
// TODO Auto-generated method stub
// 在此处添加执行的代码
handler.postDelayed(this, 200);// 200ms一次
if(flagb==0)
Toast.makeText(null,"蓝牙未打开!", Toast.LENGTH_SHORT).show();
else if(flagb==1)
{
long Center0=AutoDriodViewBase.linecenter0;
long Center1=AutoDriodViewBase.linecenter1;
long Center2=AutoDriodViewBase.linecenter2;
if((Center0>1280)||(Center0==0)||(AutoDriodViewBase.blackpoint0<30))
Center0=LastCenter0;
if((Center1>1280)||(Center1==0)||(AutoDriodViewBase.blackpoint1<30))
Center1=LastCenter1;
if((Center2>1280)||(Center2==0)||(AutoDriodViewBase.blackpoint2<30))
Center2=LastCenter2;
//当黑点位置超出屏幕范围则继续利用上一次的值,当然黑点是不可能超出屏幕范围,主要是防止定时的时候LastCenter没有除bitmapi
LastCenter0=Center0;
LastCenter1=Center1;
LastCenter2=Center2;
{
try{
OutputStreamos = _socket.getOutputStream(); //蓝牙连接输出流
//蓝牙发送数据"@"、"#"和"*"分别为帧头和帧尾校验
bytebuf0='@';
bytebuf1='#';
bytebuf2=(byte) (Center0/256);
bytebuf3=(byte) (Center0%256);
bytebuf4=(byte) (Center1/256);
bytebuf5=(byte) (Center1%256);
bytebuf6=(byte) (Center2/256);
bytebuf7=(byte) (Center2%256);
//这里数据发送的是16进制的格式。如果用串口调试助手是,注意转换,16进制和hex码、字符串的区别
bytebuf8=(byte) (buf0+buf1+buf2+buf3);//和校验
bytebuf9='*';
os.write(buf0);
os.write(buf1);
os.write(buf2);
os.write(buf3);
os.write(buf4);
os.write(buf5);
os.write(buf6);
os.write(buf7);
os.write(buf8);
os.write(buf9);
// for(byte b : bos)
// {
// os.write(b);
// }
}catch(IOExceptione){
}
}
}
}
};
单片机接收中断程序:
ch=uart_receive();//接收
buf[receive_count]=ch;//数组赋值
if(buf[receive_count]=='@'&&receive_count==0) //帧头‘@'
{
uart_sum=buf[receive_count];
receive_count=1;
}
elseif(buf[receive_count]=='#'&&receive_count==1) //帧头'#'
{
uart_sum+=buf[receive_count];
receive_count=2;
}
elseif(receive_count>=2&&receive_count<8)//数据段
{
uart_sum+=buf[receive_count];
receive_count++;
}
elseif(receive_count==8&&buf[receive_count]==uart_sum) //和校验
{
receive_count++;
}
elseif(receive_count==9&&buf[receive_count]=='*') //帧尾‘*‘
{
receive_count=0;
CenterXNew0=buf[2]*256+buf[3];
CenterXNew1=buf[4]*256+buf[5];
CenterXNew2=buf[6]*256+buf[7];
}
else
{
receive_count=0;
}
至于串口用多少的波特率,可以自己设置。最后,有什么问题尽管提,互相学习!