樹莓派+Qt+圖像識別+串口傳輸

CAMsearch.pro

QT += core
QT -= gui

TARGET = test
CONFIG += console
CONFIG -= app_bundle

TEMPLATE = app

SOURCES += main.cpp



INCLUDEPATH +=/usr/local/include \
               /usr/local/include/opencv \
               /usr/local/include/opencv2

LIBS +=/usr/local/lib/libopencv_highgui.so \
        /usr/local/lib/libopencv_core.so \
        /usr/local/lib/libopencv_imgproc.so \
        /usr/local/lib/libopencv_imgcodecs.so\
        /usr/local/lib/libopencv_videoio.so \
        /usr/local/lib/libopencv_video.so \
        /usr/local/lib/libopencv_videostab.so \
        /usr/local/lib/libopencv_calib3d.so \
        /usr/local/lib/libopencv_features2d.so\
        /usr/local/lib/libopencv_flann.so \
        /usr/local/lib/libopencv_ml.so \
        /usr/local/lib/libopencv_objdetect.so \
        /usr/local/lib/libopencv_photo.so \
        /usr/local/lib/libopencv_shape.so \
        /usr/local/lib/libopencv_stitching.so \
        /usr/local/lib/libopencv_superres.so
LIBS +=-lwiringPi

main.cpp

#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <wiringPi.h>
#include <wiringSerial.h>
#include <iostream>
#include<sys/stat.h>
#include<unistd.h>
using namespace std;
using namespace cv;


int main(void)
{
    sleep(1);//延時1秒

    /*-------------初始化變量--------------*/
    Mat frame; 
    RNG rng(12345);
    vector<vector<Point> > contours; //所有輪廓
    vector<Vec4i> hierarchy;
    int fd,xxx,yyy,dx,dy;
    char string[4],str[6],str1[6];
    /*-------------初始化環境--------------*/
    if(wiringPiSetupSys()<0)return 1;//初始化wiringPi
    VideoCapture capture(0);//打開攝像頭
    if (!capture.isOpened()) { printf("--(!)Error opening video capture\n"); return -1; }

    /*-------------主循環--------------*/
    while (capture.read(frame))
    {
        if (frame.empty())
        {
            printf(" --(!) No captured frame -- Break!");
            break;
        }
        capture >> frame;  //從攝像頭取一幀緩存到frame

        /*-------------圖像處理部分-------------*/
        Mat proimage = frame;
        cvtColor(proimage, proimage, CV_BGRA2GRAY); 
        blur(proimage, proimage, Size(5, 5));       
        Canny(proimage, proimage, 50, 100);       //canny邊緣檢測
        adaptiveThreshold(proimage, proimage, 255, ADAPTIVE_THRESH_GAUSSIAN_C,
            THRESH_BINARY_INV, 7, 7); //自適應二值化

        /*-------------圖像識別部分--------------*/
        Mat Findallcontours = proimage;
        findContours(Findallcontours, contours,CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE); //提取所有的輪廓存到contours

        vector<RotatedRect> possibleObj; //可能的目標
        vector<RotatedRect> target;//最終目標

        for (size_t i = 0; i < contours.size(); i++)
        {
            size_t count = contours[i].size(); //所有的輪廓數量
            if (count < 50)continue;//排除過小的輪廓
            if (count > 1640)continue;//排除過大的輪廓

            Mat pointsf;
            Mat(contours[i]).convertTo(pointsf, CV_32F);
            RotatedRect box = fitEllipse(pointsf);// 橢圓擬合

            if (MAX(box.size.width, box.size.height) >
                MIN(box.size.width, box.size.height)*1.2)continue;//選出接近園的輪廓

            possibleObj.push_back(box); //可能的目標放到possibleObj

            /*當前box與之前所有的possibleObj作比較*/
            for (int p = 0; p < possibleObj.size(); p++)
            {

                float d = powf((possibleObj[p].center.x -  box.center.x), 2) + powf((possibleObj[p].center.y - box.center.y), 2);
                 d = sqrtf(d);  //兩個圓心的歐式距離

                bool flag = true;
                if(possibleObj[p].size == box.size){flag = false;} //排除自身
                if (d <20&&flag)
                {   
                    /*半徑兩倍*/
                    if(((1.7<possibleObj[p].size.width/box.size.width)
                        && (possibleObj[p].size.width / box.size.width<2.4)) 
                        || ((1.7<box.size.height / possibleObj[p].size.height) 
                        && (box.size.height / possibleObj[p].size.height<2.4)))
                    {
                        target.push_back(possibleObj[p]);
                        target.push_back(box); //符合條件的輪廓放入target
                    }
                }
            }

        }

        /*-------------輪廓繪製--------------*/
        Mat drawing = Mat::zeros(frame.size(), CV_8UC3); 
        for (int p = 0; p < possibleObj.size(); p++)
        {
            Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
            ellipse(drawing, possibleObj[p], color, 2, 8);

        }
        for (int t = 0; t < target.size()/2; t++)
        {

            Scalar color = Scalar(0, 0, 255);
            ellipse(frame, target[t], color, 2, 8);
            /*以攝像頭爲原點,輸出xy二軸座標
            在opencv,圖像座標是以左上角爲原點的*/
            xxx=int(target[t].center.x);dx=xxx-proimage.cols/2;
            yyy=int(target[t].center.y);dy=proimage.rows/2-yyy;

            sprintf(str,"%s%d%s","X",dx,"R");
            sprintf(str1,"%s%d%s","Y",dy,"R");//字符串拼接,傳輸協議x軸X***R,y軸Y***R

            printf(":%s,%s\n", str, str1);
            /*打開串口設備,發送座標字符串,波特率9600*/
            if ((fd = serialOpen("/dev/ttyS0", 9600)) < 0)
            {
                printf("serial doesn't open,return %d", fd);
            }
                serialPrintf(fd,str); 
                delay(10);
                serialPrintf(fd,str1);
                serialClose(fd);//清緩存
             }
        int c = waitKey(10);
        if ((char)c == 27) { break; } // escape
    }
    capture.release();
    return 0;
}

測試

這裏寫圖片描述
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章