2014年4月20日 星期日

政治獻金鄉民 OCR


今天是 g0v 黑客松,當初沒有報名,只好在家裡看看能做些什麼。
然後看到了有一個主題是要把政治獻金人肉轉回電子檔,有聽到 ronny 在 ODBC 上面提到就很想做做看。

我在 g0v 做的政治獻金網站翻譯了三個多小時,小有心得,有一些想法,希望能實做看看。
  • 翻譯時順便用 OCR 先掃一遍,如果運氣好辨識出來,那 user 就不用再打字了。
  • 看了一下原始表格,其實會有很大量的重複詞彙,其實可以先整理起來。
去找了一下有沒有甚麼 OCR 的函式庫。發現常用的有
  • tesseract-ocr
  • Office內建的 OCR: Microsot Office Document Imaging Library
我現在熟的是 PHP 還有 C# (好衝突)。
但又想要快速開發,然後我現在沒有 WebServer,於是就決定用 C# 和 MODI 希望能把研究的時間花到最少。

在開發中這次學到的技巧:
  • C# 串 JSON 
  • C# 串 WebService
  • C# 串 MODI
先放完成圖: [原始碼]






C# 串 JSON + WebService

要增加 Reference

  • System.ServiceModel.Web
  • System.Runtime.Serialization

範例



using System.Runtime.Serialization;
using System.Runtime.Serialization.Json; 

    [DataContract]
    class GetRandomResponse
    {
        [DataMember(Name = "img_url")]
        public string ImageUrl { get; set; }

        [DataMember(Name = "page")]
        public int Page { get; set; }

        [DataMember(Name = "x")]
        public int x { get; set; }

        [DataMember(Name = "y")]
        public int y { get; set; }

        [DataMember(Name = "ans")]
        public string Answer { get; set; }
    }

        public GetRandomResponse GetRandom()
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(API_GETRANDOM);
            GetRandomResponse resp = null;
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(GetRandomResponse));
                resp = serializer.ReadObject(response.GetResponseStream()) as GetRandomResponse;
            }

            return resp;
        }

        public string PostFillCell(int page, int x, int y, string ans)
        {
            this.CleanLog();

            string uri = string.Format("{0}/{1}/{2}/{3}", API_POSTANSWER, page, x, y);
            this.AppendLog("URL=" + uri);

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = "POST";

            request.ContentType = "application/x-www-form-urlencoded";
            string param = "ans=" + HttpUtility.UrlEncode(ans);
            byte[] bs = Encoding.ASCII.GetBytes(param);

            using (Stream reqStream = request.GetRequestStream())
            {
                reqStream.Write(bs, 0, bs.Length);
            }

            string result;
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                StreamReader sr = new StreamReader(response.GetResponseStream());
                result = sr.ReadToEnd();
                sr.Close();
            }

            return result;
        }

C# 串 MODI

要增加 Reference



辨識的程式碼範例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Drawing;

namespace OCR
{
    class OCREngine
    {
        public static string DoOCR(Bitmap bmp, MODI.MiLANGUAGES lang = MODI.MiLANGUAGES.miLANG_ENGLISH)
        {
            string str = string.Empty;
            string tmpfile = Path.GetTempFileName() + ".png";
            bmp.Save(tmpfile, System.Drawing.Imaging.ImageFormat.Png);

            try
            {
                MODI.Document mdoc = new MODI.Document();
                mdoc.Create(tmpfile);
                MODI.Image mImage = (MODI.Image)mdoc.Images[0];
                mImage.OCR(lang, true, true);

                foreach (MODI.Word word in mImage.Layout.Words)
                {
                    str += word.Text;
                }

                mdoc.Close();
            }
            catch { }
            finally
            {
                File.Delete(tmpfile);
            }

            return str;
        }
    }
}

沒有留言:

張貼留言