2016-07-13 2 views
1

Эта программа является моим «Отслеживанием цвета в реальном времени в системе птичьего полета».Отслеживание объектов в реальном времени в птичьем глазу в OpenCV

#include <sstream> 
    #include <string> 
    #include <iostream> 
    #include <vector> 
    #include <stdio.h> 
    #include <stdlib.h> 
    #include "stdafx.h" 
    #include "Fruit.h" 
    #include "opencv2\\opencv.hpp" 

    #pragma comment(lib,"C:\\opencv\\build\\x86\\vc10\\lib\\opencv_core249d.lib") 
    #pragma comment(lib,"C:\\opencv\\build\\x86\\vc10\\lib\\opencv_imgproc249d.lib") 
    #pragma comment(lib,"C:\\opencv\\build\\x86\\vc10\\lib\\opencv_highgui249d.lib") 
    #pragma comment(lib,"C:\\opencv\\build\\x86\\vc10\\lib\\opencv_objdetect249d.lib") 
    #pragma comment(lib,"C:\\opencv\\build\\x86\\vc10\\lib\\opencv_ml249d.lib") 
    #pragma comment(lib,"C:\\opencv\\build\\x86\\vc10\\lib\\opencv_video249d.lib") 
    #pragma comment(lib,"C:\\opencv\\build\\x86\\vc10\\lib\\opencv_calib3d249d.lib") 

    using namespace cv; 
    //initial min and max HSV filter values. 
    //these will be changed using trackbars 
    int H_MIN = 0; 
    int H_MAX = 256; 
    int S_MIN = 0; 
    int S_MAX = 256; 
    int V_MIN = 0; 
    int V_MAX = 256; 
    //default capture width and height 
    const int FRAME_WIDTH = 640; 
    const int FRAME_HEIGHT = 480; 
    //max number of objects to be detected in frame 
    const int MAX_NUM_OBJECTS=50; 
    //minimum and maximum object area 
    const int MIN_OBJECT_AREA = 7*7; 
    const int MAX_OBJECT_AREA = FRAME_HEIGHT*FRAME_WIDTH/1.5; 
    //names that will appear at the top of each window 
    const string windowName = "Original Image"; 
    const string windowName1 = "HSV Image"; 
    const string windowName2 = "Thresholded Image"; 
    const string windowName3 = "After Morphological Operations"; 
    const string trackbarWindowName = "Trackbars"; 

    void on_trackbar(int, void*) 
    { 
    //This function gets called whenever a 
    // trackbar position is changed 

    } 

    string intToString(int number){ 

    std::stringstream ss; 
    ss << number; 
    return ss.str(); 

    } 

    void createTrackbars(){ 

    //create window for trackbars 
    namedWindow(trackbarWindowName,0); 
    //create memory to store trackbar name on window 
    char TrackbarName[50]; 
    sprintf(TrackbarName, "H_MIN", H_MIN); 
    sprintf(TrackbarName, "H_MAX", H_MAX); 
    sprintf(TrackbarName, "S_MIN", S_MIN); 
    sprintf(TrackbarName, "S_MAX", S_MAX); 
    sprintf(TrackbarName, "V_MIN", V_MIN); 
    sprintf(TrackbarName, "V_MAX", V_MAX); 

    createTrackbar("H_MIN", trackbarWindowName, &H_MIN, H_MAX, on_trackbar); 
    createTrackbar("H_MAX", trackbarWindowName, &H_MAX, H_MAX, on_trackbar); 
    createTrackbar("S_MIN", trackbarWindowName, &S_MIN, S_MAX, on_trackbar); 
    createTrackbar("S_MAX", trackbarWindowName, &S_MAX, S_MAX, on_trackbar); 
    createTrackbar("V_MIN", trackbarWindowName, &V_MIN, V_MAX, on_trackbar); 
    createTrackbar("V_MAX", trackbarWindowName, &V_MAX, V_MAX, on_trackbar); 

    } 

    void drawObject(vector<Fruit> theFruits,Mat &frame){ 

    for(int i =0; i<theFruits.size(); i++){ 

    cv::circle(frame,cv::Point(theFruits.at(i).getXPos(),theFruits.at(i).getYPos()),10,cv::Scalar(0,0,255)); 
    cv::putText(frame,intToString(theFruits.at(i).getXPos())+ " , " + intToString(theFruits.at(i).getYPos()),cv::Point(theFruits.at(i).getXPos(),theFruits.at(i).getYPos()+20),1,1,Scalar(0,255,0)); 
    } 
    } 

    void morphOps(Mat &thresh){ 

    //create structuring element that will be used to "dilate" and "erode" image. 
    //the element chosen here is a 3px by 3px rectangle 

    Mat erodeElement = getStructuringElement(MORPH_RECT,Size(3,3)); 
    //dilate with larger element so make sure object is nicely visible 
    Mat dilateElement = getStructuringElement(MORPH_RECT,Size(8,8)); 

    erode(thresh,thresh,erodeElement); 
    erode(thresh,thresh,erodeElement); 

    dilate(thresh,thresh,dilateElement); 
    dilate(thresh,thresh,dilateElement); 

    } 

    void trackFilteredObject(Mat threshold,Mat HSV, Mat &cameraFeed_BE){ 

    vector <Fruit> apples; 

    Mat temp; 
    threshold.copyTo(temp); 
    //these two vectors needed for output of findContours 
    vector< vector<Point> > contours; 
    vector<Vec4i> hierarchy; 
    //find contours of filtered image using openCV findContours function 
    findContours(temp,contours,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE); 
    //use moments method to find our filtered object 
    double refArea = 0; 
    bool objectFound = false; 
    if (hierarchy.size() > 0) { 
     int numObjects = hierarchy.size(); 
     //if number of objects greater than MAX_NUM_OBJECTS we have a noisy filter 
     if(numObjects<MAX_NUM_OBJECTS){ 
       for (int index = 0; index >= 0; index = hierarchy[index][0]) { 

        Moments moment = moments((cv::Mat)contours[index]); 
        double area = moment.m00; 

        if(area>MIN_OBJECT_AREA){ 
          Fruit apple; 

          apple.setXPos(moment.m10/area); 
          apple.setYPos(moment.m01/area); 

          apples.push_back(apple); 

          objectFound = true; 

        }else objectFound = false; 


       } 
       //let user know you found an object 
       if(objectFound ==true){ 
        //draw object location on screen 
        drawObject(apples,cameraFeed_BE); 
       } 

     }else putText(cameraFeed_BE,"TOO MUCH NOISE! ADJUST FILTER",Point(0,50),1,2,Scalar(0,0,255),2); 
    } 
    } 

    int main(int argc, char* argv[]) 
    { 
    //if we would like to calibrate our filter values, set to true. 
    bool calibrationMode = true; 

    //Matrix to store each frame of the webcam feed 
    Mat cameraFeed; 
    Mat threshold; 
    Mat HSV; 

    if(calibrationMode){ 
     //create slider bars for HSV filtering 
     createTrackbars(); 
    } 
    //video capture object to acquire webcam feed 
    VideoCapture capture; 
    //open capture object at location zero (default location for webcam) 
    capture.open(0); 
    //set height and width of capture frame 
    capture.set(CV_CAP_PROP_FRAME_WIDTH,FRAME_WIDTH); 
    capture.set(CV_CAP_PROP_FRAME_HEIGHT,FRAME_HEIGHT); 

    if(!capture.isOpened()) //confirm camera opened 
    { 
     return -1; 
    } 

    //start an infinite loop where webcam feed is copied to cameraFeed matrix 
    //all of our operations will be performed within this loop 
    while(1){ 

     do{ 
       capture >> cameraFeed; 
     }while(cameraFeed.empty()); 

     int key = 0; 
     IplImage* Frame ; 
     IplImage* birds_image; 
     CvMat *H; 
     float Z; 

    cvNamedWindow("Birds eye"); 

    Frame =new IplImage(cameraFeed); 
    birds_image = cvCloneImage(Frame); 

    // EXAMPLE OF LOADING THESE MATRICES BACK IN: 
    CvMat *intrinsic = (CvMat*)cvLoad("Intrinsics.xml"); 
    CvMat *distortion = (CvMat*)cvLoad("Distortion.xml"); 

    // Build the undistort map which we will use for all subsequent frames. 
    IplImage* mapx = cvCreateImage(cvGetSize(Frame), IPL_DEPTH_32F, 1); 
    IplImage* mapy = cvCreateImage(cvGetSize(Frame), IPL_DEPTH_32F, 1); 
    cvInitUndistortMap(
     intrinsic, 
     distortion, 
     mapx, 
     mapy 
); 

    IplImage *t = cvCloneImage(Frame); 
    //cvShowImage("Calibration", image); // Show raw image 
    cvRemap(t, Frame, mapx, mapy);  // Undistort image 
    cvReleaseImage(&t); 

    H = (CvMat*)cvLoad("H.xml"); 

    cvWarpPerspective(
     Frame, 
     birds_image, 
     H, 
     CV_INTER_LINEAR | CV_WARP_INVERSE_MAP | CV_WARP_FILL_OUTLIERS 
     ); 

    cvShowImage("Birds eye", birds_image); 

    Mat cameraFeed_BE = cvarrToMat(birds_image); 

    //store image to matrix 
    capture.read(cameraFeed_BE); 
    //convert frame from BGR to HSV colorspace 
    cvtColor(cameraFeed_BE,HSV,COLOR_BGR2HSV); 

    if(calibrationMode==true){ 
    //if in calibration mode, we track objects based on the HSV slider values. 
    cvtColor(cameraFeed_BE,HSV,COLOR_BGR2HSV); 
    inRange(HSV,Scalar(H_MIN,S_MIN,V_MIN),Scalar(H_MAX,S_MAX,V_MAX),threshold); 
    morphOps(threshold); 

    imshow(windowName2,threshold); 
    trackFilteredObject(threshold,HSV,cameraFeed_BE); 
    } 

    //show frames 
    imshow(windowName2,threshold); 
    imshow(windowName,cameraFeed_BE); 
    imshow(windowName1,HSV); 

    //delay 30ms so that screen can refresh. 
    //image will not appear without this waitKey() command 
    if(cv::waitKey(30) >= 0) break; 
    } 

    return 0; 
    } 
  1. Я думаю Original Image, HSV Image и Thresholded Image должны быть birds image, но на самом деле это не так. Я не знаю почему.

  2. И я запускаю программу на минуту, появляется эта ошибка. enter image description here

