前言
上次太神奇了!使用C#实现自动核验健康码:(1)二维码识别,我们已经实现了识别健康码的颜色,但是健康码的内容不包含时间属性。那么使用图片就可以通过检查,肯定是不合适的。
因此,我们还需要读出健康码上方的“更新于: xxxx”,获得最后的健康码更新时间,保证识别的是真实的健康码。
实现
1. OCR服务
由于通过摄像头获得的是图片,因此我们需要使用OCR文字识别功能,将图片上的文字读取出来。
可以有多种方式实现OCR功能,在这里,我们使用的是百度提供的“PaddleOCR 超轻量级中文OCR模型”在线体验服务(https://www.paddlepaddle.org.cn/hub/scene/ocr)。
它的优点是不用注册即可使用,而且速度和识别率也很高。
可以看到,服务返回的是一个JSON字符串,对应的C#数据结构如下:
public class OcrResult
{ public IReadOnlyList<ResultData> Result { get; set; }public class ResultData{public IReadOnlyList<TextData> Data { get; set; }public class TextData{public string Text { get; set; }}}
}
调用OCR服务代码如下:
var content = JsonConvert.SerializeObject(new { image = ToBase64(img) });
var json = Post("https://www.paddlepaddle.org.cn/paddlehub-api/image_classification/chinese_ocr_db_crnn_mobile", content);
var ocrResult = JsonConvert.DeserializeObject<OcrResult>(json);
2. 解析更新时间
我们需要读出Result
数组的第一个元素,然后遍历Data
数组,判断Text
是不是以“更新于”开头,如果是,后面紧跟的就是更新时间。
由于图片角度的问题,一行文字可能会被截成2个TextData
,因此需要做下判断。
具体实现代码如下:
string updateTimeText =null;
var dataResult = ocrResult.Result.First();
for (int i = 0; i < dataResult.Data.Count; i++)
{if (dataResult.Data[i].Text.StartsWith("更新于:") && dataResult.Data[i].Text.Length>4){updateTimeText = dataResult.Data[i].Text.Substring(4);break;}else if (dataResult.Data[i].Text.Equals("更新于:") || dataResult.Data[i].Text.Equals("更新于")){if (i < dataResult.Data.Count - 1){updateTimeText = dataResult.Data[i+1].Text;break;}}
}if (string.IsNullOrEmpty(updateTimeText))
{ return null;
}DateTime updateTime;
if (!DateTime.TryParseExact(updateTimeText, "yyyy-MM-ddHHmm", null, DateTimeStyles.None, out updateTime))
{return null;
}return updateTime;
3. 判断更新时间
最后,只显示更新时间在5分钟之内的健康码,表示是最新的健康码:
var updateTime = GetUpdateTime(img);
if (!updateTime.HasValue|| Math.Abs((DateTime.Now - updateTime.Value).TotalMinutes) > 5)
{return;
}label2.Text = updateTime.Value.ToString("yyyy-MM-dd HH:mm");ShowColor(color);
结论
把功能和界面完善一下,完全可以做成一个产品,代替人工核验健康码。
科技改变生活!
如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“,记住我!