• 如何调用百度驾驶证离线SDK实现驾驶证自动识别功能
  • 发布于 1个月前
  • 59 热度
    0 评论
先看正页、副页识别效果。
效果


说明
SDK说明

SDK 支持在微软的 VS2015 上编译及运行,不保证在 VS 其他版本上正确运行,建议采用 VS2015 community 或 professional 版本。

代码
调用代码
using Newtonsoft.Json;
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using 驾驶证测试.Commom;

namespace 驾驶证测试
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
        string image_path = "";
        bool isDraw = false;

        private void Form1_Load(object sender, EventArgs e)
        {
            image_path = Application.StartupPath + "\\front_images\\1.png";
            pictureBox1.Image = new Bitmap(image_path);
        }

        private void button4_Click(object sender, EventArgs e)
        {
            image_path = Application.StartupPath + "\\front_images\\1.png";

            Mat image = new Mat(image_path);

            pictureBox1.Image = new Bitmap(image_path);
        }

        private void button5_Click(object sender, EventArgs e)
        {
            image_path = Application.StartupPath + "\\back_images\\1.png";
            pictureBox1.Image = new Bitmap(image_path);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = fileFilter;
            if (ofd.ShowDialog() != DialogResult.OK) return;
            pictureBox1.Image = null;
            image_path = ofd.FileName;
            pictureBox1.Image = new Bitmap(image_path);
            textBox1.Text = "";
        }

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

            textBox1.Text = "";
            Application.DoEvents();

            string ocr_result1 = "";
            string ocr_result2 = "";
            Mat image = new Mat(image_path);
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            int res = DL_OCR_Helper.dl_front_ocr2(image, out ocr_result1, out ocr_result2);
            stopwatch.Stop();
            double totalTime = stopwatch.Elapsed.TotalSeconds;
            textBox1.Text += $"耗时: {totalTime:F2}s";
            textBox1.Text += "\r\n-------------------\r\n";

            if (res == 0)
            {
                Object jsonObject = JsonConvert.DeserializeObject(ocr_result1.ToString());
                textBox1.Text += JsonConvert.SerializeObject(jsonObject, Newtonsoft.Json.Formatting.Indented);

                textBox1.Text += "\r\n-------------------\r\n";

                Object jsonObject2 = JsonConvert.DeserializeObject(ocr_result2.ToString());
                textBox1.Text += JsonConvert.SerializeObject(jsonObject2, Newtonsoft.Json.Formatting.Indented);

                List<OcrRes2> lt = JsonConvert.DeserializeObject<List<OcrRes2>>(ocr_result2.ToString());

                foreach (OcrRes2 item in lt)
                {
                    string[] pts = item.coordinator.Split(' ');

                    //多边形的顶点
                    OpenCvSharp.Point[] points = new OpenCvSharp.Point[]
                    {
                        new OpenCvSharp.Point(Convert.ToDouble( pts[0]), Convert.ToDouble( pts[1])),
                        new OpenCvSharp.Point(Convert.ToDouble( pts[2]), Convert.ToDouble( pts[3])),
                        new OpenCvSharp.Point(Convert.ToDouble( pts[4]), Convert.ToDouble( pts[5])),
                        new OpenCvSharp.Point(Convert.ToDouble( pts[6]), Convert.ToDouble( pts[7])),
                    };

                    // 绘制多边形
                    if (isDraw)
                    {
                        Cv2.Polylines(image, new OpenCvSharp.Point[][] { points }, isClosed: true, color: new Scalar(0, 255, 0), thickness: 3);

                    }
                }
                if (pictureBox1.Image != null)
                {
                    pictureBox1.Image.Dispose();
                    pictureBox1.Image = null;
                }

                pictureBox1.Image = new Bitmap(image.ToMemoryStream());
                image.Dispose();
            }
            else
            {
                textBox1.Text = "识别失败";
            }

        }

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

            textBox1.Text = "";
            Mat image = new Mat(image_path);
            Application.DoEvents();
            string ocr_result1 = "";
            string ocr_result2 = "";
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            int res = DL_OCR_Helper.dl_back_ocr2(image, out ocr_result1, out ocr_result2);
            stopwatch.Stop();
            double totalTime = stopwatch.Elapsed.TotalSeconds;
            textBox1.Text += $"耗时: {totalTime:F2}s";
            textBox1.Text += "\r\n-------------------\r\n";
            if (res == 0)
            {
                Object jsonObject = JsonConvert.DeserializeObject(ocr_result1.ToString());
                textBox1.Text += JsonConvert.SerializeObject(jsonObject, Newtonsoft.Json.Formatting.Indented);

                textBox1.Text += "\r\n-------------------\r\n";

                Object jsonObject2 = JsonConvert.DeserializeObject(ocr_result2.ToString());
                textBox1.Text += JsonConvert.SerializeObject(jsonObject2, Newtonsoft.Json.Formatting.Indented);

                List<OcrRes2> lt = JsonConvert.DeserializeObject<List<OcrRes2>>(ocr_result2.ToString());

                foreach (OcrRes2 item in lt)
                {

                    string[] pts = item.coordinator.Split(' ');

                    //多边形的顶点
                    OpenCvSharp.Point[] points = new OpenCvSharp.Point[]
                    {
                        new OpenCvSharp.Point(Convert.ToDouble( pts[0]), Convert.ToDouble( pts[1])),
                        new OpenCvSharp.Point(Convert.ToDouble( pts[2]), Convert.ToDouble( pts[3])),
                        new OpenCvSharp.Point(Convert.ToDouble( pts[4]), Convert.ToDouble( pts[5])),
                        new OpenCvSharp.Point(Convert.ToDouble( pts[6]), Convert.ToDouble( pts[7])),
                    };

                    // 绘制多边形
                    if (isDraw)
                    {
                        Cv2.Polylines(image, new OpenCvSharp.Point[][] { points }, isClosed: true, color: new Scalar(0, 255, 0), thickness: 3);
                    }
                }
                if (pictureBox1.Image != null)
                {
                    pictureBox1.Image.Dispose();
                    pictureBox1.Image = null;
                }
                pictureBox1.Image = new Bitmap(image.ToMemoryStream());
                image.Dispose();
            }
            else
            {
                textBox1.Text = "识别失败";
            }
        }

        private void button6_Click(object sender, EventArgs e)
        {
            DL_OCR_Helper.InitStatus();

            //授权校验 初始化引擎
            string key = "";
            string licenseKeyPath = Application.StartupPath + "\\license\\license.key";
            string licenseFile = Application.StartupPath + "\\license\\license.ini";
            int res = -1;
            string ini_path = "";

            key = File.ReadAllText(licenseKeyPath);

            res = DL_OCR_Helper.dl_front_init_license(key, licenseFile, false);
            if (res != 0)
            {
                MessageBox.Show(DL_OCR_Helper.GetMsg(res));
                return;
            }

            res = DL_OCR_Helper.dl_front_create();
            if (res != 0)
            {
                MessageBox.Show("驾驶证正页创建引擎失败!");
                return;
            }

            ini_path = Application.StartupPath + "\\front_resource";
            res = DL_OCR_Helper.dl_front_init(ini_path);
            if (res != 0)
            {
                MessageBox.Show(DL_OCR_Helper.GetMsg(res));
                return;
            }

            res = DL_OCR_Helper.dl_back_init_license(key, licenseFile, false);
            if (res != 0)
            {
                MessageBox.Show(DL_OCR_Helper.GetMsg(res));
                return;
            }

            res = DL_OCR_Helper.dl_back_create();
            if (res != 0)
            {
                MessageBox.Show("驾驶证副页创建引擎失败!");
                return;
            }

            ini_path = Application.StartupPath + "\\back_resource";
            res = DL_OCR_Helper.dl_back_init(ini_path);
            if (res != 0)
            {
                MessageBox.Show(DL_OCR_Helper.GetMsg(res));
                return;
            }
            MessageBox.Show("初始化成功!");
            button1.Enabled = true;
            button3.Enabled = true;
        }
    }
}
Native.cs
public class Native
{
    const string DllName = "JiashizhengSharp.dll";

