2011-10-14 23 views
7

Quiero implementar un método de promediado de fondo. Tengo 50 cuadros de imágenes tomadas en un segundo y algunos de los cuadros contienen rayos que quiero extraer como primer plano. Los marcos se toman con una cámara fija y los marcos se toman como escalas de grises. Lo que quiero hacer es:Resta de fondo en OpenCV (C++)

  1. obtener el modelo de fondo
  2. Después, comparar cada marco para el modelo de fondo para determinar si hay iluminación en ese marco o no.

He leído algunos documentos sobre cómo esto se puede hacer usando cvAcc(), pero tengo dificultades para entender cómo se puede hacer esto. Agradecería una pieza de código que me guíe y enlaces a documentos que puedan ayudarme a comprender cómo puedo implementar esto.

Agradeciendo de antemano.

Respuesta

18

Tuvimos la misma tarea en uno de nuestros proyectos.

Para obtener el modelo de fondo, simplemente creamos una clase BackgroundModel, capturamos el primer (digamos) 50 marcos y calculamos el marco promedio para evitar errores de píxeles en el modelo de fondo.

Por ejemplo, si obtiene una imagen en escala de grises de 8 bits (CV_8UC1) de su cámara, inicializa su modelo con CV_16UC1 para evitar el recorte.

cv::Mat model = cv::Mat(HEIGHT, WIDTH, CV_16UC1, cv::Scalar(0)); 

Ahora, a la espera de los primeros marcos para calcular el modelo, basta con añadir cada cuadro con el modelo y contar la cantidad de tramas recibidas.

void addFrame(cv::Mat frame) { 
    cv::Mat convertedFrame; 
    frame.convertTo(convertedFrame, CV_16UC1); 
    cv::add(convertedFrame, model, model); 
    if (++learnedFrames >= FRAMES_TO_LEAN) { // FRAMES_TO_LEARN = 50 
     createMask(); 
    } 
} 

La función createMask() calcula el marco promedio que usamos para el modelo.

void createMask() { 
    cv::convertScaleAbs(model, mask, 1.0/learnedFrames); 
    mask.convertTo(mask, CV_8UC1); 
} 

Ahora, sólo envía todas las tramas del camino a través de la clase BackgroundModel a una función de resta(). Si el resultado es un cv :: Mat vacío, la máscara aún se calcula. De lo contrario, obtienes un marco restado.

cv::Mat subtract(cv::Mat frame) { 
    cv::Mat result; 
    if (++learnedFrames >= FRAMES_TO_LEAN) { // FRAMES_TO_LEARN = 50 
     cv::subtract(frame, mask, result); 
    } 
    else { 
     addFrame(frame); 
    } 
    return result; 
} 

Por último, pero no menos importante, puede utilizar suma escalar (const Mat & MTX) para calcular la suma de píxeles y decidir si se trata de un marco con las luces en él.

+0

Muchas gracias ping (",) – user854576

+3

@ user854576 Si esta es una respuesta correcta, debe ser amable y aceptarla. Consulte [esta página] (http://stackoverflow.com/faq#howtoask) en el Preguntas frecuentes sobre cómo aceptar respuestas. –