Red de conocimiento informático - Material del sitio web - Cómo usar QTcreator para llamar a la cámara local en Linux

Cómo usar QTcreator para llamar a la cámara local en Linux

/*Abre el dispositivo y realiza la comprobación de errores*/

int fd = open ("/dev/video",O_RDONLY);

if (fd = =-1){

error ("No se puede abrir el dispositivo");

return -1;

}

/ * Consultar el formato de salida del dispositivo*/

struct v4l2_format format;

memset (&format,0,sizoef(format));

format. type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;

if (-1==ioctl(fd,VIDIOC_G_FMT,&format)){

error ("Mientras obtengo el formato");

return -2 ;

}

/*

* Aquí debe establecer la estructura struct v4l2_format en cero y luego configurar

* format.type Configúrelo en V4L2_BUF_TYPE_VIDEO_CAPTURE,

* De esta forma al realizar el ioctl de VIDIOC_G_FMT, el controlador sabrá

* que el contenido del formato se obtiene mientras captura de vídeo.

* Después de una devolución exitosa, el formato contendrá el tamaño del video capturado.

* Formato. El formato se almacena en format.fmt.pix.pixelformat, un entero sin signo de 32

* bits, *** cuatro bytes, almacenado en orden little-endian. Aquí

* presenta un método para obtenerlo.

*/

código de carácter[5];

unsigned int i;