    //正页

    [DllImport(DllName, EntryPoint = "dl_front_init_license", CallingConvention = CallingConvention.Cdecl)]
    public extern static int dl_front_init_license(string key, string licenseFile, bool is_remote);

    [DllImport(DllName, EntryPoint = "dl_front_create", CallingConvention = CallingConvention.Cdecl)]
    public extern static IntPtr dl_front_create();

    [DllImport(DllName, EntryPoint = "dl_front_init", CallingConvention = CallingConvention.Cdecl)]
    public extern static int dl_front_init(IntPtr engine, string ini_path);

    [DllImport(DllName, EntryPoint = "dl_front_ocr", CallingConvention = CallingConvention.Cdecl)]
    public extern static int dl_front_ocr(IntPtr engine, string image_path, StringBuilder ocr_result1, StringBuilder ocr_result2);

    [DllImport(DllName, EntryPoint = "dl_front_ocr2", CallingConvention = CallingConvention.Cdecl)]
    public extern static int dl_front_ocr2(IntPtr engine, IntPtr image, StringBuilder ocr_result1, StringBuilder ocr_result2);

    [DllImport(DllName, EntryPoint = "dl_front_destroy", CallingConvention = CallingConvention.Cdecl)]
    public extern static void dl_front_destroy(IntPtr engine);


