自学内容网 自学内容网

C# OpenCvSharp DNN 卡证检测矫正

目录

说明

效果

模型

项目

代码

下载

参考


说明

源码地址:https://modelscope.cn/models/iic/cv_resnet_carddetection_scrfd34gkps

在实人认证、文档电子化等场景中需要自动化提取卡证的信息,以便进一步做录入处理。这类场景通常存在两类问题,一是识别卡证类型时易受背景干扰,二是卡证拍摄角度造成的文字畸变影响OCR准确率。鉴于证件类数据的敏感性,我们采用大量合成卡证数据做训练(参见:SyntheticCards), 并改造人脸检测SOTA方法SCRFD(论文地址, 代码地址)训练了卡证检测矫正模型,可以对各类国际常见卡证(如,身份证、护照、驾照等)进行检测、定位及矫正,得到去除背景的正视角卡证图像,便于后续卡证分类或OCR内容提取。

效果

模型

Model Properties
-------------------------
---------------------------------------------------------------

Inputs
-------------------------
name:input.1
tensor:Float[1, 3, 640, 640]
---------------------------------------------------------------

Outputs
-------------------------
name:1401
tensor:Float[1, 25600, 1]
name:1455
tensor:Float[1, 6400, 1]
name:1507
tensor:Float[1, 1600, 1]
name:1408
tensor:Float[1, 25600, 4]
name:1461
tensor:Float[1, 6400, 4]
name:1513
tensor:Float[1, 1600, 4]
name:1415
tensor:Float[1, 25600, 8]
name:1467
tensor:Float[1, 6400, 8]
name:1519
tensor:Float[1, 1600, 8]
---------------------------------------------------------------

项目

代码

