1、乱码问题
std::cout << "\n---------------------->>" << std::endl; WCHAR* pchDest = new WCHAR[64]; Utf8ToUnicode(final_result.name, pchDest, 64); string s(WcharToChar(pchDest)); delete pchDest; std::cout << "识别的姓名:" << s << std::endl; std::cout << "---------------------->>\n" << std::endl;Utf8ToUnicode函数
/*============================================================================= 函 数 名: Utf8ToUnicode 功 能: 实现将char型的buffer(utf8编码)中的内容安全地拷贝到指定的WCHAR型buffer(Unicode编码)中 参 数: char* pchSrc [in] 源字符串 WCHAR* pchDest [out] 目标buf int nDestLen [in] 目标buf长度(注意:以字节为单位,不是以字符个数为单位) 注 意: 无 返 回 值: 无 =============================================================================*/ void Utf8ToUnicode(const char* pchSrc, WCHAR* pchDest, int nDestLen) { if (pchSrc == NULL || pchDest == NULL) { return; } int nTmpLen = MultiByteToWideChar(CP_UTF8, 0, pchSrc, -1, NULL, 0); WCHAR* pWTemp = new WCHAR[nTmpLen + 1]; memset(pWTemp, 0, (nTmpLen + 1) * sizeof(WCHAR)); MultiByteToWideChar(CP_UTF8, 0, pchSrc, -1, pWTemp, nTmpLen + 1); UINT nLen = wcslen(pWTemp); if (nLen + 1 > (nDestLen / sizeof(WCHAR))) { wcsncpy(pchDest, pWTemp, nDestLen / sizeof(WCHAR) - 1); pchDest[nDestLen / sizeof(WCHAR) - 1] = 0; } else { wcscpy(pchDest, pWTemp); } delete[]pWTemp; }2、返回结构体
struct IDCardResponse { char name[64]; // 姓名 char gender[64]; // 性别 char ethnicity[64]; // 民族 char birth[1024]; // 出身日期 char address[1024]; // 住址 char id_number[1024]; // 身份证号 char authority[1024]; // 签发机关 char issuing_date[1024]; // 签发日期 char expiry_date[1024]; // 失效日期 float name_coord[8]; // 姓名 坐标 float gender_coord[8]; // 性别 坐标 float birth_coord[8]; // 出身日期 坐标 float address_coord[8]; // 住址 坐标 float id_number_coord[8]; // 身份证号 坐标 float ethnicity_coord[8]; // 民族 坐标 float authority_coord[8]; // 签发机关 坐标 float issuing_date_coord[8]; // 签发日期 坐标 float expiry_date_coord[8]; // 失效日期 坐标 };DLL中导出,我们定义如下:
//识别 extern "C" _declspec(dllexport) int __stdcall ocr(void* idcard_sdk, Mat* image, IDCardResponse* final_result);那么,在C#中我们进行如下对应的定义:
[StructLayout(LayoutKind.Sequential)] public struct IDCardResponse { [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 64)] public byte[] name; // 姓名 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 64)] public byte[] gender; // 性别 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 64)] public byte[] ethnicity; // 民族 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1024)] public byte[] birth; // 出身日期 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1024)] public byte[] address; // 住址 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1024)] public byte[] id_number; // 身份证号 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1024)] public byte[] authority; // 签发机关 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1024)] public byte[] issuing_date; // 签发日期 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1024)] public byte[] expiry_date; // 失效日期 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 8)] public float[] name_coord; // 姓名 坐标 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 8)] public float[] gender_coord; // 性别 坐标 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 8)] public float[] birth_coord; // 出身日期 坐标 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 8)] public float[] address_coord; // 住址 坐标 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 8)] public float[] id_number_coord; // 身份证号 坐标 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 8)] public float[] ethnicity_coord; // 民族 坐标 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 8)] public float[] authority_coord; // 签发机关 坐标 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 8)] public float[] issuing_date_coord; // 签发日期 坐标 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 8)] public float[] expiry_date_coord; // 失效日期 坐标 }C#中申明如下:
[DllImport(DllName, EntryPoint = "ocr", CallingConvention = CallingConvention.Cdecl)] public extern static int ocr(IntPtr idcard_sdk, IntPtr image, ref IDCardResponse final_result);调用代码如下:
Mat image = new Mat(image_path); IDCardResponse final_result = new IDCardResponse(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); int res = Native.ocr(IDCard, image.CvPtr, ref final_result); stopwatch.Stop(); double totalTime = stopwatch.Elapsed.TotalSeconds; textBox1.Text += $"耗时: {totalTime:F2}s"; textBox1.Text += "\r\n-------------------\r\n";效果