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