Адаптация в скрипте для OpenCV (Raspberry PI)

#c #opencv #raspberry-pi #object-detection

#c #opencv #raspberry-pi #обнаружение объекта

Вопрос:

Я работал над адаптацией учебника, которому следовал:

https://www.youtube.com/watch?v=RS_uQGOQIdg

В этом руководстве показано, как выполнить отслеживание нескольких объектов с помощью OpenCV через камеру, но в Windows. Я сделал это в своем Pi, и он работает нормально, как и должно было быть. Теперь я пытаюсь адаптировать это для проекта, над которым я работаю.

Этот проект, над которым я работаю, направлен на отслеживание перемещения цыплят на ферме, и, учитывая их координаты, мы бы проанализировали движение в течение дня и изучили их поведение с учетом множества других факторов (температура, влажность, еда и т. Д.).

Разница в том, что теперь я хочу отслеживать снимки, сделанные моей Raspicam каждые 10 минут, чтобы генерировать меньше обрабатываемых и ненужных данных. Проблема для меня в том, что я не очень разбираюсь в C , поэтому мне нужна ваша помощь, потому что я застрял.

Существует режим калибровки, это модуль, в котором я могу искать цвета, которые я хочу отслеживать, и когда он включен, я могу нормально отслеживать цыплят (их координаты отображаются на изображении). Поскольку я уже знаю эти цвета, мне это больше не нужно, поэтому я отключил его. Когда я делаю это, отслеживание перестает работать. Это твой основной файл, старый код теперь прокомментирован, и вы можете увидеть, что я пытался адаптировать:

 //objectTrackingTutorial.cpp

#include <sstream>
#include <string>
#include <iostream>
#include <vector>

#include "Chicken.h"


