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)