es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

No puede detectarse el rectángulo del documento de identidad.

Quiero detectar el rectángulo delimitador de una tarjeta de identificación alemana dentro de una imagen utilizando OpenCV.

Este es cómo se ve mi código:

    capture >> frame;

    cv::resize(frame, frame, cv::Size(512,256));
    cv::Mat grayScaledFrame, blurredFrame, cannyFrame;
    cv::cvtColor(frame, grayScaledFrame, cv::COLOR_BGR2GRAY);
    cv::GaussianBlur(grayScaledFrame, blurredFrame, cv::Size(9,9), 1);

    cv::Canny(blurredFrame, cannyFrame, 40, 70);

    // CONTORNOS
    std::vector<><cv::point>> contours;
    cv::findContours(cannyFrame, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

    // ORDENAR
    int maxArea = 0;
    std::vector<cv::point> contour;

    for(int i = 0; i < contours.size(); i++) {
        int thisArea = cv::contourArea(contours.at(i));
        if(thisArea > maxArea) {
            maxArea = thisArea;
            contour = contours.at(i);
        }
    }
    cv::Rect borderBox = cv::boundingRect(contour);

    cv::rectangle(cannyFrame, borderBox, cv::Scalar{255, 32, 32}, 8);
    cv::imshow("Webcam", cannyFrame);

El resultado se ve así:
RESULTADO

Hay algunos rectángulos detectados pero no el grande en el que estoy interesado.
Ya he probado diferentes umbrales para Canny y diferentes tamaños de kernel para Gaussian Blur.

Saludos cordiales.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para mejorar la detección del rectángulo delimitador de la tarjeta de identificación alemana, puedes intentar los siguientes pasos:

    1. Preprocesa la imagen convirtiéndola a escala de grises y aplicando umbralización adaptativa para mejorar los bordes.
    2. Utiliza la transformada de Hough para detectar las líneas en la imagen.

    3. Filtra las líneas que no son relevantes para la tarjeta de identificación y combina las líneas restantes para formar las esquinas del rectángulo delimitador.

    4. Aplica la transformación de perspectiva a la imagen para enderezarla y obtener una tarjeta de identificación correctamente alineada.

    Aquí tienes un ejemplo de código que implementa estos pasos:

    cv::Mat frame;
    captura >> frame;
    
    cv::resize(frame, frame, cv::Size(512, 256));
    
    // Convierte la imagen a escala de grises y aplica umbralización adaptativa
    cv::Mat gray;
    cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
    cv::adaptiveThreshold(gray, gray, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY_INV, 15, 10);
    
    // Detecta las líneas utilizando transformada de Hough
    std::vector<cv::vec4i> lines;
    cv::HoughLinesP(gray, lines, 1, CV_PI / 180, 50, 50, 10);
    
    // Filtra las líneas no horizontales y no verticales
    std::vector<cv::vec4i> horizLines, vertLines;
    for (auto line : lines) {
        double angle = std::atan2(line[3] - line[1], line[2] - line[0]) * 180 / CV_PI;
        if (std::abs(angle) < 20 || std::abs(angle - 90) < 20) {
            if (std::abs(angle) < 20) horizLines.push_back(line);
            else vertLines.push_back(line);
        }
    }
    
    // Encuentra las intersecciones de las líneas horizontales y verticales
    std::vector<cv::point2f> corners;
    for (auto hline : horizLines) {
        for (auto vline : vertLines) {
            cv::Point2f pt;
            pt.x = (hline[0] * vline[1] - hline[1] * vline[0]) / (vline[1] - hline[1]);
            pt.y = (hline[3] * vline[2] - hline[2] * vline[3]) / (vline[2] - hline[2]);
            corners.push_back(pt);
        }
    }
    
    // Asegúrate de tener exactamente 4 esquinas
    if (corners.size() == 4) {
        // Ordena las esquinas en sentido horario
        std::sort(corners.begin(), corners.end(), [](cv::Point2f a, cv::Point2f b) {
            return a.x < b.x;
        });
        std::vector<cv::point2f> top, bot;
        top.push_back(corners[0]);
        top.push_back(corners[1]);
        bot.push_back(corners[2]);
        bot.push_back(corners[3]);
        if (top[0].y > top[1].y) std::swap(top[0], top[1]);
        if (bot[0].y > bot[1].y) std::swap(bot[0], bot[1]);
        corners.clear();
        corners.push_back(top[0]);
        corners.push_back(top[1]);
        corners.push_back(bot[1]);
        corners.push_back(bot[0]);
    
        // Aplica transformación de perspectiva para obtener una imagen enderezada
        cv::Mat transform = cv::getPerspectiveTransform(corners, cv::Size(400, 300));
        cv::Mat result;
        cv::warpPerspective(frame, result, transform, cv::Size(400, 300));
    
        // Muestra el resultado
        cv::imshow("Resultado", result);
    }
    

    Este código primero convierte la imagen a escala de grises y aplica umbralización adaptativa para mejorar los bordes. Luego utiliza la transformada de Hough para detectar las líneas en la imagen, filtra las líneas no horizontales y no verticales, y encuentra las intersecciones de las líneas horizontales y verticales para obtener las esquinas de la tarjeta de identificación.

    Luego ordena las esquinas en sentido horario y aplica una transformación de perspectiva para obtener una tarjeta de identificación correctamente alineada. El resultado se muestra en una nueva ventana llamada “Resultado”.

    Ten en cuenta que el código asume que la tarjeta de identificación está orientada aproximadamente en posición horizontal o vertical. Si la tarjeta de identificación está inclinada, es posible que necesites implementar pasos adicionales para detectar el ángulo de la tarjeta y girarla adecuadamente antes de aplicar la transformación de perspectiva.

Comments are closed.