Webcam sphere

De system.co.free.fr.

retour vers linux

Sommaire

WebCam logitech Web-Sphere (QuickCam Orbit) motorisée et autres WebCam UVC sous linux

La QuickCam Orbit est reconnu comme un périphérique UVC.
UVC: USB Video Class en anglais
http://fr.wikipedia.org/wiki/USB_video_device_class
Linux n'est pas le seul concerné par cette norme. Solaris, Mac OS X, ... et Windows le sont aussi.
Le driver UVC est intégré au noyau depuis la version 2.6.26. Donc rien a faire a ce niveau :-) La WebCam fonctionne avec vos logiciels habituels.
Pour ce qui est de la motorisation, c'est ci-dessous.

webcam motorisée, installez uvcdynctrl du dépôt universe

Pour l'installer:

 apt-get install uvcdynctrl

cela peux nécessiter l'installation de paquets supplémentaires. Si c'est le cas, apt-get vous proposera de les installer:

libwebcam0 uvcdynctrl-data


débranché la Web-Sphere usb et rebranché la.
De façon générale, en cas de dysfonctionnement, n'hesitez pas a la débrancher et la rebrancher avant de pousser trop loin vos investigations. (il existe une autre solution par ligne de commande pour réinitialiser les périphériques usb avec les outils udev, mais je ne l'ai plus en mémoire.)

uvcdynctrl: Utilisation

Cet outil, en ligne de commande est a utiliser en parallèle de votre logiciel favoris de visionnement de webcam UVC.

Pour lister les périphériques accessibles par la commande uvcdynctrl

 uvcdynctrl -l
 Listing available devices:
   video0   UVC Camera (046d:0994)
     Media controller device /dev/media1 doesn't exist
 ERROR: Unable to list device entities: Invalid device or device cannot be opened. (Code: 5)

Les 2 dernières lignes ne sont pas importantes. uvcdynctrl recherche par défaut des periphériques sur /dev/media*

Pour lister les formats possible de votre périphérique (par défaut /dev/video0 sinon préciser -d /dev/video34 par exemple):

uvcdynctrl -f 
Listing available frame formats for device video0:
Pixel format: MJPG (MJPEG; MIME type: image/jpeg)
  Frame size: 160x120
    Frame rates: 30, 25, 20, 15, 10, 5
  Frame size: 176x144
    Frame rates: 30, 25, 20, 15, 10, 5
  Frame size: 320x240
    Frame rates: 30, 25, 20, 15, 10, 5
  Frame size: 352x288
    Frame rates: 30, 25, 20, 15, 10, 5
  Frame size: 640x480
    Frame rates: 30, 25, 20, 15, 10, 5
  Frame size: 800x600
    Frame rates: 30, 25, 20, 15, 10, 5
  Frame size: 960x720
    Frame rates: 15, 10, 5
Pixel format: YUYV (YUV 4:2:2 (YUYV); MIME type: video/x-raw-yuv)
  Frame size: 160x120
    Frame rates: 30, 25, 20, 15, 10, 5
  Frame size: 176x144
    Frame rates: 30, 25, 20, 15, 10, 5
  Frame size: 320x240
    Frame rates: 30, 25, 20, 15, 10, 5
  Frame size: 352x288
    Frame rates: 30, 25, 20, 15, 10, 5
  Frame size: 640x480
    Frame rates: 30, 25, 20, 15, 10, 5
  Frame size: 800x600
    Frame rates: 25, 20, 15, 10, 5
  Frame size: 960x720
    Frame rates: 10, 5
  Frame size: 1600x1200
    Frame rates: 5

Voici pour ma WebCam logitech Web-Sphere

Pour lister les contrôles possibles du périphérique (par défaut /dev/video0 )

 uvcdynctrl -c
 Listing available controls for device /dev/video0:
   Brightness
   Contrast
   Saturation
   White Balance Temperature, Auto
   Gain
   Power Line Frequency
   White Balance Temperature
   Sharpness
   Backlight Compensation
   Exposure, Auto
   Exposure (Absolute)
   Exposure, Auto Priority
   Pan (relative)
   Tilt (relative)
   Pan Reset
   Tilt Reset
   Focus
   LED1 Mode
   LED1 Frequency
   Disable video processing
   Raw bits per pixel