    //副页

    [DllImport(DllName, EntryPoint = "dl_back_init_license", CallingConvention = CallingConvention.StdCall)]
    public extern static int dl_back_init_license(string key, string licenseFile, bool is_remote);

    [DllImport(DllName, EntryPoint = "dl_back_create", CallingConvention = CallingConvention.StdCall)]
    public extern static IntPtr dl_back_create();

    [DllImport(DllName, EntryPoint = "dl_back_init", CallingConvention = CallingConvention.StdCall)]
    public extern static int dl_back_init(IntPtr engine, string ini_path);

    [DllImport(DllName, EntryPoint = "dl_back_ocr", CallingConvention = CallingConvention.StdCall)]
    public extern static int dl_back_ocr(IntPtr engine, string image_path, StringBuilder ocr_result1, StringBuilder ocr_result2);

    [DllImport(DllName, EntryPoint = "dl_back_ocr2", CallingConvention = CallingConvention.StdCall)]
    public extern static int dl_back_ocr2(IntPtr engine, IntPtr image, StringBuilder ocr_result1, StringBuilder ocr_result2);

    [DllImport(DllName, EntryPoint = "dl_back_destroy", CallingConvention = CallingConvention.StdCall)]
    public extern static void dl_back_destroy(IntPtr engine);

}
C++封装代码
头文件
#include "targetver.h"

#define WIN32_LEAN_AND_MEAN             // 从 Windows 头中排除极少使用的资料
// Windows 头文件: 
#include <windows.h>
#include <windows.h>
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

//-----正页
// 初始化正页SDK授权
extern "C" _declspec(dllexport) int __stdcall dl_front_init_license(char* key, char* licenseFile, bool is_remote);

// 创建正页SDK实例
extern "C" _declspec(dllexport) void* __stdcall dl_front_create();

//正页SDK实例初始化
extern "C" _declspec(dllexport) int __stdcall dl_front_init(void* engine, char* ini_path);

//正页SDK识别
extern "C" _declspec(dllexport) int __stdcall dl_front_ocr(void* engine, char* image_path, char* ocr_result1, char* ocr_result2);

//正页SDK识别2
extern "C" _declspec(dllexport) int __stdcall dl_front_ocr2(void* engine, Mat* image, char* ocr_result1, char* ocr_result2);

//正页SDK释放
extern "C" _declspec(dllexport) void __stdcall dl_front_destroy(void* engine);

//-----副页
// 初始化副页SDK授权
extern "C" _declspec(dllexport) int __stdcall dl_back_init_license(char* key, char* licenseFile, bool is_remote);

// 创建副页SDK实例
extern "C" _declspec(dllexport) void* __stdcall dl_back_create();

//副页SDK实例初始化
extern "C" _declspec(dllexport) int __stdcall dl_back_init(void* engine, char* ini_path);

//副页SDK识别
extern "C" _declspec(dllexport) int __stdcall dl_back_ocr(void* engine, char* image_path, char* ocr_result1, char* ocr_result2);

//副页SDK识别2
extern "C" _declspec(dllexport) int __stdcall dl_back_ocr2(void* engine, Mat* image, char* ocr_result1, char* ocr_result2);

//副页SDK释放
extern "C" _declspec(dllexport) void __stdcall dl_back_destroy(void* engine);

源文件

// stdafx.cpp : 只包括标准包含文件的源文件
// JiashizhengSharp.pch 将作为预编译头
// stdafx.obj 将包含预编译类型信息
#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"

// TODO: 在 STDAFX.H 中引用任何所需的附加头文件,
//而不是在此文件中引用
#include <memory>
#include "front_iocrgve_engine.h"
#include "back_iocrgve_engine.h"
#include "response.h"
#include "DLL_API.h"
#include <fstream>
#include <iostream>

using namespace vis_ocrgve;
using namespace cv;

// 初始化正页SDK授权
int __stdcall dl_front_init_license(char* key, char* licenseFile, bool is_remote)
{
 IOcrgveEngineFront::set_log(OFF_LOG, "", false);
 std::cout << "front_init_license key:" << key << std::endl;
 std::cout << "front_init_license licenseFile:" << licenseFile << std::endl;
 return (int)IOcrgveEngineFront::init_license(key, licenseFile, is_remote);
}

