DIY基于模式识别的自动找球小车
在小车平台上放一个路由器,刷上openwrt装好uvc驱动,挂载摄像头用电脑接收 图像,进行处理,主要是霍夫圆检测,然后把小球的位置坐标通过蓝牙串口下发给小车,小车根据坐标运动,就可以一直跟着乒乓球了~上位机用C++编写,代码如下:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include "Windows.h"
#include "string"
using namespace std;
using namespace cv;
#define input_sources3
//cam = 0; img = 1;stream = 3
#define standby 998
#define noball 990
using namespace cv;
/** @function main */
int main(int argc, char** argv)
{
Mat src, src_gray;
#if input_sources == 1
char* filename = "I:\\OpenCV\\1.jpg";
#endif
#if input_sources == 0;
VideoCapture vcap(0);
if (!vcap.isOpened())
return -1;
#endif
#if input_sources == 3
cv::VideoCapture vcap;
const string address = "http://192.168.11.1:8080/?action=stream?dummy=param.mjpg";
if (!vcap.open(address))
{
cout << "Error opening video stream" << endl;
return -1;
}
cout << "Stream opened" << endl;
#endif
////////////////////////////////////////////////////////////////////////////////////////////
//serial init
HANDLE hCom;
hCom = CreateFile(TEXT("\\\\.\\COM14"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
char Out_Buffer;
DWORD byteswritten = 0;
int x = 640;
int y = 480;
DCB dcb;
GetCommState(hCom, &dcb);
dcb.BaudRate = 9600; //波特率为9600
dcb.ByteSize = 8; //每个字节有8位
dcb.Parity = NOPARITY; //无奇偶校验位
dcb.StopBits = 0; //yi个停止位
SetCommState(hCom, &dcb);
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
//serial
string strx = to_string(standby);
string stry = to_string(standby);
string str_temp = strx + ',' + stry + '\r'+'\n';
strcpy(Out_Buffer, str_temp.c_str());
int temp = 0;
DWORD byteswrite = str_temp.length();
WriteFile(hCom, Out_Buffer, byteswrite, &byteswritten, NULL);
WriteFile(hCom, Out_Buffer, byteswrite, &byteswritten, NULL);
////////////////////////////////////////////////////////////////////////////////////////////////
namedWindow("Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE);
namedWindow("scanny", 1);
while (1)
{
#if (input_sources == 0 || input_sources ==3)
vcap >> src;
#endif
/// Read the image
#if input_sources == 1
src = imread(filename);
if (!src.data)
{
return -1;
}
#endif
/// Convert it to gray
//cvtColor(src, src_gray, CV_BGR2GRAY);
Mat src_gray = Mat::zeros(src.size(), CV_8UC1);
Mat scanny = Mat::zeros(src.size(), CV_8UC1);
//printf("cols=%d\nrows=%d\n\n", src.cols, src.rows);
for (int y = 0; y < src.rows; y++)
{
for (int x = 0; x < src.cols; x++)
{
src_gray.at<uchar>(y, x) = abs(src.at<Vec3b>(y, x) - src.at<Vec3b>(y, x));
}
}
//printf("cols=%d\nrows=%d\n\n", src.cols, src.rows);
/// Reduce the noise so we avoid false circle detection
GaussianBlur(src_gray, src_gray, Size(5,5), 2, 2);
namedWindow("rc", CV_WINDOW_AUTOSIZE);
imshow("rc", src_gray);
vector<Vec3f> circles;
/// Apply the Hough Transform to find the circles
Canny(src_gray, scanny, 0, 70, 3);
HoughCircles(src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows / 8, 80, 20, 0, 150); //80 scanny阈值 20圆心检测阈值 0 150 最小最大圆半径
//int i = 1;
/// Draw the circles detected
for (size_t i = 0; i < circles.size(); i++)
{
//i = 0;
printf("\ncircle.size = %d\n", circles.size());
Point center(cvRound(circles), cvRound(circles));
printf("x=%d\ny=%d\n\n", cvRound(circles), cvRound(circles));
x = cvRound(circles);
y = cvRound(circles);
int radius = cvRound(circles);
// circle center
circle(src, center, 3, Scalar(0, 255, 0), -1, 8, 0);
// circle outline
circle(src, center, radius, Scalar(0, 0, 255), 3, 8, 0);
Point text_center(cvRound(circles) - cvRound(circles), cvRound(circles) - cvRound(circles));
if (circles>2)
putText(src, "Object Detected !", text_center, 0, 0.7, (0, 255, 255), 2);
}
/////////////////////////////////////////////////////////////////////////////////////
//serial
string strx = to_string(x);
string stry = to_string(y);
int x_old, y_old;
string str_temp = strx + ',' + stry +'\r'+ '\n';
//if (str_temp == '\n')
{
strcpy(Out_Buffer, str_temp.c_str());
DWORD byteswrite = str_temp.length();
if ((x_old != x) || (y_old != y))
WriteFile(hCom, Out_Buffer, byteswrite, &byteswritten, NULL);
else
{
/////////////////////////////////////////////////////////////////////////////////////
//serial
temp++;
if (temp == 30)
{
temp = 0;
strx = to_string(noball);
stry = to_string(noball);
str_temp = strx + ',' + stry + '\r' + '\n';
strcpy(Out_Buffer, str_temp.c_str());
byteswrite = str_temp.length();
WriteFile(hCom, Out_Buffer, byteswrite, &byteswritten, NULL);
WriteFile(hCom, Out_Buffer, byteswrite, &byteswritten, NULL);
}
////////////////////////////////////////////////////////////////////////////////////////////////
}
x_old = x;
y_old = y;
}
////////////////////////////////////////////////////////////////////////////////////////////////
/// Show your results
imshow("Hough Circle Transform Demo", src);
imshow("scanny", scanny);
if (waitKey(2) == 27)
break;
}
destroyAllWindows();
//CloseHandle(hCom);
// waitKey(0);
return 0;
}
最终实现效果是这样的:
http://v.youku.com/v_show/id_XOTMxMzY5Nzcy.html 不错,很厉害 很好玩滴样子呢~ :lol 贊啊,不過是用什麼路由器的呢?
页:
[1]