A webcam USB utilizada no AD4M4ST0R é uma Logitech C170.
Depois de ligada são reconhecidos dois devices: uma webcam propriamente dita do tipo UVC (USB Video Class) gerida pelo v4l2 e um microfone gerido como uma placa de som pelo ALSA:
root@ev3dev:~# dmesg (...) usb 1-1.3: new full-speed USB device number 5 using ohci Linux video capture interface: v2.00 uvcvideo: Found UVC 1.00 device Webcam C170 (046d:082b) input: Webcam C170 as /devices/platform/ohci.0/usb1/1-1/1-1.3/1-1.3:1.0/input/input3 usbcore: registered new interface driver uvcvideo USB Video Class driver (1.1.1) usbcore: registered new interface driver snd-usb-audio
O microfone não aparece como dispositivo USB, apenas a webcam:
root@ev3dev:~# lsusb Bus 001 Device 005: ID 046d:082b Logitech, Inc. (...)
mas se formos ver ao alsamixer temos lá uma nova placa de som: “Webcam C170”.
A parte mais crítica, a criação de um dispositivo video, também funcionou:
root@ev3dev:~# ls /dev
mostra entre outros “video0”.
Como a webcam foi também reconhecida como um dispositivo OHCI temos ainda:
root@ev3dev:~# ls /dev/input/by-id/ -la (...) lrwxrwxrwx 1 root root 9 Aug 18 12:13 usb-_Webcam_C170-event-if00 -> ../event3 (...)
Para capturar imagens da webcam optei pelo fswebcam
apt-get install fswebcam
Como já o tinha experimentado com esta mesma webcam no meu Ubuntu, avanço para um comando que sei que funciona:
fswebcam -d /dev/video0 -p YUYV -r 640x480 teste.jpg
E efectivamente funciona só que quando fui ver a imagem esta tinha apenas 176×144 e não 640×480 (e o próprio comando devolve isso: “Adjusting resolution from 640×480 to 176×144”). Mas que raio…?
Perdi algum tempo nisto por isso vou alongar-me um pouco mais para que outros que passem pelo mesmo possam beneficiar também.
Descobri que a câmara permite despejar video em dois formatos diferentes: YUYV e MJPG:
root@ev3dev:~# v4l2-ctl --list-formats ioctl: VIDIOC_ENUM_FMT Index : 0 Type : Video Capture Pixel Format: 'YUYV' Name : YUV 4:2:2 (YUYV) Index : 1 Type : Video Capture Pixel Format: 'MJPG' (compressed) Name : MJPEG
MJPG (Motion JPEG) é um formato com compressão (e alguma perda também) e por isso consome menos largura de banda que o YUYV. A minha teoria é de que sendo o bus USB do EV3 apenas 1.1 (11 Mbps) em vez de USB 2.0 (480 Mbps) como no meu Ubuntu a webcam de algum modo se autoconfigura para a largura de banda disponível. Por isso no Ubuntu ao pedir com o fswebcam uma foto 640×480 extraída de video gerado em formato YUV ele consiga mas no EV3 seja obrigado a reduzir para 176×144.
A solução foi indicar ao fswebcam para lidar com MJPG:
fswebcam -d /dev/video0 -p MJPEG -r 640x480 teste.jpg
Agora já funciona, excepto que nalgumas situações ocorre um erro semelhante a este (os dois números hexadecimais do final variam):
GD Error: gd-jpeg: JPEG library reports unrecoverable error: Not a JPEG file: starts with 0x92 0x7
Aparentemente algumas webcams (e pelos vistos a maioria são da Logitech?) demora a estabilizar a captura e por isso produz lixo nas primeiras frames. As soluções passam invariavelmente por descartar umas quantas frames inicais… só ainda não encontrem o número mágico:
fswebcam -d /dev/video0 -p MJPEG -r 640x480 -S 20 teste.jpg
Descartar 20 frames funciona sempre mas parece-me um exagero. Além disso descobri que à medida que se vai utilizando podemos baixar o número, até mesmo deixar de descartar qualquer frame… Parece que a câmara “aquece” ou se vai auto-ajustando, será?
Para facilitar a utilização a partir de outros programas criei um script ‘saycheese.sh’ que ao ser invocado tira uma fotografia e guarda-a com um nome correspondendo à data:
#!/bin/sh filename=$(date +"%d-%m-%y_%Hh%Mm%Ss") fswebcam -d /dev/video0 -p MJPEG -r 640x480 -q -D 1 -S 10 -s brightness=8 -s contrast=10 $filename.jpg
Utilizo alguns outros parâmetros:
- “-D 1” força um atraso de 1 segundo entre a activação da câmara e o íncio da captura
- -s brightness=8 aumenta ligeiramente o brilho
- -s contrast=10 diminui ligeiramente o contraste
Os valores de brightness e contrast, bem como outros aceites pela webcam, podem ser questionados à própria câmara:
root@ev3dev:~# v4l2-ctl --all Driver Info (not using libv4l2): Driver name : uvcvideo Card type : Webcam C170 Bus info : usb-ohci.0-1.3 Driver version: 3.14.7 Capabilities : 0x84000001 Video Capture Streaming Device Capabilities Device Caps : 0x04000001 Video Capture Streaming Priority: 2 Video input : 0 (Camera 1: ok) Format Video Capture: Width/Height : 640/480 Pixel Format : 'MJPG' Field : None Bytes per Line: 0 Size Image : 921600 Colorspace : SRGB Crop Capability Video Capture: Bounds : Left 0, Top 0, Width 640, Height 480 Default : Left 0, Top 0, Width 640, Height 480 Pixel Aspect: 1/1 Streaming Parameters Video Capture: Capabilities : timeperframe Frames per second: 30.000 (30/1) Read buffers : 0 brightness (int) : min=-64 max=64 step=1 default=0 value=0 contrast (int) : min=0 max=30 step=1 default=13 value=13 saturation (int) : min=0 max=127 step=1 default=38 value=38 hue (int) : min=-16000 max=16000 step=1 default=0 value=0 white_balance_temperature_auto (bool) : default=1 value=1 gamma (int) : min=20 max=250 step=1 default=100 value=100 power_line_frequency (menu) : min=0 max=2 default=1 value=1 white_balance_temperature (int) : min=2800 max=6500 step=1 default=5000 value=5000 flags=inactive sharpness (int) : min=0 max=100 step=1 default=35 value=35 backlight_compensation (int) : min=0 max=1 step=1 default=0 value=0 exposure_auto (menu) : min=0 max=3 default=3 value=3 exposure_absolute (int) : min=2 max=5000 step=1 default=312 value=10000 flags=inactive exposure_auto_priority (bool) : default=0 value=1 pan_absolute (int) : min=-72000 max=72000 step=3600 default=0 value=0 tilt_absolute (int) : min=-54000 max=54000 step=3600 default=0 value=0 zoom_absolute (int) : min=1 max=2 step=1 default=1 value=1
(embora nem todos os comandos aceites pela câmara sejam perceptíveis, só experimentando vários valores para ver a diferença)