C# OpenCvSharp DNN 卡证检测矫正

B站影视 2024-12-28 09:13 1

摘要:Mat resize_image(Mat srcimg, ref int newh, ref int neww, ref int top, ref int left)

源码地址: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
{
publicForm1
{
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 = ;
pictureBox2.Image = ;
textBox1.Text ="";

image_path = ofd.FileName;

}

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;
floatconfThreshold = 0.5f;
floatnmsThreshold = 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)
{
floathw_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;

top = (int)((inpHeight - newh) * 0.5);
Cv2.CopyMakeBorder(dstimg, dstimg, top, inpHeight - newh - top, 0, 0, BorderTypes.Constant, 0);
}
}
else
{

}
returndstimg;
}

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

stopwatch.Restart;

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),truefalse);

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
Listfloat> confidences = new Listfloat>;
List boxes = new List;
List> landmarks = new List>;
floatratioh = (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 landmark = new List;
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;
}
}
}
}
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 labelforthe 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 == )
{
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)
{
case1:
{
output.Save(sdf.FileName, ImageFormat.Jpeg);
break;
}
case2:
{
output.Save(sdf.FileName, ImageFormat.Png);
break;
}
case3:
{
output.Save(sdf.FileName, ImageFormat.Bmp);
break;
}
}
MessageBox.Show("保存成功,位置:"+ sdf.FileName);
}
}
}
}

来源:opendotnet

相关推荐