using OpenCvSharp;
using OpenCvSharp.Dnn;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace OpenCvSharp_Demo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
        string startupPath;
        string image_path;

        private void Form1_Load(object sender, EventArgs e)
        {
            startupPath = System.Windows.Forms.Application.StartupPath;

            image_path = "1.jpg";
            pictureBox1.Image = new Bitmap(image_path);
            image = new Mat(image_path);

            opencv_net = CvDnn.ReadNetFromOnnx("carddetection_scrfd34gkps.onnx");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = fileFilter;
            if (ofd.ShowDialog() != DialogResult.OK) return;

            pictureBox1.Image = null;
            pictureBox2.Image = null;
            textBox1.Text = "";

            image_path = ofd.FileName;
            pictureBox1.Image = new Bitmap(image_path);
            image = new Mat(image_path);
        }

        Stopwatch stopwatch = new Stopwatch();
        Net opencv_net;
        Mat BN_image;
        Mat image;
        Mat result_image;

        float[] stride = { 8.0f, 16.0f, 32.0f };
        int inpWidth = 640;
        int inpHeight = 640;
        float confThreshold = 0.5f;
        float nmsThreshold = 0.5f;
        bool keep_ratio = true;

        Mat resize_image(Mat srcimg, ref int newh, ref int neww, ref int top, ref int left)
        {
            int srch = srcimg.Rows, srcw = srcimg.Cols;
            newh = inpHeight;
            neww = inpWidth;
            Mat dstimg = new Mat();
            if (keep_ratio && srch != srcw)
            {
                float hw_scale = (float)srch / srcw;
                if (hw_scale > 1)
                {
                    newh = inpHeight;
                    neww = (int)(inpWidth / hw_scale);
                    Cv2.Resize(srcimg, dstimg, new OpenCvSharp.Size(neww, newh));
                    left = (int)((inpWidth - neww) * 0.5);
                    Cv2.CopyMakeBorder(dstimg, dstimg, 0, 0, left, inpWidth - neww - left, BorderTypes.Constant, 0);
                }
                else
                {
                    newh = (int)(inpHeight * hw_scale);
                    neww = inpWidth;
                    Cv2.Resize(srcimg, dstimg, new OpenCvSharp.Size(neww, newh));
                    top = (int)((inpHeight - newh) * 0.5);
                    Cv2.CopyMakeBorder(dstimg, dstimg, top, inpHeight - newh - top, 0, 0, BorderTypes.Constant, 0);
                }
            }
            else
            {
                Cv2.Resize(srcimg, dstimg, new OpenCvSharp.Size(neww, newh));
            }
            return dstimg;
        }

        unsafe private void button2_Click(object sender, EventArgs e)
        {
            if (image_path == "")
            {
                return;
            }

            stopwatch.Restart();
            image = new Mat(image_path);
            result_image = image.Clone();

            int newh = 0, neww = 0, padh = 0, padw = 0;
            Mat img = resize_image(image, ref newh, ref neww, ref padh, ref padw);
            Mat blob = new Mat();

            BN_image = CvDnn.BlobFromImage(img, 1 / 128.0, new OpenCvSharp.Size(inpWidth, inpHeight), new Scalar(127.5, 127.5, 127.5), true, false);

            opencv_net.SetInput(BN_image);

            Mat[] outs = new Mat[9] { new Mat(), new Mat(), new Mat(), new Mat(), new Mat(), new Mat(), new Mat(), new Mat(), new Mat() };
            string[] outBlobNames = opencv_net.GetUnconnectedOutLayersNames();
            opencv_net.Forward(outs, outBlobNames);

            //generate proposals
            List<float> confidences = new List<float>();
            List<Rect> boxes = new List<Rect>();
            List<List<int>> landmarks = new List<List<int>>();
            float ratioh = (float)image.Rows / newh, ratiow = (float)image.Cols / neww;
            int n = 0, i = 0, j = 0, k = 0, l = 0;
            for (n = 0; n < 3; n++)
            {
                int num_grid_x = (int)(inpWidth / stride[n]);
                int num_grid_y = (int)(inpHeight / stride[n]);
                float* pdata_score = (float*)outs[n * 3].Data;  //score
                float* pdata_bbox = (float*)outs[n * 3 + 1].Data;  //bounding box
                float* pdata_kps = (float*)outs[n * 3 + 2].Data;  //face landmark
                for (i = 0; i < num_grid_y; i++)
                {
                    for (j = 0; j < num_grid_x; j++)
                    {
                        for (k = 0; k < 4; k++)
                        {
                            if (pdata_score[0] > confThreshold)
                            {
                                int xmin = (int)(((j - pdata_bbox[0]) * stride[n] - padw) * ratiow);
                                int ymin = (int)(((i - pdata_bbox[1]) * stride[n] - padh) * ratioh);
                                int width = (int)((pdata_bbox[2] + pdata_bbox[0]) * stride[n] * ratiow);
                                int height = (int)((pdata_bbox[3] + pdata_bbox[1]) * stride[n] * ratioh);
                                confidences.Add(pdata_score[0]);
                                boxes.Add(new Rect(xmin, ymin, width, height));
                                List<int> landmark = new List<int>();
                                for (l = 0; l < 8; l += 2)
                                {
                                    landmark.Add((int)(((j + pdata_kps[l]) * stride[n] - padw) * ratiow));
                                    landmark.Add((int)(((i + pdata_kps[l + 1]) * stride[n] - padh) * ratioh));
                                }
                                landmarks.Add(landmark);
                            }
                            pdata_score++;
                            pdata_bbox += 4;
                            pdata_kps += 8;
                        }
                    }
                }
            }

            //vector<int> indices;
            int[] indices;
            CvDnn.NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, out indices);
            //draw bbox and kps
            for (i = 0; i < indices.Length; ++i)
            {
                int idx = indices[i];
                Rect box = boxes[idx];
                Cv2.Rectangle(result_image, new OpenCvSharp.Point(box.X, box.Y), new OpenCvSharp.Point(box.X + box.Width, box.Y + box.Height), new Scalar(0, 0, 255), 2);
                for (k = 0; k < 8; k += 2)
                {
                    Cv2.Circle(result_image, new OpenCvSharp.Point(landmarks[idx][k], landmarks[idx][k + 1]), 10, new Scalar(0, 255, 0), -1);
                }
                //Get the label for the class name and its confidence
                string label = confidences[idx].ToString("P2");
                //Display the label at the top of the bounding box
                int baseLine;
                OpenCvSharp.Size labelSize = Cv2.GetTextSize(label, HersheyFonts.HersheySimplex, 0.5, 2, out baseLine);
                int top = Math.Max(box.Y, labelSize.Height);
                Cv2.PutText(result_image, label, new OpenCvSharp.Point(box.X, top - 10), HersheyFonts.HersheySimplex, 1, new Scalar(0, 255, 0), 2);
            }

            stopwatch.Stop();
            double costTime = stopwatch.Elapsed.TotalMilliseconds;

            textBox1.Text = $"耗时:{costTime:F2}ms";
            pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (pictureBox2.Image == null)
            {
                return;
            }
            Bitmap output = new Bitmap(pictureBox2.Image);
            var sdf = new SaveFileDialog();
            sdf.Title = "保存";
            sdf.Filter = "Images (*.jpg)|*.jpg|Images (*.png)|*.png|Images (*.bmp)|*.bmp";
            if (sdf.ShowDialog() == DialogResult.OK)
            {
                switch (sdf.FilterIndex)
                {
                    case 1:
                        {
                            output.Save(sdf.FileName, ImageFormat.Jpeg);
                            break;
                        }
                    case 2:
                        {
                            output.Save(sdf.FileName, ImageFormat.Png);
                            break;
                        }
                    case 3:
                        {
                            output.Save(sdf.FileName, ImageFormat.Bmp);
                            break;
                        }
                }
                MessageBox.Show("保存成功,位置:" + sdf.FileName);
            }
        }
    }
}

