#include
#include
#include
#include
#include
#include
#include
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include
using namespace cv;
using namespace std;
#define MAX_KERNEL_LENTH (19)
#define MEAN_THRESH_VAL (1) //平均阈值
int fd;
int fps = 100; //帧率
char buf[1024] = "temp text";
Mat org_image, blurred_image, binary_image, edge_image;
//串口设置
int setupSerial()
{
struct termios toptions;
//打开串口
fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY);
printf("fd opened as %i\n", fd);
//等待Arduino启动
usleep(150000);
//获得当前串口设置
tcgetattr(fd, &toptions);
//设置波特率
cfsetispeed(&toptions, B9600);
cfsetospeed(&toptions, B9600);
//控制模式 ,没有奇偶校验、停止位,字符长度为8
toptions.c_cflag &= ~PARENB;
toptions.c_cflag &= ~CSTOPB;
toptions.c_cflag &= ~CSIZE;
toptions.c_cflag |= CS8;
//启用标准模式
toptions.c_lflag |= ICANON;
tcsetattr(fd, TCSANOW, &toptions);
printf("Attempting to communicate with arduino... \n");
return 0;
}
//命令函数
void sendCommand(const char* command)
{
int n;
write(fd, command, strlen(command)); //把命令写入fd中,并返回写的字节数
n = read(fd, buf, 512); //把fd所指的文件传送到buf所指的内存中,返回读取的字节数
buf[n+1] = '\0';
//返回命令内容
printf("Command Returned: %s\n", buf);
}
//特征提取阶段:获取图像的均值
double value(Mat binary_image)
{
Scalar mean_scalar, stddev_scalar;
meanStdDev(binary_image, mean_scalar, stddev_scalar);
double value;
value = mean_scalar.val[0];
return value;
}
//确定小车的方向
int direction(Mat image)
{
namedWindow("org image", WINDOW_NORMAL);
imshow("org image", image);
//将原图像变为640*480
resize(image, org_image, Size(640,480), 0, 0, CV_INTER_LINEAR);
//模糊处理
for (int i = 1; i < MAX_KERNEL_LENTH; i = i + 2)
GaussianBlur(org_image, blurred_image, Size(1,1), 0, 0);
//使用恒定阈值方法去掉细节,得到阈值图像
threshold(org_image, binary_image, 170, 255, THRESH_BINARY);
//得到只有边缘信息的图像
Canny(blurred_image, edge_image, 45, 90);
//把只有边缘信息的图像叠加到二值图像上,获取边缘信息的同时也获取物体的区域信息
Mat binary_image1;
binary_image1 = binary_image + edge_image;
//闭运算
Mat binary_image2 = binary_image.clone();
Mat element = getStructuringElement(MORPH_RECT, Size(40, 40));
morphologyEx(binary_image1, binary_image2, MORPH_CLOSE, element);
namedWindow("binary", WINDOW_NORMAL);
imshow("binary", binary_image2);
//定义九个方位
Mat result[9];
result[0] = binary_image2(Rect(0, 0, 213, 160));
result[1] = binary_image2(Rect(213, 0, 213, 160));
result[2] = binary_image2(Rect(426, 0, 213, 160));
result[3] = binary_image2(Rect(0, 160, 213, 160));
result[4] = binary_image2(Rect(213, 160, 213, 160));
result[5] = binary_image2(Rect(426, 160, 213, 160));
result[6] = binary_image2(Rect(0, 320, 213, 160));
result[7] = binary_image2(Rect(213, 320, 213, 160));
result[8] = binary_image2(Rect(426, 320, 213, 160));
//计算九个方位的均值
double seperate_value[9];
for (int i = 0; i < 9; ++ i)
seperate_value[i] = value(result[i]);
//得到后面均值最小的方位
double min_value = 100;
int index = 0, key = 0;
for (int i = 6; i < 9; ++ i)
if (seperate_value[i] < min_value)
{
min_value = seperate_value[i];
index = i;
}
//返回车转动的方向
switch (index)
{
case 6: key = -1; break; //左转
case 8: key = 1; break; //右转
default: key = 0; break; //直走
}
if (seperate_value[6] < 1 && seperate_value[7] < 1 && seperate_value[8] < 1)
key = 0; //没有障碍物,直接往前行驶
else if (seperate_value[6] > 10 && seperate_value[7] > 10 && seperate_value[8] > 10)
key = 9; //道路都被障碍物挡住,停止前进
cout << "key: " << key << endl;
waitKey(1);
return key;
}
int main()
{
setupSerial();
VideoCapture capture(0);
while(1)
{
capture>>org_image;
if(org_image.data != NULL)
{
cvtColor(org_image, org_image, COLOR_BGR2GRAY);
//确定前进方向并向Arduino发送命令
int key = direction(org_image);
if (key == 0)
{
sendCommand("f0");
usleep(500000);}
else if (key == -1)
{
sendCommand("s");
usleep(500000);
sendCommand("l60");
usleep(500000);
}
else if (key == 1)
{
sendCommand("s");
usleep(500000);
sendCommand("r140");
usleep(500000);
}
else
{
sendCommand("l90");
usleep(500000);
sendCommand("s");
usleep(500000);
//sendCommand("l90");
}
}
else
{
cout << "error:empty image!" << endl;
break;
}
}
return 0;
}