触摸精灵调用大漠字库识别文字

发布于 2019-06-14 01:39:08

本代码原始文件由@jzl6668 提供.本人改成触摸可用的格式.如有侵权请联系本人删除!

原贴地址 #触摸加个OCR文字识别模块 最好是可以调用大漠字库的

DM = {
    LoadDict = (function(sPath)
            tDict = {}
            local f = io.open(sPath,"r")
            if not f then
                notifyMessage(string.format("字库打开错误:%s",sPath),5000)
                return
            end
            local str = f:read()
            while str do
                str = string.gsub(str, "%$", "|")
                local s = DM.Split(str,"|")
                local v = s[1]
                local ps={}
                local Or = DM.HexToOr(v)
                local len = string.len(Or)
                local w = math.floor(len/11)
                local h = tonumber(s[4])

                if h>=11 then
                    h = 11
                    for i=1,w*h do
                        table.insert(ps,tonumber(string.sub(Or,i,i)))
                    end
                else
                    local clum = 1
                    for i=1,len do
                        if i%12<=h then
                            table.insert(ps,tonumber(string.sub(Or,i,i)))
                        end
                    end
                end

                table.insert(tDict,{ps=ps,c=s[2],w = w,h = h})
                str = f:read()
            end
            f:close()
        end),
    HexToOr = (function(hexstr)--16进制转2进制
            if type(hexstr)=="number" then
                hexstr = string.format("%X",hexstr)
            else
                hexstr = string.upper(hexstr)
                hexstr = string.gsub(hexstr,"0X","")
            end
            local len = string.len(hexstr)
            local ot = {}
            local tOr = DM.tOr
            for i=1,len do
                table.insert(ot,tOr[string.sub(hexstr,i,i)])
            end
            return table.concat(ot)
        end),
    OrToHex = (function(OrStr)--2进制转16进制
            local len = string.len(OrStr)
            local on = ""
            local tOr = DM.tOr
            for i=1,len,4 do
                local n = tOr[string.sub(OrStr,i,i+3)]
                if n then
                    on = on..n
                end
            end
            return on
        end),
    tOr = {
            ["0"] = "0000",
            ["1"] = "0001",
            ["2"] = "0010",
            ["3"] = "0011",
            ["4"] = "0100",
            ["5"] = "0101",
            ["6"] = "0110",
            ["7"] = "0111",
            ["8"] = "1000",
            ["9"] = "1001",
            ["A"] = "1010",
            ["B"] = "1011",
            ["C"] = "1100",
            ["D"] = "1101",
            ["E"] = "1110",
            ["F"] = "1111",
            ["0000"] = "0",
            ["0001"] = "1",
            ["0010"] = "2",
            ["0011"] = "3",
            ["0100"] = "4",
            ["0101"] = "5",
            ["0110"] = "6",
            ["0111"] = "7",
            ["1000"] = "8",
            ["1001"] = "9",
            ["1010"] = "A",
            ["1011"] = "B",
            ["1100"] = "C",
            ["1101"] = "D",
            ["1110"] = "E",
            ["1111"] = "F"
        },
    Split = (function(szFullString, szSeparator)
            local nFindStartIndex = 1
            local nSplitIndex = 1
            local nSplitArray = {}
            while true do
               local nFindLastIndex = string.find(szFullString, szSeparator, nFindStartIndex)
               if not nFindLastIndex then
                nSplitArray[nSplitIndex] = string.sub(szFullString, nFindStartIndex, string.len(szFullString))
                break
               end
               nSplitArray[nSplitIndex] = string.sub(szFullString, nFindStartIndex, nFindLastIndex - 1)
               nFindStartIndex = nFindLastIndex + string.len(szSeparator)
               nSplitIndex = nSplitIndex + 1
            end
            return nSplitArray
        end),
    GetRGB = (function(c)
            return  math.floor(c/0x10000),math.floor(c%0x10000/0x100),math.floor(c%0x100)
        end),
    CmpColor = (function(x,y,c,p)
            local r,g,b = DM.GetRGB(c)
            local r1,g1,b1 =DM.GetRGB(p)
            local rr,gg,bb = getColorRGB(x,y)
            if math.abs(r-rr)<=r1 and math.abs(g-gg)<=g1 and math.abs(b-bb)<=b1 then
                return 1
            end
            return 0
        end),
    GetWord = (function(lx,ly,rx,ry,c,p)
            keepScreen(true)
            local st = {}
            for x=lx,rx do
                for y=ly,ry do
                    table.insert(st,DM.CmpColor(x,y,c,p))
                end
            end
            local n = #st%4
            for i=1,n do
                table.insert(st,"0")
            end
            keepScreen(false)
            return st
        end),
    CmpWordByPs = (function(ps,lx,ly,rx,ry,t)
        local pnumber = #ps
        local snumber = pnumber - (pnumber * t.sim)
        local i = 1
        local r,g,b,c
        local MaxR,MaxG,MaxB,SmlR,SmlG,SmlB = t.MaxR,t.MaxG,t.MaxB,t.SmlR,t.SmlG,t.SmlB
        for x = lx , rx do
            for y = ly , ry do
                r,g,b = getColorRGB(x,y)
                if r>MaxR or r<SmlR or g>MaxG or g<SmlG or b>MaxB or b<SmlB then
                    c = 0
                else
                    c = 1
                end
                if c ~= ps[i] then
                    snumber = snumber - 1
                    if snumber<1 then
                        return
                    end
                end
                i = i + 1
            end
        end
        return true
    end),
    OcrWord = (function(lx,ly,rx,ry,t)
        local tx,ty
        local ipairs = ipairs
        for x=lx,rx do
            for y=ly,ry do
                for k,v in ipairs(tDict) do
                    tx,ty = x+v.w - 1,y + v.h - 1
                    if tx<=rx and ty<=ry then
                        if DM.CmpWordByPs(v.ps,x,y,tx,ty,t) then
                            return v.c..DM.OcrWord(x+v.w,ly,rx,ry,t)..DM.OcrWord(x,y + v.h ,x+v.w,ry,t)
                        end
                    end
                end
            end
        end
        return ""
    end),
    Ocr = (function(lx,ly,rx,ry,c,p,sim)
        keepScreen(true)
        local r,g,b = DM.GetRGB(c)
        local pr,pg,pb = DM.GetRGB(p)
        local t = {
            MaxR = math.min(r+pr,255),
            MaxG = math.min(g+pg,255),
            MaxB = math.min(b+pb,255),
            SmlR = math.max(r-pr,0),
            SmlG = math.max(g-pg,0),
            SmlB = math.max(b-pb,0),
            sim = sim,
        }
        local sReuslt = DM.OcrWord(lx,ly,rx,ry,t)
        keepScreen(false)
        return sReuslt
    end),
    CmpWordByMap = (function(tMap,ps,lx,ly,rx,ry,sim)
        local pnumber = #ps
        local snumber = pnumber - (pnumber * sim)
        local i = 1
        local Data = tMap.Data
        local w = tMap.w
        for x = lx , rx do
            for y = ly , ry do
                if Data[y*w + x] and ps[i]~=0 then
                    snumber = snumber - 1
                    if snumber<1 then
                        return
                    end
                end
                i = i + 1
            end
        end
        return true
    end),
    OrgMap = (function(lx,ly,rx,ry,c,p)
        local r,g,b = DM.GetRGB(c)
        local pr,pg,pb = DM.GetRGB(p)
        local MaxR = math.min(r+pr,255)
        local MaxG = math.min(g+pg,255)
        local MaxB = math.min(b+pb,255)
        local SmlR = math.max(r-pr,0)
        local SmlG = math.max(g-pg,0)
        local SmlB = math.max(b-pb,0)
        local Data = {}
        local tBitMap = {w = rx-lx,h = ry-ly,sx=lx,sy =ly}
        lx = lx - 1
        ly = ly - 1
        keepScreen(true)
        for y=1,tBitMap.h do
            for x=1,tBitMap.w do
                r,g,b = getColorRGB(x + lx,y  + ly)
                if r>MaxR or r<SmlR or g>MaxG or g<SmlG or b>MaxB or b<SmlB then
                    Data[y*tBitMap.w + x] = 0
                end
            end
        end
        keepScreen(false)
        tBitMap.Data = Data
        return tBitMap
    end),
    OrcWordByMap = (function(tMap,lx,ly,rx,ry,sim)
        local tDict = tDict
        local ipairs = ipairs
        local tx,ty
        for x=lx,rx do
            for y=ly,ry do
                for k,v in ipairs(tDict) do
                    tx,ty = x+v.w - 1,y + v.h - 1
                    if tx<=rx and ty<=ry then
                        if DM.CmpWordByMap(tMap,v.ps,x,y,tx,ty,sim) then
                            return v.c..DM.OrcWordByMap(tMap,x+v.w,ly,rx,ry,sim)..DM.OrcWordByMap(tMap,x,y + v.h ,x+v.w,ry,sim)
                        end
                    end

                end
            end
        end
        return ""
    end),
    OcrEx = (function (lx,ly,rx,ry,c,p,sim)
        local tMap = DM.OrgMap(lx,ly,rx,ry,c,p)
        return DM.OrcWordByMap(tMap,1,1,tMap.w,tMap.h,sim)
    end)
}

将以上代码复制到脚本内 main 入口函数之前

调用方法

function main()
    mSleep(2000)
    DM.LoadDict("/var/touchelf/res/dm.txt")--加载字库文件
    local t = os.clock()
    local s = DM.OcrEx(145,579,256,746,0x000000,0x000000,1)--识别,变量s是识别出来的内容
    logDebug(string.format("内容:%s  用时:%d",s,(os.clock()-t)*1000))
end
简单的测试了一下,使用机型5S.指定一个小范围识别时间大概是0.2秒左右.全屏识别大概30秒+,所以不要当做全屏找字来用!!

觉得有用的麻烦给点个赞^_^

7 条评论

发布
问题