當前位置: 妍妍網 > 碼農

百度駕駛證C++離線SDK V1.1 C#接入

2024-04-21碼農

先看正頁、副頁辨識效果。

效果

說明

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);
}