Pour avoir le detail des paramétres pour chaque option ( par defaut /dev/video0, si defferent ajouter l'option -d /dev/video9 ou autres )

 uvcdynctrl -c -v
 Listing available controls for device /dev/video0:
 Brightness
   ID      : 0x00000001,
   Type    : Dword,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ 0 .. 255, step size: 1 ],
   Default : 128
 Contrast
   ID      : 0x00000002,
   Type    : Dword,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ 0 .. 255, step size: 1 ],
   Default : 32
 Saturation
   ID      : 0x00000004,
   Type    : Dword,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ 0 .. 255, step size: 1 ],
   Default : 32
 White Balance Temperature, Auto
   ID      : 0x00000009,
   Type    : Boolean,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ 0 .. 1, step size: 1 ],
   Default : 1
 Gain
   ID      : 0x00000003,
   Type    : Dword,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ 0 .. 255, step size: 1 ],
   Default : 0
 Power Line Frequency
   ID      : 0x0000000d,
   Type    : Choice,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : { 'Disabled'[0], '50 Hz'[1], '60 Hz'[2] },
   Default : 2
 White Balance Temperature
   ID      : 0x00000008,
   Type    : Dword,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ 0 .. 10000, step size: 10 ],
   Default : 4000
 Sharpness
   ID      : 0x00000007,
   Type    : Dword,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ 0 .. 255, step size: 1 ],
   Default : 224
 Backlight Compensation
   ID      : 0x0000000c,
   Type    : Dword,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ 0 .. 2, step size: 1 ],
   Default : 1
 Exposure, Auto
   ID      : 0x0000000f,
   Type    : Choice,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : { 'Manual Mode'[1], 'Aperture Priority Mode'[3] },
   Default : 3
 Exposure (Absolute)
   ID      : 0x00000011,
   Type    : Dword,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ 1 .. 10000, step size: 1 ],
   Default : 166
 Exposure, Auto Priority
   ID      : 0x00000010,
   Type    : Boolean,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ 0 .. 1, step size: 1 ],
   Default : 0
 Pan (relative)
   ID      : 0x0000001c,
   Type    : Dword,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ -4480 .. 4480, step size: 0 ],
   Default : 0
 Tilt (relative)
   ID      : 0x0000001e,
   Type    : Dword,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ -1920 .. 1920, step size: 0 ],
   Default : 0
 Pan Reset
   ID      : 0x00000022,
   Type    : Button,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ 0 .. 0, step size: 0 ],
   Default : 0
 Tilt Reset
   ID      : 0x00000023,
   Type    : Button,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ 0 .. 0, step size: 0 ],
   Default : 0
 Focus
   ID      : 0x00000014,
   Type    : Dword,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ 0 .. 255, step size: 1 ],
   Default : 0
 LED1 Mode
   ID      : 0x046d0003,
   Type    : Choice,
   Flags   : { CAN_READ, CAN_WRITE, IS_CUSTOM },
   Values  : { 'Off'[0], 'On'[1], 'Blinking'[2], 'Auto'[3] },
   Default : 3
 LED1 Frequency
   ID      : 0x046d0004,
   Type    : Dword,
   Flags   : { CAN_READ, CAN_WRITE, IS_CUSTOM },
   Values  : [ 0 .. 255, step size: 1 ],
   Default : 0
 Disable video processing
   ID      : 0x046d0005,
   Type    : Boolean,
   Flags   : { CAN_READ, CAN_WRITE, IS_CUSTOM },
   Values  : [ 0 .. 1, step size: 1 ],
   Default : 0
 Raw bits per pixel
   ID      : 0x046d0006,
   Type    : Dword,
   Flags   : { CAN_READ, CAN_WRITE, IS_CUSTOM },
   Values  : [ 0 .. 1, step size: 1 ],
   Default : 0

Pour la motorisation, se sont les 4 options lié a Pan et Tilt qui vont nous interesser (rien ne vous empeche de faire mumuse avec les autres :-) )

 Pan (relative)
   ID      : 0x0000001c,
   Type    : Dword,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ -4480 .. 4480, step size: 0 ],
   Default : 0
 Tilt (relative)
   ID      : 0x0000001e,
   Type    : Dword,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ -1920 .. 1920, step size: 0 ],
   Default : 0
 Pan Reset
   ID      : 0x00000022,
   Type    : Button,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ 0 .. 0, step size: 0 ],
   Default : 0
 Tilt Reset
   ID      : 0x00000023,
   Type    : Button,
   Flags   : { CAN_READ, CAN_WRITE },
   Values  : [ 0 .. 0, step size: 0 ],
   Default : 0

On peut voir que 'Pan Reset' et 'Tilt Reset' ne prennent qu'un paramètre: 0
Pour les utiliser on lancera donc la ligne de commande:

 uvcdynctrl -d /dev/video0 -s 'Pan Reset' 0

Et vous verrez votre Web-Cam tourné horizontalement et revenir au centre.

 uvcdynctrl -d /dev/video0 -s 'Tilt Reset' 0

Pour la voir se recentrer verticalement