for (i=0;i<4; i++) {

código[i] = (format.fmt.pix.pixelformat & (0xff<>i*8;

}

code[4]=0;

/* El código actual es una cadena que termina en \0. Muchas cámaras emiten vídeo en formato MJPG.

* MJPG es la abreviatura de Motion JPEG, que en realidad son algunas imágenes JPEG que no completan la tabla de Huffman.

*/

/* Solicita un número determinado de buffers.

*Pero es posible que no puedas solicitar tantas.

El cuerpo de los datos depende de la cantidad devuelta

*/

struct v4l2_requestbuffers req;

memset (&req,0,sizeof(req));

req.count = 10;

req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

req.memory = V4L2_MEMORY_MMAP;

if (-1==ioctl (fd,VIDIOC_REQBUFS,&req)){

error ("Mientras se solicitan buffers");

return -3;

}

if (req.count < 5){

fprintf (stderr, "¡No puedo obtener suficientes buffers!\n");

return -4;

}

/* Aquí, se solicitan 10 áreas de caché y su tipo se establece en MMAP.

*/

/* Obtener información del buffer

* Antes de la operación, debemos poder registrar el área del buffer que

* * solicitamos y finalmente usar munmap para liberarlos

* Utilice la estructura aquí

* struct buffer {

* void * start

* ssize_t length ;

* } y el número de buffers

* static int nbuffer

* para representar

*/

estructura buffer * buffers = (struct buffer *)malloc (nbuffer*sizeof(*buffers));

if (!buffers){

perror ("No se puede asignar memoria para los buffers) !");

return -4;

}

struct v4l2_buffer buf;

for (nbuffer=0;nbuffer< req .count;++nbuffer) {

memset (&buf,0,sizeof(buf));

buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

memoria buf. = V4L2_MEMORY_MMAP;

buf.index = nbuffer;

if (-1==ioctl(fd,VIDIOC_QUERYBUF,&buf)){

error (" Mientras buffer de consulta");

return -5;

}

buffers[nbuffer].length = buf.length;

buffers [nbuffer].start = mmap (

NULL,

buf.length,

PROT_READ, /* El documento oficial dice que se debe agregar PROT_WRITE, pero agregar An se producirá un error*/

MAP_SHARED,

fd,

buf.m.offset

);

if (MAP_FAILED == buffers[nbuffer].start) {

perror ("Mientras se asigna la memoria");

return -6;

}

}

/*Después de completar este ciclo, todas las áreas de búfer se guardan en

*En la matriz de búferes, simplemente vuelva a mapearlas.

*/

/* Activar captura de vídeo*/

enum v4l2_buf_type type;

type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

if (-1==ioctl(fd,VIDIOC_STREAMON,&type)){

error ("Al abrir la transmisión");

return -7;

}

/* Búfer de intercambio con kernel*/

unsigned int i;

i=0;

while( 1) {

memset (&buf,0,sizeof(buf));

buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

buf.memory = V4L2_MEMORY_MMAP; p>

buf.index = i;

if (-1==ioctl(fd,VIDIOC_DQBUF,&buf)){

perror ("Mientras se obtienen los datos del buffer ") ;

return -8;

}

/* Ahora tenemos un buffer de datos y los enviamos para su procesamiento*/

process_image ( buffers+buf.index,buf.index );

/* Devuelve el buffer al kernel*/

if (-1==ioctl(fd,VIDIOC_QBUF ,&buf )){

perror ("Al devolver los datos del buffer");

return -9;

}

i = (i +1) & nbuffer;

}

Este es todo el proceso de adquisición. En cuanto al procesamiento de imágenes, lo manejan la función de decodificación y Qt. Ahora comencemos con algunas ideas de diseño. Imagine que al convertir una imagen, se le debe proporcionar un área de memoria. Por supuesto, podemos usar malloc para asignarla dinámicamente durante la conversión. Una vez completada y mostrada la conversión, se puede liberar. Sin embargo, hacerlo supone una carga considerable para el núcleo: cada vez que se asigna memoria a una imagen completa, se asignan al menos cientos de KB. Una cantidad tan grande de asignación y liberación puede provocar fácilmente la fragmentación de la memoria y aumentar la carga sobre el núcleo. Dado que la imagen solo se muestra una vez por conversión, el área de memoria utilizada para la conversión se puede reutilizar de forma segura y no será operada por dos subprocesos al mismo tiempo. Por lo tanto, durante la inicialización, asignamos un área de memoria para cada búfer de mapa de memoria para la conversión. Para la conversión de MJPEG a JPEG, se utiliza el mismo tamaño de memoria. El código no aparece aquí.

Esto supone que el puntero inicial de esta área de memoria es conversion_buffers. En Process_image (struct buffer * buf, int index), hay

void Process_image (struct buffer *buf, int index){

.

struct * buffer conv_buf = conversion_buffers+index;

do_image_conversion (

buf->start, buf->length, /* área a convertir*/

conv_buf->start, conv_buf->length, /* área para guardar los datos convertidos*/

);

/* Los datos ahora se pueden extraer y entregar a Procesamiento QPixmap

* Para dibujar en un QWidget, debe sobrecargar la función paintEvent

* y usar QPainter para dibujar. Sin embargo, paintEvent

* es llamado por la capa controlada por eventos, no podemos hacerlo manualmente,

* por lo que necesitamos guardar un valor global en nuestra propia clase sobrecargada

*QPixmap.

Establezca aquí en QPixmap * m_pixmap

*/

m_pixmap -> loadFromData (conv_buf->start,conv_buf->length);

/* Organice una vez inmediatamente Repintar evento*/

repintar ();

}

/* Ejemplo de paintEvent sobrecargado*/

MyWidget:: paintEvent (QPaintEvent * evt) {

QPainter pintor(este);

pintor.drawPixmap (QPoint(0,0),*m_pixmap);

QWidget ::paintEvent (evt);

}

V4L está completo + QT muestra el vídeo de la cámara + QT muestra animación GIF 2009-11-02 09:32 Oye, qt finalmente se completó hace dos semanas Mostrar colección de videos de la cámara. Ahora resumamos el código importante final. QImage img; unsigned char *bit= v4l _dev.buffer; / /v41_dev.buffer es la dirección asignada en memoria QRgb *point; (img.create(MAX_WIDTH, MAX_HEIGHT,32, 0, QImage::IgnoreEndian)) { for(y=0; ysetMovie(movie); gif_lable->show();

Oye, dos semanas finalmente terminé la colección de videos de la cámara de visualización en Qt, ahora resumamos el código importante final

QImage img;

unsigned char *bit= v4l _dev.buffer // v41_dev.buffer es; la dirección asignada en memoria

QRgb *point;

int r, g, b;

QPainter paint;

if(img. create(MAX_WIDTH, MAX_HEIGHT,32, 0, QImage::IgnoreEndian))

{

for(y=0; y

{

for(x=0; x

{

r=(int)bit[i+2] ;

g=(int)bit[i+1];

b=(int)bit[i];

punto= (QRgb *) (img). scanLine(y)+ x;

*point = qRgb(r,g,b); //La función qRgb puede convertir datos en valores RGB de tres píxeles

i+=3 ;

}

}

}

Pero no lo entiendo muy bien. Espero que alguien pueda escribir esto directamente. APLICACIÓN GUI QT PR

OJECT Entonces me referiré a ello. . . Porque realmente no sé mucho sobre la biblioteca de clases de QT, jaja