//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 = 20*20;
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);
   //create trackbars and insert them into window
   //3 parameters are: the address of the variable that is changing when the trackbar is moved(eg.H_LOW),
   //the max value the trackbar can move (eg. H_HIGH), 
   //and the function that is called whenever the trackbar is moved(eg. on_trackbar)
   //                                  ---->    ---->     ---->      
   createTrackbar( "H_MIN", trackbarWindowName, amp;H_MIN, H_MAX, on_trackbar );
   createTrackbar( "H_MAX", trackbarWindowName, amp;H_MAX, H_MAX, on_trackbar );
   createTrackbar( "S_MIN", trackbarWindowName, amp;S_MIN, S_MAX, on_trackbar );
   createTrackbar( "S_MAX", trackbarWindowName, amp;S_MAX, S_MAX, on_trackbar );
   createTrackbar( "V_MIN", trackbarWindowName, amp;V_MIN, V_MAX, on_trackbar );
   createTrackbar( "V_MAX", trackbarWindowName, amp;V_MAX, V_MAX, on_trackbar );

}
void drawObject(vector<Chicken> TheChickens,Mat amp;frame){

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

   cv::circle(frame,cv::Point(TheChickens.at(i).getXPos(),TheChickens.at(i).getYPos()),10,cv::Scalar(0,0,255));
   cv::putText(frame,intToString(TheChickens.at(i).getXPos())  " , "   intToString(TheChickens.at(i).getYPos()),cv::Point(TheChickens.at(i).getXPos(),TheChickens.at(i).getYPos() 20),1,1,Scalar(0,255,0));
   cv::putText(frame,TheChickens.at(i).getType(),cv::Point(TheChickens.at(i).getXPos(),TheChickens.at(i).getYPos()-30),1,2,TheChickens.at(i).getColour());
   }
}
void morphOps(Mat amp;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 amp;Image){


   vector <Chicken> chickens;

   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 the area is less than 20 px by 20px then it is probably just noise
            //if the area is the same as the 3/2 of the image size, probably just a bad filter
            //we only want the object with the largest area so we safe a reference area each
            //iteration and compare it to the area in the next iteration.
            if(area>MIN_OBJECT_AREA){

               Chicken chicken;

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

               chickens.push_back(chicken);

               objectFound = true;

            }else objectFound = false;


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

      }else putText(Image,"TOO MUCH NOISE! ADJUST FILTER",Point(0,50),1,2,Scalar(0,0,255),2);
   }
}
void trackFilteredObject(Chicken theChicken,Mat threshold,Mat HSV, Mat amp;Image){
   std::cout << "Trackfilteredobject called";

   vector <Chicken> chickens;

   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;


// Problem here, hierarchy size equals 0
   if (hierarchy.size() >0) {
      std::cout << "First if";
      int numObjects = hierarchy.size();
      //if number of objects greater than MAX_NUM_OBJECTS we have a noisy filter
      if(numObjects<MAX_NUM_OBJECTS){
         std::cout << "Second if";
         for (int index = 0; index >= 0; index = hierarchy[index][0]) {
            std::cout <<"Inside Loop";
            Moments moment = moments((cv::Mat)contours[index]);
            double area = moment.m00;

            //if the area is less than 20 px by 20px then it is probably just noise
            //if the area is the same as the 3/2 of the image size, probably just a bad filter
            //we only want the object with the largest area so we safe a reference area each
            //iteration and compare it to the area in the next iteration.
            if(area>MIN_OBJECT_AREA){

               Chicken chicken;

               chicken.setXPos(moment.m10/area);
               chicken.setYPos(moment.m01/area);
               chicken.setType(theChicken.getType());
               chicken.setColour(theChicken.getColour());

               chickens.push_back(chicken);
               std::cout << "Chicken Found!";
               objectFound = true;

            }else objectFound = false;


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

      }else putText(Image,"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 = false;

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

   if(calibrationMode){
      //create slider bars for HSV filtering
      createTrackbars();
   }

   Mat Image = imread("image0117.jpg", 1);

   //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);
   //start an infinite loop where webcam feed is copied to cameraFeed matrix
   //all of our operations will be performed within this loop
   while(1){

      //store image to matrix
      //capture.read(cameraFeed);
      //convert frame from BGR to HSV Colorspace
      cvtColor(Image,HSV,CV_BGR2HSV);
      if(calibrationMode==true){

      //if in calibration mode, we track objects based on the HSV slider values.
      cvtColor(Image,HSV,CV_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,Image);
      }else{
      //create some temp Color objects so that
      //we can use their member functions/information
      Chicken chicken1("chicken1");

      std::cout << "Chicken Created! n";

      //first find chickens
      cvtColor(Image,HSV,CV_BGR2HSV);
      inRange(HSV,chicken1.getHSVmin(),chicken1.getHSVmax(),threshold);
      morphOps(threshold);
      trackFilteredObject(chicken1,threshold,HSV,Image);
      }

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


      //delay 30ms so that screen can refresh.
      //image will not appear without this waitKey() command
      waitKey(0);
   }


   return 0;
}
  

Класс Chicken:

 #include "Chicken.h"



Chicken::Chicken()
{
   //set values for default constructor
   setType("null");
   setColour(Scalar(0,0,0));

}

Chicken::Chicken(string name){

   setType(name);

   if(name=="chicken1"){

      //TODO: use "calibration mode" to find HSV min
      //and HSV max values

      setHSVmin(Scalar(0,0,48));
      setHSVmax(Scalar(115,256,48));

      //BGR value for Chicken:
      setColour(Scalar(0,250,0));

   }


}

Chicken::~Chicken(void)
{
}

int Chicken::getXPos(){

   return Chicken::xPos;

}

void Chicken::setXPos(int x){

   Chicken::xPos = x;

}

int Chicken::getYPos(){

   return Chicken::yPos;

}

void Chicken::setYPos(int y){

   Chicken::yPos = y;

}

Scalar Chicken::getHSVmin(){

   return Chicken::HSVmin;

}
Scalar Chicken::getHSVmax(){

   return Chicken::HSVmax;
}

void Chicken::setHSVmin(Scalar min){

   Chicken::HSVmin = min;
}


void Chicken::setHSVmax(Scalar max){

   Chicken::HSVmax = max;
}
  

Заголовочный файл:

 #pragma once
#include <string>
#include <opencv/cv.h>
#include <opencv/highgui.h>
using namespace std;
using namespace cv;

class Chicken
{
public:
   Chicken();
   ~Chicken(void);

   Chicken(string name);

   int getXPos();
   void setXPos(int x);

   int getYPos();
   void setYPos(int y);

   Scalar getHSVmin();
   Scalar getHSVmax();

   void setHSVmin(Scalar min);
   void setHSVmax(Scalar max);

   string getType(){return type;}
   void setType(string t){type = t;}

   Scalar getColour(){
      return Colour;
   }
   void setColour(Scalar c){

      Colour = c;
   }

private:

   int xPos, yPos;
   string type;
   Scalar HSVmin, HSVmax;
   Scalar Colour;
};
  

И это образ, в котором я работаю:

https://www.dropbox.com/s/k7r0p6cha3duomi/image0117.jpg

Я надеюсь, что кто-нибудь сможет мне помочь, мои знания в C невелики :/

Спасибо!