Pour le paramètre 'Pan (relative)' les valeurs acceptées vont de -4480 à 4480 comme indique pour Values
Si vous tenter de lire la valeur actuel des 'Pan (relative)' et 'Tilt (relative)' par la commande

   uvcdynctrl -d /dev/video0 -g 'Pan (relative)'

ou

   uvcdynctrl -d /dev/video0 -g 'Tilt (relative)'

Vous aurez un beau message d'erreur:

  ERROR: Unable to retrieve control value: A Video4Linux2 API call returned an unexpected error 22. (Code: 12)

Vous essayez de lire une valeur de position relative ( relative a elle meme), qui par définition est relative. C'est a dire égale a 0.
On regrette donc que ces 2 options soient en "CAN_READ", ce qui est de la responsabilité du constructeur ...

vous ne pouvez les utiliser qu'en écriture. Exemple de commande a passer:

   uvcdynctrl -d /dev/video0 -s 'Pan (relative)' -- -4480
   uvcdynctrl -d /dev/video0 -s 'Tilt (relative)' 1920

La 1ere commande va donc tenter de déplacer vers la droite (-) de 4480 unités ( le max accepté )par rapport a la position actuelle. La 2eme commande va tenter de deplacer vers le bas (+) de 1920 unités (le max accepter ) par rapport a la position actuelle.

Programmation UVC: des fonctions de libwebcam utilisées par uvcdynctrl

 #include <webcam.h>
 CResult c_get_control (CHandle hDevice, CControlId control_id, CControlValue *value)
 CResult c_set_control (CHandle hDevice, CControlId control_id, const CControlValue *value)
 CResult c_enum_events (CHandle hDevice, CEvent *events, unsigned int *size, unsigned int *count) 
 CResult c_enum_frame_intervals(hDevice, pixelformat, framesize, NULL, &size, &count)
 CResult c_enum_frame_sizes(hDevice, pixelformat, NULL, &size, &count);
 CResult c_enum_pixel_formats(hDevice, NULL, &size, &count);
 CResult c_enum_devices(devices, &req_size, &count);
 CHandle c_open_device (const char *device_name)
 CResult c_init(void)
 ...

a linker a libwebcam

Programmation UVC: un exemple d'utilisation de la libwebcam

Un exemple de Ana Huamán tiré du tutorial de OpenCV ( http://docs.opencv.org/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.html#cascade-classifier ) repris et modifié pour suivre un visage avec la motorisation. . L’idéal serait d'avoir réussi a faire fonctionner l'exemple d'origine.

Demo filmé sous youtube


http://youtu.be/IRUDeyVWi6U

Code Sources


Nécessite d'avoir OpenCV d'installé (voir OpenCV), libwebcam-dev et Qt4 (Les lib d'openCV ont été créé avec l’utilisation de QT4). Une seul webcam doit être connecté a Linux, La WebSphere. Mon code ajouté est un exemple a ne pas suivre, il est codé comme du script et dans un mélange de c++ et c. J'en ai honte. Quand j'aurais un peu de temps, je le reprendrais. Milles excuses pour ce code merdique. Il est du aux multitudes d'essais nécessaires. Vous verrez également des tempo...du préhistorique rendu nécessaire par la motorisation de la webcam tres rustique.
il est nécessite d'avoir le fichier haarcascade_frontalface_alt.xml de l’OpenCV dans le même répertoire que ce fichier exécutable.

/**
 * @file objectDetection.cpp
 * @author A. Huaman ( based in the classic facedetect.cpp in samples/c )
 * @brief A simplified version of facedetect.cpp, show how to load a cascade classifier and how to find objects (Face + eyes) in a video stream
 */
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <webcam.h>

#include <iostream>
#include <stdio.h>

#include <unistd.h>

using namespace std;
using namespace cv;

/** Function Headers */
void detectAndDisplay( Mat &frame );

/** Global variables */

String face_cascade_name = "haarcascade_frontalface_alt.xml";

CascadeClassifier face_cascade;

string window_name = "Capture - Face detection";

int hauteur=480;
int largeur=640;
int viseur_mot=100;

CHandle handle = 0;
int reset_centre=0;

/********************************************************************************************
 * @function main
 *********************************************************************************************/
int main( int argc, const char** argv )
{
  printf("--(!)Debut\n");
  CvCapture* capture;
  Mat frame;
   //-- 1. Load  cascade
   if( !face_cascade.load( face_cascade_name ) )
       {
        printf("--(!)Erreur de lecture du fichier haarcascade_frontalface_alt.xml\n");
        return -1; 
        }

//////////////////////////////////////////////////////////////////////////////////////////////
//    ajouter pour gerer la motorisation logitech
//    avec libwebcam pour uvc
//////////////////////////////////////////////////////////////////////////////////////////////
  CResult res = C_SUCCESS;
  res = c_init();
  if (res) 
    {	
    c_cleanup();
    res = c_init();
    if (res) 
      {
      printf("--(!)Erreur c_init de libwebcam\n");
      return -1;
      }
    }


  handle=c_open_device ("/dev/video0");
  printf("libwebcam handle=%i\n",handle);
  if ( ! handle) 
    {
    printf("--(!)Erreur open_device de libwebcam\n");
    return -1;
    }

  //-- 2. Read the video stream
  capture = cvCreateCameraCapture(-1);
  printf("--(!)Creation de capture\n");

/********************************************************************************************
 * Effectue un Reset des motorisations
 *********************************************************************************************/
  CControlValue CCContValue;
  CCContValue.value=0;
  c_set_control(handle, CC_PAN_RESET, &CCContValue);
  usleep(2500000);
  c_set_control(handle, CC_TILT_RESET, &CCContValue);
  usleep(2500000);


cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH, static_cast<double>(largeur));
cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT, static_cast<double>(hauteur));

 printf("--(!)Definition de la hauteur et largeur\n");
  if( capture )
  {
     printf("--(!)Avant Entre boucle while\n");

     while( true )
    {
       
      frame = cvQueryFrame( capture );

      //-- 3. Apply the classifier to the frame
      if( !frame.empty() )
       { detectAndDisplay( frame ); }
      else
       { printf(" --(!) No captured frame -- Break!"); break; }

      int c = waitKey(10);
      if( (char)c == 'c' ) { break; }

    }
  }
  c_close_device (handle);
  c_cleanup();
  return 0;
}

