hosea1008 发表于 2015-4-12 12:50:20

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

zoologist 发表于 2015-4-12 16:15:06

不错,很厉害

lawrencedon 发表于 2015-4-12 16:56:28

很好玩滴样子呢~ :lol

vaf 发表于 2016-3-12 17:26:30

贊啊,不過是用什麼路由器的呢?
页: [1]
查看完整版本: DIY基于模式识别的自动找球小车