Corrección de distorsión de código OpenCV~QR

Este es el código de c#, solo mira la idea~~

Mire el efecto (la izquierda es la imagen original y la derecha es el efecto corregido):

【1】Análisis de demanda 

 Debido al ángulo de disparo de la cámara, la forma del código QR no es un rectángulo y hay una distorsión obvia. Queremos corregirlo a un patrón rectangular o cuadrado normal para facilitar la decodificación u otro procesamiento de imágenes.

    Los pasos preliminares de procesamiento son los siguientes:

    ① Encuentra parte del contorno del código QR a través del preprocesamiento;

    ② Encuentre las cuatro esquinas del código QR mediante análisis de contorno;

    ③ Según los cuatro puntos de esquina encontrados, use la transformación de perspectiva para corregir el código QR.

[2] Demostración de los pasos de implementación

    ① Segmente el área del código QR mediante binarización simple, porque el objetivo es negro y el fondo está resaltado, por lo que el parámetro de binarización usa ThresholdTypes.BinaryInv

Mat src = Cv2.ImRead("1.jpg");
Cv2.NamedWindow("src", WindowFlags.GuiExpanded);
Cv2.ImShow("src", src);
Mat gray = new Mat(), thres = new Mat();
Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);
Cv2.Threshold(gray, thres, 80, 255, ThresholdTypes.BinaryInv);
Cv2.NamedWindow("thres", WindowFlags.GuiExpanded);
Cv2.ImShow("thres", thres);

 ② A través de la operación morfológica cerrada, el área de código bidimensional se conecta a una ciudad, para facilitar la búsqueda de contorno posterior

Mat element = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(15, 15), new Point(-1, -1));
Cv2.MorphologyEx(thres, thres, MorphTypes.Close, element, new Point(-1, -1), 1, BorderTypes.Default, new Scalar());
Cv2.NamedWindow("close", WindowFlags.GuiExpanded);
Cv2.ImShow("close", thres);

 ③ Búsqueda y detección de contornos (tenga en cuenta que hay un contorno de interferencia en la esquina inferior izquierda) y filtre por área de contorno

double area = Cv2.ContourArea(contours[i]);
    if (area < 10000)
        continue;

 ④ Contorno (contorno de código bidimensional) que satisface las condiciones, encuentra el casco convexo del contorno y luego realiza una aproximación poligonal en el casco convexo

Point[] hull = Cv2.ConvexHull(contours[i]);

for (int j = 0; j < hull.Length; j++)
{
    if (j != hull.Length - 1)
        Cv2.Line(src, hull[j], hull[j + 1], new Scalar(0, 255, 0), 2);
    else
        Cv2.Line(src, hull[j], hull[0], new Scalar(0, 255, 0), 2);
}

  Aproximación de polígono de casco convexo, el propósito es aproximar los lados del casco convexo a 4, de modo que los puntos de las esquinas del cuadrilátero se puedan obtener directamente

Point[] approx = Cv2.ApproxPolyDP(hull, 20, true);
for (int j = 0; j < approx.Length; j++)
{
    Console.WriteLine("{0}", approx[j]);
    if (j != approx.Length - 1)
        Cv2.Line(src, approx[j], approx[j + 1], new Scalar(0, 0, 255), 2);
    else
        Cv2.Line(src, approx[j], approx[0], new Scalar(0, 0, 255), 2);
    srcPoints[j] = approx[j];
}

  ⑤ Transformación de perspectiva

    4 puntos originales, obtenidos directamente del resultado de la aproximación poligonal

Point2f[] srcPoints = new Point2f[4];

Point[] approx = Cv2.ApproxPolyDP(hull, 20, true);
for (int j = 0; j < approx.Length; j++)
{
    Console.WriteLine("{0}", approx[j]);
    if (j != approx.Length - 1)
        Cv2.Line(src, approx[j], approx[j + 1], new Scalar(0, 0, 255), 2);
    else
        Cv2.Line(src, approx[j], approx[0], new Scalar(0, 0, 255), 2);
    srcPoints[j] = approx[j];
}

    4 puntos objetivo, autoconstruidos, qrWidth puede configurarse usted mismo o calcularse mediante métodos matemáticos

Point2f[] dstPoints = new Point2f[4];
int qrWidth = 450;
dstPoints[0] = new Point2f(0, 0);
dstPoints[1] = new Point2f(qrWidth, 0);
dstPoints[2] = new Point2f(qrWidth, qrWidth);
dstPoints[3] = new Point2f(0, qrWidth);

    Lo siguiente es la transformación de la perspectiva.

Mat result = new Mat();
try
{
    Mat TransformMatrix = Cv2.GetPerspectiveTransform(srcPoints, dstPoints);      //根据变换前后四个角点坐标,计算变换矩阵
    Cv2.WarpPerspective(src, result, TransformMatrix, new Size(qrWidth, qrWidth));   //透视变换函数
}
catch (Exception e)
{
    Console.WriteLine(e);
}

//Cv2.NamedWindow("result", WindowFlags.GuiExpanded);
Cv2.ImShow("result", src);
Cv2.WaitKey();

   Luego obtenga el resultado final de la siguiente manera: whaosoft  aiot  http://143ai.com

 ​​​​​​

 

Supongo que te gusta

Origin blog.csdn.net/qq_29788741/article/details/131954093
Recomendado
Clasificación