用户上传地址图像 识别收/收件人信息定位、分割及识别图像

前言

最近在网上买了些东西,感觉不好,想退, 在办理退件过程中发现个好玩意,类似这样的输入框, 用户上传地址图像 识别收/收件人信息定位、分割及识别图像_第1张图片 

上传商户发的退货地址,自动识别退货信息。 也可粘贴文本自动识别。

感觉有点意思。考虑过各种实现原理,什么字典库,大数据之类。。。。,但是这些对个体小户来说不现实。最后还是靠baidu。

我的实现思路

1、上传图像 ...(废话), 转base64 .

2、识别图像中文字,即OCR , 目前有很多实现此功能的插件和接口,我使用的baiduapi,在百度开发者账户中可以申请的。 链接在此。 https://cloud.baidu.com/product/ocr  。

3、分词。 将图像转成的文字进行分词,识别人名,公司名,电话,省市区,详细地址。分词也有很多组件,我还是使用的baiduapi, 自然语言词法分析 http://ai.baidu.com/tech/nlp/lexical 。

4、转换。将分析的词进一步解析,比如将省市区转换为自己数据库中对应的省市区ID。 

5、回传显示 

实现步骤

1、准备好百度api相关配置信息

        //百度申请得到的AK     http://lbsyun.baidu.com/apiconsole/key
        public string Baidu_AK = "AAAAAAAAAAAAAAAAAAAAAA";

        //  文字识别 https://cloud.baidu.com/product/ocr
        public string Baidu_OCRApiKey = "BBBBBBBBBBBBBBBBBBB";
        public string Baidu_OCRSecret = "CCCCCCCCCCCCCCCCCCCC";

        //词法分析 http://ai.baidu.com/tech/nlp/lexical
        public string Baidu_NLPApiKey = "DDDDDDDDDDDDDDDDDDDDDDDD";
        public string Baidu_NLPSecret = "EEEEEEEEEEEEEEEEEEEEEEEEE";

2、上传图像,转base64 .

 上传略去,,, 转base64 给代码 

   /// 
        ///  图像路径
        /// 
        /// 
        /// 
        public static string ImgToBase64Str(string filepath)
        {
            try
            {
                Bitmap bmp = new Bitmap(filepath);
                MemoryStream ms = new MemoryStream();
                bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
                byte[] arr = new byte[ms.Length];
                ms.Position = 0;
                ms.Read(arr, 0, (int)ms.Length);
                ms.Close();
                return Convert.ToBase64String(arr);

            }
            catch (Exception ex)
            {
                return null;
            }
        }

2、图像识别

使用图像识别前要先获取AccessToken  ,和微信开发一样的。

  /// 
        ///   获取AccessToken
        /// 
        /// 
        private String getAccessToken(string Baidu_ApiKey, string Baidu_SecretKey)
        {
            string xpath = "//BaiduApi[@ApiKey='" + Baidu_ApiKey + "']";
            XmlNode apinode = XMLCache.SelectSingleNode(xpath);
            if (apinode != null)
            {
                string nodestr = apinode.InnerText;
                if (!string.IsNullOrEmpty(nodestr))
                {
                    BaiduAccessToken AccessToken = JsonConvert.DeserializeObject(nodestr);
                    if (AccessToken != null && AccessToken.ExpireTime > DateTime.Now.AddMinutes(3))
                    {
                        return AccessToken.access_token;
                    }
                }
            }

            // 缓存中若没有,重新获取
            String authHost = "https://aip.baidubce.com/oauth/2.0/token";

            List> paraList = new List>();

            paraList.Add(new KeyValuePair("grant_type", "client_credentials"));
            paraList.Add(new KeyValuePair("client_id", Baidu_ApiKey));
            paraList.Add(new KeyValuePair("client_secret", Baidu_SecretKey));
            String result = WebUtil.HttpClientPost(authHost, paraList);
            BaiduAccessToken token = JsonConvert.DeserializeObject(result);
            if (token != null && !string.IsNullOrEmpty(token.access_token))
            {
                token.ExpireTime = DateTime.Now.AddSeconds(token.expires_in);

                if (apinode != null)
                {
                    apinode.InnerText = JsonConvert.SerializeObject(token);
                }
                else
                {
                    XmlNode node = XMLCache.SelectSingleNode(ROOT);

                    XmlElement baiduapi = XMLCache.CreateElement("BaiduApi");
                    baiduapi.InnerText = JsonConvert.SerializeObject(token);
                    XmlAttribute apikey = XMLCache.CreateAttribute("ApiKey");
                    apikey.Value = Baidu_ApiKey;
                    baiduapi.Attributes.Append(apikey);
                    node.AppendChild(baiduapi);
                }
                XMLCache.Save(filepath);
                return token.access_token;
            }
            return "";
        }