// 创建正页SDK实例
void* __stdcall dl_front_create() {

 IOcrgveEngineFront* engine = IOcrgveEngineFront::create();
 return engine;
}

//实例初始化
int __stdcall dl_front_init(void* engine, char* ini_path) {

 IOcrgveEngineFront* _engine = (IOcrgveEngineFront*)engine;
 return (int)_engine->init(ini_path);
}

//识别
int __stdcall dl_front_ocr(void* engine, char* image_path, char* ocr_result1, char* ocr_result2) {
 int res = 0;
 IOcrgveEngineFront* _engine = (IOcrgveEngineFront*)engine;
 std::cout << "image_path:" << image_path << std::endl;
 Mat input_mat;

 try {
  input_mat = imread(image_path, IMREAD_COLOR);
 }
 catch (...) {
  std::cout << "imread error" << std::endl;
  return -1;
 }

 return dl_front_ocr2(_engine, &input_mat, ocr_result1, ocr_result2);
}


int __stdcall dl_front_ocr2(void* engine, Mat* image, char* ocr_result1, char* ocr_result2)
{
 int res = 0;
 IOcrgveEngineFront* _engine = (IOcrgveEngineFront*)engine;

 ImageFrame input_frame;
 input_frame._width = (*image).cols;
 input_frame._height = (*image).rows;
 input_frame._data = (uint8_t*)(*image).data;
 input_frame._fmt = IMAGE_PIX_FMT_BGR;

 std::vector<vis_ocrgve::ImageFrame> frames;
 frames.push_back(input_frame);
 std::vector<general_vertical_kv_ret> ocrgvesdk_response;

 clock_t start, finish;
 double  duration;
 start = clock();
 res = _engine->process_ocrgvesdkfront(frames, IMAGE_ORIENTATION_UP, ocrgvesdk_response);
 finish = clock();
 duration = (double)(finish - start) / CLOCKS_PER_SEC;
 printf("img_process time: %2.1f ms\r\n", duration * 1000);
 if (res != SUCCESS) {
  return res;
 }

 std::string res_str("");
 std::string res_str2("");

 auto final_result = ocrgvesdk_response[0];
 int direction = 0;

 for (auto it : final_result.kv_content)
 {
  res_str += "\"" + it.first + "\":";

  res_str += "\"" + it.second[0].get_str() + "\"";
  res_str += ",";

  std::string str = ("{\"value\":\"") + it.second[0].get_str() + ("\",") +
   "\"coordinator\":\"" + std::to_string(it.second[0].get_coord()[0]) + (" ") +
   std::to_string(it.second[0].get_coord()[1]) + (" ") +
   std::to_string(it.second[0].get_coord()[2]) + (" ") +
   std::to_string(it.second[0].get_coord()[3]) + (" ") +
   std::to_string(it.second[0].get_coord()[4]) + (" ") +
   std::to_string(it.second[0].get_coord()[5]) + (" ") +
   std::to_string(it.second[0].get_coord()[6]) + (" ") +
   std::to_string(it.second[0].get_coord()[7]) + ("\"") +
   +",\"score\":\"" + std::to_string(it.second[0].get_det_score()) + "\"}";

  res_str2 = res_str2 + str.c_str();
  res_str2 += ",";

 }
 std::string res_header =
  "\"logid\":\"\",\"err_no\":0,\"err_msg\":\"SUCCESS\",\"querysign\":\"4188554259,1723708640\",\"image_dir\":\"" + std::to_string(direction) + "\",\"ret\":{";

 if (res_str.empty()) {
  return -1;
 }

 res_str.pop_back();
 res_str = "{" + res_header + res_str + "}}";

 const char *cstr = res_str.c_str();
 strcpy(ocr_result1, cstr);

 res_str2.erase(res_str2.length() - 1);
 res_str2 = "[" + res_str2 + "]";
 const char *cstr2 = res_str2.c_str();
 strcpy(ocr_result2, cstr2);

 return res;
}

//释放
void __stdcall dl_front_destroy(void* engine) {
 IOcrgveEngineFront* _engine = (IOcrgveEngineFront*)engine;
 _engine->uninit();
 IOcrgveEngineFront::destroy(&_engine);
}


