极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 11443|回复: 3

DIY基于模式识别的自动找球小车

[复制链接]
发表于 2015-4-12 12:50:20 | 显示全部楼层 |阅读模式
在小车平台上放一个路由器,刷上openwrt装好uvc驱动,挂载摄像头用电脑接收 图像,进行处理,主要是霍夫圆检测,然后把小球的位置坐标通过蓝牙串口下发给小车,小车根据坐标运动,就可以一直跟着乒乓球了~

上位机用C++编写,代码如下:

  1. #include "opencv2/highgui/highgui.hpp"
  2. #include "opencv2/imgproc/imgproc.hpp"
  3. #include <iostream>
  4. #include <stdio.h>
  5. #include "Windows.h"
  6. #include "string"



  7. using namespace std;
  8. using namespace cv;

  9. #define input_sources  3
  10. //cam = 0; img = 1;  stream = 3

  11. #define standby 998
  12. #define noball 990


  13. using namespace cv;





  14. /** @function main */
  15. int main(int argc, char** argv)
  16. {
  17.         Mat src, src_gray;
  18. #if input_sources == 1
  19.         char* filename = "I:\\OpenCV\\1.jpg";
  20. #endif

  21. #if input_sources == 0;
  22.         VideoCapture vcap(0);
  23.         if (!vcap.isOpened())
  24.                 return -1;
  25. #endif

  26. #if input_sources == 3

  27.         cv::VideoCapture vcap;

  28.         const string address = "http://192.168.11.1:8080/?action=stream?dummy=param.mjpg";

  29.         if (!vcap.open(address))
  30.         {
  31.                 cout << "Error opening video stream" << endl;
  32.                 return -1;
  33.         }

  34.         cout << "Stream opened" << endl;
  35. #endif




  36.         ////////////////////////////////////////////////////////////////////////////////////////////
  37.         //serial init
  38.         HANDLE hCom;
  39.         hCom = CreateFile(TEXT("\\\\.\\COM14"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

  40.         char Out_Buffer[10];
  41.         DWORD byteswritten = 0;

  42.         int x = 640;
  43.         int y = 480;

  44.         DCB dcb;
  45.         GetCommState(hCom, &dcb);
  46.         dcb.BaudRate = 9600; //波特率为9600
  47.         dcb.ByteSize = 8; //每个字节有8位
  48.         dcb.Parity = NOPARITY; //无奇偶校验位
  49.         dcb.StopBits = 0; //yi个停止位
  50.         SetCommState(hCom, &dcb);
  51.         /////////////////////////////////////////////////////////////////////////////////////////////




  52.         /////////////////////////////////////////////////////////////////////////////////////
  53.         //serial
  54.         string strx = to_string(standby);
  55.         string stry = to_string(standby);
  56.         string str_temp = strx + ',' + stry + '\r'+'\n';
  57.         strcpy(Out_Buffer, str_temp.c_str());
  58.         int temp = 0;
  59.         DWORD byteswrite = str_temp.length();
  60.         WriteFile(hCom, Out_Buffer, byteswrite, &byteswritten, NULL);
  61.         WriteFile(hCom, Out_Buffer, byteswrite, &byteswritten, NULL);
  62.         ////////////////////////////////////////////////////////////////////////////////////////////////



  63.         namedWindow("Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE);
  64.         namedWindow("scanny", 1);


  65.         while (1)
  66.         {
  67. #if (input_sources == 0 || input_sources ==3)
  68.                 vcap >> src;
  69. #endif
  70.                 /// Read the image
  71. #if input_sources == 1
  72.                 src = imread(filename);
  73.                 if (!src.data)
  74.                 {
  75.                 return -1;
  76.                 }
  77. #endif
  78.                 /// Convert it to gray
  79.                 //cvtColor(src, src_gray, CV_BGR2GRAY);


  80.                 Mat src_gray = Mat::zeros(src.size(), CV_8UC1);
  81.                 Mat scanny = Mat::zeros(src.size(), CV_8UC1);

  82.                
  83.                

  84.                 //printf("cols=%d\nrows=%d\n\n", src.cols, src.rows);
  85.                 for (int y = 0; y < src.rows; y++)
  86.                 {
  87.                         for (int x = 0; x < src.cols; x++)
  88.                         {
  89.                                 src_gray.at<uchar>(y, x) = abs(src.at<Vec3b>(y, x)[2] - src.at<Vec3b>(y, x)[1]);
  90.                         }
  91.                 }


  92.                 //printf("cols=%d\nrows=%d\n\n", src.cols, src.rows);

  93.                 /// Reduce the noise so we avoid false circle detection
  94.                 GaussianBlur(src_gray, src_gray, Size(5,5), 2, 2);

  95.                 namedWindow("rc", CV_WINDOW_AUTOSIZE);
  96.                 imshow("rc", src_gray);


  97.                 vector<Vec3f> circles;

  98.                 /// Apply the Hough Transform to find the circles

  99.                 Canny(src_gray, scanny, 0, 70, 3);

  100.                 HoughCircles(src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows / 8, 80, 20, 0, 150);                //80 scanny阈值   20  圆心检测阈值    0 150 最小最大圆半径


  101.                 //int i = 1;
  102.                 /// Draw the circles detected
  103.                 for (size_t i = 0; i < circles.size(); i++)
  104.                 {
  105.                         //i = 0;
  106.                        
  107.                        
  108.                         printf("\ncircle.size = %d\n", circles.size());


  109.                         Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));

  110.                         printf("x=%d\ny=%d\n\n", cvRound(circles[i][0]), cvRound(circles[i][1]));

  111.                         x = cvRound(circles[i][0]);
  112.                         y = cvRound(circles[i][1]);

  113.                        

  114.                         int radius = cvRound(circles[i][2]);
  115.                         // circle center
  116.                         circle(src, center, 3, Scalar(0, 255, 0), -1, 8, 0);
  117.                         // circle outline
  118.                         circle(src, center, radius, Scalar(0, 0, 255), 3, 8, 0);

  119.                         Point text_center(cvRound(circles[i][0]) - cvRound(circles[i][2]), cvRound(circles[i][1]) - cvRound(circles[i][2]));
  120.                         if (circles[i][2]>2)
  121.                                 putText(src, "Object Detected !", text_center, 0, 0.7, (0, 255, 255), 2);
  122.                 }

  123.                
  124.                 /////////////////////////////////////////////////////////////////////////////////////
  125.                 //serial
  126.                 string strx = to_string(x);
  127.                 string stry = to_string(y);
  128.                 int x_old, y_old;
  129.                
  130.                 string str_temp = strx + ',' + stry +'\r'+ '\n';
  131.                 //if (str_temp[str_temp.length() - 1] == '\n')
  132.                 {
  133.                         strcpy(Out_Buffer, str_temp.c_str());
  134.                         DWORD byteswrite = str_temp.length();
  135.                         if ((x_old != x) || (y_old != y))
  136.                                 WriteFile(hCom, Out_Buffer, byteswrite, &byteswritten, NULL);
  137.                         else
  138.                         {
  139.                                 /////////////////////////////////////////////////////////////////////////////////////
  140.                                 //serial
  141.                                 temp++;
  142.                                 if (temp == 30)
  143.                                 {
  144.                                         temp = 0;
  145.                                         strx = to_string(noball);
  146.                                         stry = to_string(noball);
  147.                                         str_temp = strx + ',' + stry + '\r' + '\n';
  148.                                         strcpy(Out_Buffer, str_temp.c_str());
  149.                                         byteswrite = str_temp.length();
  150.                                         WriteFile(hCom, Out_Buffer, byteswrite, &byteswritten, NULL);
  151.                                         WriteFile(hCom, Out_Buffer, byteswrite, &byteswritten, NULL);
  152.                                 }
  153.                                 ////////////////////////////////////////////////////////////////////////////////////////////////
  154.                         }
  155.                         x_old = x;
  156.                         y_old = y;
  157.                 }
  158.                 ////////////////////////////////////////////////////////////////////////////////////////////////
  159.                

  160.                 /// Show your results
  161.                 imshow("Hough Circle Transform Demo", src);
  162.                 imshow("scanny", scanny);
  163.                 if (waitKey(2) == 27)
  164.                         break;
  165.         }

  166.         destroyAllWindows();
  167.         //CloseHandle(hCom);


  168. //        waitKey(0);
  169.         return 0;
  170. }
复制代码



最终实现效果是这样的:
回复

使用道具 举报

发表于 2015-4-12 16:15:06 | 显示全部楼层
不错,很厉害
回复 支持 反对

使用道具 举报

发表于 2015-4-12 16:56:28 | 显示全部楼层
很好玩滴样子呢~
回复 支持 反对

使用道具 举报

发表于 2016-3-12 17:26:30 | 显示全部楼层
贊啊,不過是用什麼路由器的呢?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-3-29 10:40 , Processed in 0.056169 second(s), 21 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表