智能小车项目源码

#include <stdlib.h>  
#include <string.h>  
#include <stdio.h>  
#include <time.h>  
  
#include <unistd.h>  
#include <fcntl.h>  
#include <termios.h>  
#include "opencv2/core/core.hpp"  
#include "opencv2/highgui/highgui.hpp"  
#include "opencv2/imgproc/imgproc.hpp"  
#include <iostream>  
  
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;  
}  

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页