调用api  ,识别图像内容 ,

base64一定要转码 ,切记。

System.Web.HttpUtility.UrlEncode(base64str, System.Text.Encoding.UTF8)
        private OcrData GetOcrData(string base64str)
        {

            string token = getAccessToken(Baidu_OCRApiKey, Baidu_OCRSecret);

            string OCR_URL = "https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token=" + token;

            Dictionary verifyPostParameters = new Dictionary();

            List> paraList = new List>();
            paraList.Add(new KeyValuePair("image", base64str));

            String result = WebUtil.HttpClientPostImg(OCR_URL, paraList);

            OcrData ocrResult = JsonConvert.DeserializeObject(result);
            return ocrResult;
        }

HttpClientPostImg 自己封装的。 

/// 
        /// HttPClient操作POST
        /// 
        /// 
        /// 
        /// 
        public static string HttpClientPostImg(string url, List> data)
        {
            using (var client = new HttpClient())
            {
                string str = string.Empty;
                if (data != null)
                {
                    foreach (var item in data)
                    {
                        str += item.Key + "=" + item.Value;
                    }
                }

                var content = new StringContent(str, Encoding.UTF8, "application/json");
                var response = client.PostAsync(url, content).Result;

                var responseString = response.Content.ReadAsStringAsync().Result;

                return responseString;
            }
        }

3、分词 

 使用前同样要获取AccessToken ,  将上步骤解析到的字符串拼接为一字符串,传入api .


        /// 
        /// 
        /// 
        /// 
        /// 
        private BaiduLexer GetBaiduLexer(string par)
        {
            string token = getAccessToken(Baidu_NLPApiKey, Baidu_NLPSecret);

            string OCR_URL = "https://aip.baidubce.com/rpc/2.0/nlp/v1/lexer?access_token=" + token;

            Dictionary verifyPostParameters = new Dictionary();

            String result = WebUtil.PostMoths(OCR_URL, par);

            BaiduLexer baiduLexer = JsonConvert.DeserializeObject(result);
            return baiduLexer;
        }

  解析结果 标识--百度api 

 用户上传地址图像 识别收/收件人信息定位、分割及识别图像_第2张图片

3.1 获取人名。

  /// 
        /// 获取人员姓名或公司名称
        /// 
        /// 
        /// 
        private string GetPER(BaiduLexer baiduLexer)
        {
            string per = string.Empty;
            var items = baiduLexer.items;
            var perm = items.LastOrDefault(e => e.ne == "PER");
            if (perm != null)
            {
                per = perm.item;
            }
            else
            {
                var nrm = items.LastOrDefault(e => e.pos == "nr");
                if (nrm != null)
                {
                    per = nrm.item;
                }
            }
            if (string.IsNullOrEmpty(per))
            {
                var orgm = items.LastOrDefault(e => e.ne == "ORG");
                if (orgm != null)
                {
                    per = orgm.item;
                }
                else
                {
                    var nt = items.LastOrDefault(e => e.pos == "nt");
                    if (nt != null)
                    {
                        per = nt.item;
                    }
                }
            }

            return per;
        }