//------------副页
// 初始化副业SDK授权
int __stdcall dl_back_init_license(char* key, char* licenseFile, bool is_remote) {
 IOcrgveEngineBack::set_log(OFF_LOG, "", false);
 std::cout << "back_init_license key:" << key << std::endl;
 std::cout << "back_init_license licenseFile:" << licenseFile << std::endl;
 return (int)IOcrgveEngineBack::init_license(key, licenseFile, is_remote);
}

// 创建副业SDK实例
void* __stdcall dl_back_create() {
 IOcrgveEngineBack* engine = IOcrgveEngineBack::create();
 return engine;
}

//副业SDK实例初始化
int __stdcall dl_back_init(void* engine, char* ini_path) {
 IOcrgveEngineBack* _engine = (IOcrgveEngineBack*)engine;
 return (int)_engine->init(ini_path);
}

int __stdcall dl_back_ocr2(void* engine, Mat* image, char* ocr_result1, char* ocr_result2) {

 int res = 0;
 IOcrgveEngineBack* _engine = (IOcrgveEngineBack*)engine;

 ImageFrame input_frame;
 input_frame._width = (*image).cols;
 input_frame._height = (*image).rows;
 input_frame._data = (uint8_t*)(*image).data;
 input_frame._fmt = IMAGE_PIX_FMT_BGR;

 std::vector<ImageFrame> frames;
 frames.push_back(input_frame);
 std::vector<general_vertical_kv_ret> ocrgvesdk_response;

 clock_t start, finish;
 double  duration;
 start = clock();
 res = _engine->process_ocrgvebacksdk(frames, IMAGE_ORIENTATION_UP, ocrgvesdk_response);
 finish = clock();
 duration = (double)(finish - start) / CLOCKS_PER_SEC;
 printf("img_process time: %2.1f ms\r\n", duration * 1000);
 if (res !=SUCCESS) {
  return res;
 }

 std::string res_str("");
 std::string res_str2("");

 auto final_result = ocrgvesdk_response[0];
 int direction = 0;

 for (auto it : final_result.kv_content)
 {
  res_str += "\"" + it.first + "\":";

  res_str += "\"" + it.second[0].get_str() + "\"";
  res_str += ",";

  std::string str = ("{\"value\":\"") + it.second[0].get_str() + ("\",") +
   "\"coordinator\":\"" + std::to_string(it.second[0].get_coord()[0]) + (" ") +
   std::to_string(it.second[0].get_coord()[1]) + (" ") +
   std::to_string(it.second[0].get_coord()[2]) + (" ") +
   std::to_string(it.second[0].get_coord()[3]) + (" ") +
   std::to_string(it.second[0].get_coord()[4]) + (" ") +
   std::to_string(it.second[0].get_coord()[5]) + (" ") +
   std::to_string(it.second[0].get_coord()[6]) + (" ") +
   std::to_string(it.second[0].get_coord()[7]) + ("\"") +
   +",\"score\":\"" + std::to_string(it.second[0].get_det_score()) + "\"}";

  res_str2 = res_str2 + str.c_str();
  res_str2 += ",";
 }

 std::string res_header =
  "\"logid\":\"\",\"err_no\":0,\"err_msg\":\"SUCCESS\",\"querysign\":\"4188554259,1723708640\",\"image_dir\":\"" + std::to_string(direction) + "\",\"ret\":{";

 if (res_str.empty()) {
  return -1;
 }

 res_str.pop_back();
 res_str = "{" + res_header + res_str + "}}";

 const char *cstr = res_str.c_str();
 strcpy(ocr_result1, cstr);

 res_str2.erase(res_str2.length() - 1);
 res_str2 = "[" + res_str2 + "]";
 const char *cstr2 = res_str2.c_str();
 strcpy(ocr_result2, cstr2);

 return res;
}

//副页SDK识别
int __stdcall dl_back_ocr(void* engine, char* image_path, char* ocr_result1, char* ocr_result2) {
 int res = 0;
 IOcrgveEngineBack* _engine = (IOcrgveEngineBack*)engine;
 std::cout << "image_path:" << image_path << std::endl;
 Mat input_mat;
 try {
  input_mat = imread(image_path, IMREAD_COLOR);
 }
 catch (...) {
  std::cout << "imread error" << std::endl;
  return -1;
 }
 return dl_back_ocr2(_engine, &input_mat, ocr_result1, ocr_result2);
}

//副页SDK释放
void __stdcall dl_back_destroy(void* engine) {
 IOcrgveEngineBack* _engine = (IOcrgveEngineBack*)engine;
 _engine->uninit();
 IOcrgveEngineBack::destroy(&_engine);
}

用户评论