Seguimiento de objetos rápido - Robot Visión por Computador
Yo quería mi robot para poder hacer un seguimiento de objetos y seguirlos. Lo primero que quería hacer es darle al robot la capacidad de seguir un objeto con su cámara de cabeza. El cabezal de la cámara está montada sobre un sistema de servo pan-tilt, y por lo tanto es capaz de moverse a izquierda y derecha, arriba y abajo (como se ve en la foto de abajo).
Mi segundo objetivo el seguimiento de objetos era hacer que el robot después de perseguir un objeto, como un perro perseguir una pelota lanzada por su dueño. Este tipo de seguimiento es muy difícil - que usaría el cabezal de la cámara de seguimiento de la etapa anterior, y combinarlo con el resto de los sensores del robot para seguir el objeto.
¿Cómo?
Para lograr que voy a tratar de varias imágenes básicas \ algoritmos de visión por computador. Voy a utilizar el OpenCV biblioteca. OpenCV, como su nombre lo indica, es un código abierto visión por ordenador de la biblioteca original
desarrollado por Intel. Es multiplataforma (yo lo he utilizado tanto en un PC y en el ARM BeagleBoard ). OpenCV es bastante fácil de usar si usted tiene conocimientos básicos en el procesamiento de imágenes.
El primer objeto que yo quería hacer un seguimiento era una llanura de bolas de color naranja.
Color en función de seguimiento
Filtro sólo el color naranja de la imagen. Para hacer eso, me convertí en la imagen para el espacio de color HSV , y luego se usa el filtro dos veces cvInRange para filtrar los colores naranja.
En la primera foto de abajo puedes ver el vapor de vídeo convierte en el espacio de color HSV, y en la segunda imagen se puede ver el resultado de que el color rojo de filtrado (todos los colores menos el rojo se han filtrado).
(Código python)
#declare necessary objects hsv_frame = cvCreateImage(size, IPL_DEPTH_8U, 3) thresholded = cvCreateImage(size, IPL_DEPTH_8U, 1) thresholded2 = cvCreateImage(size, IPL_DEPTH_8U, 1) hsv_min = cvScalar(0, 50, 170, 0) hsv_max = cvScalar(10, 180, 256, 0) hsv_min2 = cvScalar(170, 50, 170, 0) hsv_max2 = cvScalar(256, 180, 256, 0) # convert to HSV for color matching # as hue wraps around, we need to match it in 2 parts and OR together cvCvtColor(frame, hsv_frame, CV_BGR2HSV) cvInRangeS(hsv_frame, hsv_min, hsv_max, thresholded) cvInRangeS(hsv_frame, hsv_min2, hsv_max2, thresholded2) cvOr(thresholded, thresholded2, thresholded)
Shape based tracking
Then, I used Hough transform to detect the shape of a circle. Before applying the hough transform I smoothed the image because it seems to improve the results.
# pre-smoothing improves Hough detector cvSmooth(thresholded, thresholded, CV_GAUSSIAN, 9, 9) circles = cvHoughCircles(thresholded, storage, CV_HOUGH_GRADIENT, 2, thresholded.height/4, 100, 40, 20, 200)
The result
The result is pretty impressive. The code functions very well and detects the ball under most circumstances (i.e. the ball is far from the camera, close to the camera, slow movement, fast movement, etc).
You can see the result in this video:
Full python sources including servo movement
/***************************************************************************************** * Name : Fast object tracking using the OpenCV library * * Author : Lior Chen <chen.lior@gmail.com> * * Notice : Copyright (c) Jun 2010, Lior Chen, All Rights Reserved * * : * * Site : http://www.lirtex.com * * WebPage : http://www.lirtex.com/robotics/fast-object-tracking-robot-computer-vision * * : * * Version : 1.0 * * Notes : By default this code will open the first connected camera. * * : In order to change to another camera, change * * : CvCapture* capture = cvCaptureFromCAM( 0 ); to 1,2,3, etc. * * : Also, the code is currently configured to tracking RED objects. * * : This can be changed by changing the hsv_min and hsv_max vectors * * : * * License : This program is free software: you can redistribute it and/or modify * * : it under the terms of the GNU General Public License as published by * * : the Free Software Foundation, either version 3 of the License, or * * : (at your option) any later version. * * : * * : This program is distributed in the hope that it will be useful, * * : but WITHOUT ANY WARRANTY; without even the implied warranty of * * : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * : GNU General Public License for more details. * * : * * : You should have received a copy of the GNU General Public License * * : along with this program. If not, see <http://www.gnu.org/licenses/> * ******************************************************************************************/ #!/usr/bin/python # -*- coding: utf-8 -*- from opencv.cv import * from opencv.highgui import * from threading import Thread #import serial class RobotVision: cvSize size cvImage hsv_frame, thresholded, thresholded2 cvScalar hsv_min, hsv_max, hsv_min2, hsv_max2 cvCapture capture; def InitBallTracking(): globals size, hsv_frame, thresholded, thresholded2, hsv_min, hsv_max, hsv_min2, hsv_max2, capture print "Initializing ball Tracking" size = cvSize(640, 480) hsv_frame = cvCreateImage(size, IPL_DEPTH_8U, 3) thresholded = cvCreateImage(size, IPL_DEPTH_8U, 1) thresholded2 = cvCreateImage(size, IPL_DEPTH_8U, 1) hsv_min = cvScalar(0, 50, 170, 0) hsv_max = cvScalar(10, 180, 256, 0) hsv_min2 = cvScalar(170, 50, 170, 0) hsv_max2 = cvScalar(256, 180, 256, 0) storage = cvCreateMemStorage(0) # start capturing form webcam capture = cvCreateCameraCapture(-1) if not capture: print "Could not open webcam" sys.exit(1) #CV windows cvNamedWindow( "Camera", CV_WINDOW_AUTOSIZE ); def TrackBall(i): t = Thread(target=TrackBallThread, args=(i,)) t.start() def TrackBallThread(num_of_balls): globals size, hsv_frame, thresholded, thresholded2, hsv_min, hsv_max, hsv_min2, hsv_max2, capture while 1: # get a frame from the webcam frame = cvQueryFrame(capture) if frame is not None: # convert to HSV for color matching # as hue wraps around, we need to match it in 2 parts and OR together cvCvtColor(frame, hsv_frame, CV_BGR2HSV) cvInRangeS(hsv_frame, hsv_min, hsv_max, thresholded) cvInRangeS(hsv_frame, hsv_min2, hsv_max2, thresholded2) cvOr(thresholded, thresholded2, thresholded) # pre-smoothing improves Hough detector cvSmooth(thresholded, thresholded, CV_GAUSSIAN, 9, 9) circles = cvHoughCircles(thresholded, storage, CV_HOUGH_GRADIENT, 2, thresholded.height/4, 100, 40, 20, 200) # find largest circle maxRadius = 0 x = 0 y = 0 found = False for i in range(circles.total): circle = circles[i] if circle[2] > maxRadius: found = True maxRadius = circle[2] x = circle[0] y = circle[1] cvShowImage( "Camera", frame ); if found: print "ball detected at position:",x, ",", y, " with radius:", maxRadius if x > 420: # need to pan right servoPos += 5 servoPos = min(140, servoPos) servo(2, servoPos) elif x < 220: servoPos -= 5 servoPos = max(40, servoPos) servo(2, servoPos) print "servo position:", servoPos else: print "no ball"
Sample Sources
This c++ code takes a video stream from an attached video camera, looks for an orange ball inside the stream, and prints the coordinates of the ball.
Three “debug” windows are shown to clarify the process: 1) the video capture. 2) the stream after the conversion to HSV, 3) the stream after conversion to HSV, color-filtering, and Hough transform.
/*****************************************************************************************
* Name : Fast object tracking using the OpenCV library *
* Author : Lior Chen <chen.lior@gmail.com> *
* Notice : Copyright (c) Jun 2010, Lior Chen, All Rights Reserved *
* : *
* Site : http://www.lirtex.com *
* WebPage : http://www.lirtex.com/robotics/fast-object-tracking-robot-computer-vision *
* : *
* Version : 1.0 *
* Notes : By default this code will open the first connected camera. *
* : In order to change to another camera, change *
* : CvCapture* capture = cvCaptureFromCAM( 0 ); to 1,2,3, etc. *
* : Also, the code is currently configured to tracking RED objects. *
* : This can be changed by changing the hsv_min and hsv_max vectors *
* : *
* License : This program is free software: you can redistribute it and/or modify *
* : it under the terms of the GNU General Public License as published by *
* : the Free Software Foundation, either version 3 of the License, or *
* : (at your option) any later version. *
* : *
* : This program is distributed in the hope that it will be useful, *
* : but WITHOUT ANY WARRANTY; without even the implied warranty of *
* : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* : GNU General Public License for more details. *
* : *
* : You should have received a copy of the GNU General Public License *
* : along with this program. If not, see <http://www.gnu.org/licenses/> *
******************************************************************************************/
#include <opencv/cvaux.h>
#include <opencv/highgui.h>
#include <opencv/cxcore.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <time.h>
#include <ctype.h>
int main(int argc, char* argv[])
{
// Default capture size - 640x480
CvSize size = cvSize(640,480);
// Open capture device. 0 is /dev/video0, 1 is /dev/video1, etc.
CvCapture* capture = cvCaptureFromCAM( 0 );
if( !capture )
{
fprintf( stderr, "ERROR: capture is NULL \n" );
getchar();
return -1;
}
// Create a window in which the captured images will be presented
cvNamedWindow( "Camera", CV_WINDOW_AUTOSIZE );
cvNamedWindow( "HSV", CV_WINDOW_AUTOSIZE );
cvNamedWindow( "EdgeDetection", CV_WINDOW_AUTOSIZE );
// Detect a red ball
CvScalar hsv_min = cvScalar(150, 84, 130, 0);
CvScalar hsv_max = cvScalar(358, 256, 255, 0);
IplImage * hsv_frame = cvCreateImage(size, IPL_DEPTH_8U, 3);
IplImage* thresholded = cvCreateImage(size, IPL_DEPTH_8U, 1);
while( 1 )
{
// Get one frame
IplImage* frame = cvQueryFrame( capture );
if( !frame )
{
fprintf( stderr, "ERROR: frame is null...\n" );
getchar();
break;
}
// Covert color space to HSV as it is much easier to filter colors in the HSV color-space.
cvCvtColor(frame, hsv_frame, CV_BGR2HSV);
// Filter out colors which are out of range.
cvInRangeS(hsv_frame, hsv_min, hsv_max, thresholded);
// Memory for hough circles
CvMemStorage* storage = cvCreateMemStorage(0);
// hough detector works better with some smoothing of the image
cvSmooth( thresholded, thresholded, CV_GAUSSIAN, 9, 9 );
CvSeq* circles = cvHoughCircles(thresholded, storage, CV_HOUGH_GRADIENT, 2,
thresholded->height/4, 100, 50, 10, 400);
for (int i = 0; i < circles->total; i++)
{
float* p = (float*)cvGetSeqElem( circles, i );
printf("Ball! x=%f y=%f r=%f\n\r",p[0],p[1],p[2] );
cvCircle( frame, cvPoint(cvRound(p[0]),cvRound(p[1])),
3, CV_RGB(0,255,0), -1, 8, 0 );
cvCircle( frame, cvPoint(cvRound(p[0]),cvRound(p[1])),
cvRound(p[2]), CV_RGB(255,0,0), 3, 8, 0 );
}
cvShowImage( "Camera", frame ); // Original stream with detected ball overlay
cvShowImage( "HSV", hsv_frame); // Original stream in the HSV color space
cvShowImage( "After Color Filtering", thresholded ); // The stream after color filtering
cvReleaseMemStorage(&storage);
// Do not release the frame!
//If ESC key pressed, Key=0x10001B under OpenCV 0.9.7(linux version),
//remove higher bits using AND operator
if( (cvWaitKey(10) & 255) == 27 ) break;
}
// Release the capture device housekeeping
cvReleaseCapture( &capture );
cvDestroyWindow( "mywindow" );
return 0;
}