3.2 获取电话

  /// 
        /// 匹配电话
        /// 
        /// 
        /// 
        private string GetMobile(string input)
        {
            Regex regex = new Regex("0?(13|14|15|17|18|19)[0-9]{9}");
            Match match = regex.Match(input);
            if (match.Success)
            {
                return match.Value;
            }
            else
            {
                Regex _regex = new Regex("^(0[0-9]{2,3}/-)?([2-9][0-9]{6,7})+(/-[0-9]{1,4})?$");
                Match _match = regex.Match(input);
                if (_match.Success)
                {
                    return _match.Value;
                }
            }
            return "";
        }

3.3 获取地址  

 /// 
        /// 获取地址
        /// 
        /// 
        /// 
        private string GetLOC(BaiduLexer baiduLexer)
        {
            string address = string.Empty;
            var items = baiduLexer.items;
            var list = items.Where(e => e.ne == "LOC").ToList();
            if (list != null && list.Count > 0)
            {
                foreach (var item in list)
                {
                    address += item.item;
                }
            }
            return address;
        }

4、转换

得到的地址信息是一串字符串,如:上海上海市普陀区桃浦新村X弄XX号。或上海普陀区桃浦新村X路XX号
地址不一定按照 XX省XX市XX区标准格式。。有能力的自己写正则匹配(在下佩服),  像我这样懒的找个api试试。

so .我又找度娘。。 我使用的方法比较笨, 如有好方法,希望留言探讨。

我先用得到的地址信息获取经纬度, 再用经纬度获取省市区。百度api会帮忙校验地址合法性以及补全地址信息。

 4.1 获取经纬度


        /// 
        /// 根据地址获取经纬度
        /// 
        /// 
        /// 
        public Location GetLocation(string address, string Baidu_AK)
        {

            string Url = "http://api.map.baidu.com/geocoder/v2/?address=" + address + "&output=json&ak=" + Baidu_AK;

            String result = WebUtil.HttpClientGet(Url);
            BaiduMapApiResult Result = JsonConvert.DeserializeObject(result);
            if (Result.status == 0)
            {
                return Result.result.location;
            }

            return null;
        }

4.2 根据经纬度获取地址信息

  public LocationOut GetLocation(decimal lat, decimal lnt, string Baidu_AK)
        {
            StringBuilder URLbuilder = new StringBuilder("http://api.map.baidu.com/geocoder/v2/");

            URLbuilder.AppendFormat("?location={0},{1}", lat, lnt);
            URLbuilder.Append("&output=json&pois=0");
            URLbuilder.AppendFormat("&ak={0}", Baidu_AK);
            string restult = WebUtil.HttpClientGet(URLbuilder.ToString());
            LocationOut location = new LocationOut();
            var baiduresult = JsonConvert.DeserializeObject(restult);
            if (baiduresult.status == 0 && !string.IsNullOrEmpty(baiduresult.result.formatted_address))
            {
                var addressComponent = baiduresult.result.addressComponent;
                location.ProvinceName = addressComponent.province;
                location.CityName = addressComponent.city;
                location.AreaName = addressComponent.district;

            }
            return location;
        }

5、显示,,,,没啥说的

结尾

此实例对应并发性较高的不太使用。毕竟百度API 限制DPS为5 , 

实际业务中,中小客户,地址使用频率并不是很高, 可以使用,但不是很建议, 

网络上有提供识别地址的服务,当然是收费的,而且价格还很高。 

 

 实例截图,

用户上传地址图像 识别收/收件人信息定位、分割及识别图像_第3张图片用户上传地址图像 识别收/收件人信息定位、分割及识别图像_第4张图片

 

上传实例图片 。用户上传地址图像 识别收/收件人信息定位、分割及识别图像_第5张图片 (网络图片,有出处的,,),

 

实例代码下载 地址 : https://download.csdn.net/download/qq_25042791/10567449

 

 

你可能感兴趣的:(C#)