/**
 * @function detectAndDisplay
 */
void detectAndDisplay( Mat &frame )
{
   std::vector<Rect> faces;
   Mat frame_gray;
   CResult cresult_con;
   cvtColor( frame, frame_gray, CV_BGR2GRAY );
   equalizeHist( frame_gray, frame_gray );

//-- Carre de visé pour la motorisation
   rectangle( frame, cvPoint( (largeur - viseur_mot) / 2, (hauteur + viseur_mot) / 2),
	      cvPoint( (largeur + viseur_mot) / 2 , (hauteur - viseur_mot) / 2), Scalar( 0, 0, 255 ),2 );
   
//-- Detect faces 
   face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
    if (faces.size() < 1 )
    {
      reset_centre++;
      if (reset_centre > 200)
      {
	  CControlValue CCContValue;
	  CCContValue.value=1;
	  c_set_control(handle, CC_TILT_RESET, &CCContValue);
	  usleep(2500000);
	  c_set_control(handle, CC_PAN_RESET, &CCContValue);
	  usleep(2500000); 
	  reset_centre=-500;
      }
    }
    
   for( int i = 0; i < faces.size(); i++ )
    {
      Point center( faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5 );
      ellipse( frame, center, Size( faces[i].width*0.4, faces[i].height*0.6), 0, 0, 360, Scalar( 255, 0, 255 ), 2, 8, 0 );
      
if  (  faces.size() == 1 )
{     // depasse en x
      CControlValue  CCContValue;
      if (center.x > ((largeur + viseur_mot) / 2)) 
      {	
	CCContValue.type = CC_TYPE_WORD;
	CCContValue.value = -70;
	c_set_control(handle, CC_PAN_RELATIVE, &CCContValue);
	goto next;
      }
      
      if (center.x < ((largeur - viseur_mot) / 2) ) 
      {	
	CCContValue.type = CC_TYPE_WORD;
	CCContValue.value = 70;
	c_set_control(handle, CC_PAN_RELATIVE, &CCContValue);
        goto next;
      }

        if (center.y > ((hauteur + viseur_mot) / 2)  ) 
      {	
	CCContValue.type = CC_TYPE_WORD;
	CCContValue.value = 70;
	c_set_control(handle, CC_TILT_RELATIVE, &CCContValue);
	goto next;
      }
      if (center.y < ((hauteur - viseur_mot) / 2) ) 
      {	
	CCContValue.type = CC_TYPE_WORD;
	CCContValue.value = -70;
	c_set_control(handle, CC_TILT_RELATIVE, &CCContValue);
	goto next;
      }
      next:
      reset_centre=0;
}    
      
      Mat faceROI = frame_gray( faces[i] );
      imshow( "face", faceROI );
    
    }
   //-- Show what you got
//   imshow( "en_gris", frame_gray );
   imshow( window_name, frame );  
}


le fichier CMakeLists.txt a mettre dans le meme repertoire:

project( CameraVisage )
FIND_PACKAGE(OpenCV REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ")
# Linking (add flags as needed)
add_executable( CameraVisage main.cpp )
target_link_libraries( CameraVisage ${OpenCV_LIBS} /usr/lib/libwebcam.so )
Outils personnels