MainActivity.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. using Android.App;
  2. using Android.Graphics;
  3. using Android.OS;
  4. using Android.Widget;
  5. using AndroidX.AppCompat.App;
  6. using IDCardRecognitionLibs;
  7. using OfficeOpenXml;
  8. using System;
  9. using System.IO;
  10. using System.Linq;
  11. using System.Reflection;
  12. using System.Runtime.InteropServices;
  13. using System.Threading;
  14. using System.Threading.Tasks;
  15. namespace IDCardRecognitionXamarin
  16. {
  17. [Activity(Label = "@string/app_name", Theme = "@style/AppTheme.NoActionBar", MainLauncher = true)]
  18. public class MainActivity : AppCompatActivity
  19. {
  20. private IDCardRecog _iDCardRecog = new IDCardRecog();
  21. private volatile bool _testing = false;
  22. private volatile Android.Graphics.Bitmap _testImg;
  23. private string _assemblyName;
  24. private TypeInfo _typeInfo;
  25. protected override void OnCreate(Bundle savedInstanceState)
  26. {
  27. var typeInfo = GetType().GetTypeInfo();
  28. _typeInfo = typeInfo;
  29. var assemblyName = typeInfo.Assembly.GetName().Name;
  30. _assemblyName = assemblyName;
  31. var netDetDir = $"{assemblyName}.Resources.ValidModels.ch_PP-OCRv4_det_infer.onnx";
  32. byte[] detBuffer = getModelBuffer(typeInfo, netDetDir);
  33. var netRecDir = $"{assemblyName}.Resources.ValidModels.ch_PP-OCRv4_rec_infer.onnx";
  34. byte[] recBuffer = getModelBuffer(typeInfo, netRecDir);
  35. var netDirKeys = $"{assemblyName}.Resources.ValidModels.ppocr_keys_v1.txt";
  36. byte[] recKeyBuffer = getModelBuffer(typeInfo, netDirKeys);
  37. var netClsDir = $"{assemblyName}.Resources.ValidModels.ch_ppocr_mobile_cls_infer.onnx";
  38. byte[] clsBuffer = getModelBuffer(typeInfo, netClsDir);
  39. bool ret = _iDCardRecog.LoadNetWorks(detBuffer, recBuffer, recKeyBuffer, clsBuffer);
  40. if (!ret)
  41. {
  42. Console.WriteLine("LoadNetWorks error");
  43. }
  44. base.OnCreate(savedInstanceState);
  45. Xamarin.Essentials.Platform.Init(this, savedInstanceState);
  46. SetContentView(Resource.Layout.activity_main);
  47. var btnTestBin = FindViewById<Button>(Resource.Id.btnBin);
  48. btnTestBin.Click += BtnShowSrcImgClick;
  49. var btnPlusStruct = FindViewById<Button>(Resource.Id.btnPlus);
  50. btnPlusStruct.Click += BtnTestBtnPlusClick;
  51. }
  52. private void BtnShowSrcImgClick(object sender, EventArgs e)
  53. {
  54. if (!_testing)
  55. {
  56. Task.Run(() =>
  57. {
  58. _testing = true;
  59. ImageView imageView = FindViewById<ImageView>(Resource.Id.imageView);
  60. var typeInfo = GetType().GetTypeInfo();
  61. var assemblyName = typeInfo.Assembly.GetName().Name;
  62. TextView textView = FindViewById<TextView>(Resource.Id.retTextInfor);
  63. var resourceName1 = $"{assemblyName}.Resources.drawable.img_3.png";
  64. using (var stream = typeInfo.Assembly.GetManifestResourceStream(resourceName1))
  65. {
  66. // 更新显示图像
  67. var bitmap = BitmapFactory.DecodeStream(stream);
  68. RunOnUiThread(() => imageView.SetImageBitmap(bitmap));
  69. // 将图像传给_test去做检测
  70. int width = bitmap.Width;
  71. int height = bitmap.Height;
  72. IntPtr dataPointer = bitmap.LockPixels();
  73. EnumColorType colorType = EnumColorType.Rgba;
  74. int stride = bitmap.RowBytes;
  75. byte[] data = BitmapToByte(dataPointer, width, height, colorType, stride);
  76. ClassIDCardRecogResult result = _iDCardRecog.EvaluateOneImage(data, width, height, colorType);
  77. RunOnUiThread(() => textView.Text = "身份证信息:" + "\n "
  78. + "返回码:" + result.Status + "\n "
  79. + "姓名:" + result.Name + "\n "
  80. + "性别:" + result.Gender + "\n "
  81. + "民族:" + result.Nation + "\n "
  82. + "出生:" + result.Birthdate + "\n "
  83. + "住址:" + result.Address + "\n "
  84. + "公民身份号码:" + result.IdNumber + "\n ");
  85. }
  86. Thread.Sleep(3000);
  87. _iDCardRecog.Dispose();
  88. _testing = false;
  89. });
  90. }
  91. }
  92. private void BtnTestBtnPlusClick(object sender, EventArgs e)
  93. {
  94. if (!_testing)
  95. {
  96. Task.Run(() =>
  97. {
  98. _testing = true;
  99. ImageView imageView = FindViewById<ImageView>(Resource.Id.imageView);
  100. var typeInfo = GetType().GetTypeInfo();
  101. var assemblyName = typeInfo.Assembly.GetName().Name;
  102. TextView textView = FindViewById<TextView>(Resource.Id.retTextInfor);
  103. int indexStart = 19;
  104. int indexEnd = 50;
  105. string dstPath = "/sdcard/Documents/" + DateTime.Now.ToString("yyyy-MM-dd-mm-ss-fffff") + "_log.txt";
  106. // 将文本内容存储到Excel表格
  107. string excelFilePath = "/sdcard/Documents/" + DateTime.Now.ToString("yyyy-MM-dd-mm-ss-fffff") + "_log.xlsx";
  108. AppendTextToExcel(excelFilePath, "imgId", "so20");
  109. for (int i = indexStart; i < indexEnd; i++)
  110. {
  111. var resourceName1 = $"{assemblyName}.Resources.drawable.img_{i}.png";
  112. using (var stream = typeInfo.Assembly.GetManifestResourceStream(resourceName1))
  113. {
  114. // 更新显示图像
  115. var bitmap = BitmapFactory.DecodeStream(stream);
  116. RunOnUiThread(() => imageView.SetImageBitmap(bitmap));
  117. // 将图像传给_test去做检测
  118. int width = bitmap.Width;
  119. int height = bitmap.Height;
  120. IntPtr dataPointer = bitmap.LockPixels();
  121. EnumColorType colorType = EnumColorType.Rgba;
  122. int stride = bitmap.RowBytes;
  123. byte[] data = BitmapToByte(dataPointer, width, height, colorType, stride);
  124. ClassIDCardRecogResult result = _iDCardRecog.EvaluateOneImage(data, width, height, colorType);
  125. RunOnUiThread(() => textView.Text = i + ".jpg -" + "身份证信息:" + "\n "
  126. + "返回码:" + result.Status + "\n "
  127. + "耗时:" + result.TimeSpan + "\n ");
  128. // 添加文本到log 中
  129. string addExcelCol2 = result.Status + "-" + result.Name
  130. + "-" + result.Gender
  131. + "-" + result.Nation
  132. + "-" + result.Birthdate
  133. + "-" + result.Nation
  134. + "-" + result.Address;
  135. AppendTextToFile(dstPath, "img_" + i + ".jpg:\n" + addExcelCol2);
  136. AppendTextToExcel(excelFilePath, "img_" + i + ".jpg", addExcelCol2);
  137. }
  138. Thread.Sleep(3000);
  139. }
  140. _testing = false;
  141. _iDCardRecog.Dispose();
  142. });
  143. }
  144. }
  145. // 追加文本到文件
  146. private void AppendTextToFile(string filePath, string text)
  147. {
  148. try
  149. {
  150. // 如果文件不存在,则创建文件;如果存在,则追加内容
  151. using (StreamWriter sw = File.AppendText(filePath))
  152. {
  153. sw.WriteLine(text);
  154. }
  155. }
  156. catch (Exception ex)
  157. {
  158. Console.WriteLine("Error appending text to file: " + ex.Message);
  159. }
  160. }
  161. // 将文本内容追加到Excel表格
  162. private static void AppendTextToExcel(string excelFilePath, string textContentColumn0, string textContentColumn1)
  163. {
  164. FileInfo excelFile = new FileInfo(excelFilePath);
  165. using (ExcelPackage package = new ExcelPackage(excelFile))
  166. {
  167. ExcelWorksheet worksheet;
  168. // 检查是否存在名为 "LogData" 的工作表
  169. if (package.Workbook.Worksheets.Any(ws => ws.Name == "LogData"))
  170. {
  171. worksheet = package.Workbook.Worksheets["LogData"];
  172. }
  173. else
  174. {
  175. // 如果不存在,则创建新的工作表
  176. worksheet = package.Workbook.Worksheets.Add("LogData");
  177. }
  178. // 获取工作表中已有的行数
  179. int existingRowCount = worksheet.Dimension?.Rows ?? 0;
  180. // 分割新文本内容并追加到表格
  181. string[] linesColumn0 = textContentColumn0.Split('\n');
  182. string[] linesColumn1 = textContentColumn1.Split('\n');
  183. int newRowCount = Math.Max(linesColumn0.Length, linesColumn1.Length);
  184. for (int rowIndex = existingRowCount + 1; rowIndex <= existingRowCount + newRowCount; rowIndex++)
  185. {
  186. // 获取每列文本内容
  187. string column0Value = (rowIndex - existingRowCount <= linesColumn0.Length) ? linesColumn0[rowIndex - existingRowCount - 1] : string.Empty;
  188. string column1Value = (rowIndex - existingRowCount <= linesColumn1.Length) ? linesColumn1[rowIndex - existingRowCount - 1] : string.Empty;
  189. // 存储到表格
  190. worksheet.Cells[rowIndex, 1].Value = column0Value; // 第一列
  191. worksheet.Cells[rowIndex, 2].Value = column1Value; // 第二列
  192. }
  193. package.Save();
  194. }
  195. }
  196. private static byte[] ReadStreamContent(System.IO.Stream stream)
  197. {
  198. if (stream != null)
  199. {
  200. try
  201. {
  202. // 使用BinaryReader读取流中的内容并转换为字节数组
  203. using (BinaryReader br = new BinaryReader(stream))
  204. {
  205. // 使用MemoryStream来存储字节数组
  206. using (MemoryStream ms = new MemoryStream())
  207. {
  208. byte[] buffer = new byte[1024];
  209. int bytesRead;
  210. while ((bytesRead = br.Read(buffer, 0, buffer.Length)) > 0)
  211. {
  212. ms.Write(buffer, 0, bytesRead);
  213. }
  214. // 返回字节数组
  215. return ms.ToArray();
  216. }
  217. }
  218. }
  219. catch (Exception ex)
  220. {
  221. // 处理异常
  222. Console.WriteLine("读取流时发生错误:" + ex.Message);
  223. return new byte[0];
  224. }
  225. }
  226. else
  227. {
  228. Console.WriteLine("流为空");
  229. return new byte[0];
  230. }
  231. }
  232. private static string ReadStreamContentStr(System.IO.Stream stream)
  233. {
  234. if (stream != null)
  235. {
  236. try
  237. {
  238. // 使用StreamReader读取流中的内容
  239. using (StreamReader sr = new StreamReader(stream))
  240. {
  241. // 读取流中的全部内容
  242. return sr.ReadToEnd();
  243. }
  244. }
  245. catch (Exception ex)
  246. {
  247. // 处理异常
  248. Console.WriteLine("读取流时发生错误:" + ex.Message);
  249. return string.Empty;
  250. }
  251. }
  252. else
  253. {
  254. Console.WriteLine("流为空");
  255. return string.Empty;
  256. }
  257. }
  258. private byte[] getModelBuffer(TypeInfo typeInfo, string netDir)
  259. {
  260. // 获取模型流
  261. var stream = typeInfo.Assembly.GetManifestResourceStream(netDir);
  262. if (stream == null)
  263. {
  264. throw new InvalidOperationException($"Resource not found: {netDir}");
  265. }
  266. // 读取流内容到字节数组
  267. byte[] buffer = new byte[stream.Length];
  268. stream.Read(buffer, 0, buffer.Length);
  269. return buffer;
  270. }
  271. private byte[] BitmapToByte(IntPtr dataPointer, int width, int height, EnumColorType colorType, int stride)
  272. {
  273. int origBytesPerPixel = 0;
  274. EnumColorType dstColorType = EnumColorType.Bgra;
  275. if (colorType == EnumColorType.Rgba)
  276. {
  277. origBytesPerPixel = 4;
  278. }
  279. if (colorType == EnumColorType.Bgr)
  280. {
  281. origBytesPerPixel = 3;
  282. }
  283. byte[] dstDataArray = new byte[width * height * origBytesPerPixel];
  284. IntPtr ptrH, ptrW;
  285. int dstStride = width * origBytesPerPixel;
  286. for (int nh = 0; nh < height; nh++)
  287. {
  288. ptrH = IntPtr.Add(dataPointer, nh * stride);
  289. Marshal.Copy(ptrH, dstDataArray, nh * dstStride, dstStride);
  290. }
  291. //// 如果原图是BGRA彩色图
  292. ////if (oriColorType == EnumColorType.Bgra)
  293. ////{
  294. //// if (colorType == EnumColorType.Bgr)
  295. //// {
  296. //// int dstOffset;
  297. //// for (int nh = 0; nh < height; nh++)
  298. //// {
  299. //// ptrH = IntPtr.Add(dataPointer, nh * stride);
  300. //// for (int nw = 0; nw < width; nw++)
  301. //// {
  302. //// ptrW = IntPtr.Add(ptrH, nw * origBytesPerPixel);
  303. //// dstOffset = nh * dstStride + nw * 3;
  304. //// Marshal.Copy(ptrW, dstDataArray, dstOffset, 3);
  305. //// }
  306. //// }
  307. //// }
  308. ////}
  309. return dstDataArray;
  310. }
  311. }
  312. }