Я думаю, что эта ошибка появляется, когда есть некоторая утечка памяти. Я добавил этот код.

cvReleaseImage(&birds_image) 

, но этот код не работал.

Не могли бы вы дать мне свои идеи относительно 1. и 2.?

+0

Вы должны избегать смешивания функций устаревших OpenCV как 'cvReleaseImage' с новыми (например,' сорте :: imshow') ... На самом деле вам следует избегать устаревшего OpenCV. – Sunreef

ответ

0

Как вы отметили, сообщение об ошибке связано с ошибкой памяти. У вас есть линия распределения памяти

Frame =new IplImage(cameraFeed); 

внутри вашего бесконечного цикла. Этот массив (изображение RGB с веб-камеры !!) никогда не выпускается, и цикл записывает поверх указателя, теряя информацию и делая невозможным уничтожение этого распределения памяти.

Кроме того, может быть хорошей идеей, чтобы переместить чтения XML-файлов из бесконечного цикла

CvMat *intrinsic = (CvMat*)cvLoad("Intrinsics.xml"); 
CvMat *distortion = (CvMat*)cvLoad("Distortion.xml"); 
+0

Я пробовал свои идеи, но ошибка также появляется. Есть ли какие-то нечетные программы? –

+0

В общем, я бы предложил использовать cv :: Mat вместо IplImage *. cv :: Mat - умный указатель и выпускает собственную память. Во-первых, это поможет вам уменьшить количество неудобных типов бросков, которые вы сейчас делаете, по мере того, как вы смешиваете типы. И, во-вторых, легче видеть, какую память вы выделяете и что вы освобождаете. Очевидно, что некоторые указатели IplImage * по-прежнему выделены, но никогда не выпущены. –

+0

Еще один вопрос к вашему первому вопросу. Вы выполняете различные преобразования и операции на кадре, который вы снимаете с подачи камеры. В итоге вы получите Mat cameraFeed_BE. На следующей строке кода после этого вы перезаписываете этот массив, захватывая видео снова capture.read (cameraFeed_BE), интересно, полностью ли это намеренно. –

Смежные вопросы