using OpenCvSharp;
using OpenCvSharp.Dnn;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace OpenCvSharp_Demo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
        string startupPath;
        string image_path;

        private void Form1_Load(object sender, EventArgs e)
        {
            startupPath = System.Windows.Forms.Application.StartupPath;

            image_path = "1.jpg";
            pictureBox1.Image = new Bitmap(image_path);
            image = new Mat(image_path);

            opencv_net = CvDnn.ReadNetFromOnnx("carddetection_scrfd34gkps.onnx");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = fileFilter;
            if (ofd.ShowDialog() != DialogResult.OK) return;

            pictureBox1.Image = null;
            pictureBox2.Image = null;
            textBox1.Text = "";

            image_path = ofd.FileName;
            pictureBox1.Image = new Bitmap(image_path);
            image = new Mat(image_path);
        }

        Stopwatch stopwatch = new Stopwatch();
        Net opencv_net;
        Mat BN_image;
        Mat image;
        Mat result_image;

        float[] stride = { 8.0f, 16.0f, 32.0f };
        int inpWidth = 640;
        int inpHeight = 640;
        float confThreshold = 0.5f;
        float nmsThreshold = 0.5f;
        bool keep_ratio = true;

        Mat resize_image(Mat srcimg, ref int newh, ref int neww, ref int top, ref int left)
        {
            int srch = srcimg.Rows, srcw = srcimg.Cols;
            newh = inpHeight;
            neww = inpWidth;
            Mat dstimg = new Mat();
            if (keep_ratio && srch != srcw)
            {
                float hw_scale = (float)srch / srcw;
                if (hw_scale > 1)
                {
                    newh = inpHeight;
                    neww = (int)(inpWidth / hw_scale);
                    Cv2.Resize(srcimg, dstimg, new OpenCvSharp.Size(neww, newh));
                    left = (int)((inpWidth - neww) * 0.5);
                    Cv2.CopyMakeBorder(dstimg, dstimg, 0, 0, left, inpWidth - neww - left, BorderTypes.Constant, 0);
                }
                else
                {
                    newh = (int)(inpHeight * hw_scale);
                    neww = inpWidth;
                    Cv2.Resize(srcimg, dstimg, new OpenCvSharp.Size(neww, newh));
                    top = (int)((inpHeight - newh) * 0.5);
                    Cv2.CopyMakeBorder(dstimg, dstimg, top, inpHeight - newh - top, 0, 0, BorderTypes.Constant, 0);
                }
            }
            else
            {
                Cv2.Resize(srcimg, dstimg, new OpenCvSharp.Size(neww, newh));
            }
            return dstimg;
        }

        unsafe private void button2_Click(object sender, EventArgs e)
        {
            if (image_path == "")
            {
                return;
            }

            stopwatch.Restart();
            image = new Mat(image_path);
            result_image = image.Clone();

            int newh = 0, neww = 0, padh = 0, padw = 0;
            Mat img = resize_image(image, ref newh, ref neww, ref padh, ref padw);
            Mat blob = new Mat();

            BN_image = CvDnn.BlobFromImage(img, 1 / 128.0, new OpenCvSharp.Size(inpWidth, inpHeight), new Scalar(127.5, 127.5, 127.5), true, false);

            opencv_net.SetInput(BN_image);

            Mat[] outs = new Mat[9] { new Mat(), new Mat(), new Mat(), new Mat(), new Mat(), new Mat(), new Mat(), new Mat(), new Mat() };
            string[] outBlobNames = opencv_net.GetUnconnectedOutLayersNames();
            opencv_net.Forward(outs, outBlobNames);

            //generate proposals
            List<float> confidences = new List<float>();
            List<Rect> boxes = new List<Rect>();
            List<List<int>> landmarks = new List<List<int>>();
            float ratioh = (float)image.Rows / newh, ratiow = (float)image.Cols / neww;
            int n = 0, i = 0, j = 0, k = 0, l = 0;
            for (n = 0; n < 3; n++)
            {
                int num_grid_x = (int)(inpWidth / stride[n]);
                int num_grid_y = (int)(inpHeight / stride[n]);
                float* pdata_score = (float*)outs[n * 3].Data;  //score
                float* pdata_bbox = (float*)outs[n * 3 + 1].Data;  //bounding box
                float* pdata_kps = (float*)outs[n * 3 + 2].Data;  //face landmark
                for (i = 0; i < num_grid_y; i++)
                {
                    for (j = 0; j < num_grid_x; j++)
                    {
                        for (k = 0; k < 4; k++)
                        {
                            if (pdata_score[0] > confThreshold)
                            {
                                int xmin = (int)(((j - pdata_bbox[0]) * stride[n] - padw) * ratiow);
                                int ymin = (int)(((i - pdata_bbox[1]) * stride[n] - padh) * ratioh);
                                int width = (int)((pdata_bbox[2] + pdata_bbox[0]) * stride[n] * ratiow);
                                int height = (int)((pdata_bbox[3] + pdata_bbox[1]) * stride[n] * ratioh);
                                confidences.Add(pdata_score[0]);
                                boxes.Add(new Rect(xmin, ymin, width, height));
                                List<int> landmark = new List<int>();
                                for (l = 0; l < 8; l += 2)
                                {
                                    landmark.Add((int)(((j + pdata_kps[l]) * stride[n] - padw) * ratiow));
                                    landmark.Add((int)(((i + pdata_kps[l + 1]) * stride[n] - padh) * ratioh));
                                }
                                landmarks.Add(landmark);
                            }
                            pdata_score++;
                            pdata_bbox += 4;
                            pdata_kps += 8;
                        }
                    }
                }
            }

            //vector<int> indices;
            int[] indices;
            CvDnn.NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, out indices);
            //draw bbox and kps
            for (i = 0; i < indices.Length; ++i)
            {
                int idx = indices[i];
                Rect box = boxes[idx];
                Cv2.Rectangle(result_image, new OpenCvSharp.Point(box.X, box.Y), new OpenCvSharp.Point(box.X + box.Width, box.Y + box.Height), new Scalar(0, 0, 255), 2);
                for (k = 0; k < 8; k += 2)
                {
                    Cv2.Circle(result_image, new OpenCvSharp.Point(landmarks[idx][k], landmarks[idx][k + 1]), 10, new Scalar(0, 255, 0), -1);
                }
                //Get the label for the class name and its confidence
                string label = confidences[idx].ToString("P2");
                //Display the label at the top of the bounding box
                int baseLine;
                OpenCvSharp.Size labelSize = Cv2.GetTextSize(label, HersheyFonts.HersheySimplex, 0.5, 2, out baseLine);
                int top = Math.Max(box.Y, labelSize.Height);
                Cv2.PutText(result_image, label, new OpenCvSharp.Point(box.X, top - 10), HersheyFonts.HersheySimplex, 1, new Scalar(0, 255, 0), 2);
            }

            stopwatch.Stop();
            double costTime = stopwatch.Elapsed.TotalMilliseconds;

            textBox1.Text = $"耗时:{costTime:F2}ms";
            pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (pictureBox2.Image == null)
            {
                return;
            }
            Bitmap output = new Bitmap(pictureBox2.Image);
            var sdf = new SaveFileDialog();
            sdf.Title = "保存";
            sdf.Filter = "Images (*.jpg)|*.jpg|Images (*.png)|*.png|Images (*.bmp)|*.bmp";
            if (sdf.ShowDialog() == DialogResult.OK)
            {
                switch (sdf.FilterIndex)
                {
                    case 1:
                        {
                            output.Save(sdf.FileName, ImageFormat.Jpeg);
                            break;
                        }
                    case 2:
                        {
                            output.Save(sdf.FileName, ImageFormat.Png);
                            break;
                        }
                    case 3:
                        {
                            output.Save(sdf.FileName, ImageFormat.Bmp);
                            break;
                        }
                }
                MessageBox.Show("保存成功,位置:" + sdf.FileName);
            }
        }
    }
}

下载

源码下载

参考

https://github.com/hpc203/cv_resnet_carddetection_scrfd34gkps-opencv-dnn


原文地址:https://blog.csdn.net/lw112190/article/details/144754559

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!