同級新建fonts檔案夾里拷貝一些字體檔案,從這里找C:\Windows\Fonts,幾十個就行, get_character_pic.py 生成字體 cnn.py 訓練資料 main.py 裁剪指定圖片并識別,素材圖片新建imgs檔案夾,在imgs/question.png下,結果檔案保存在imgs/result.png, 注意如果識別不成功,很可能是question.png的字體你沒有訓練(這幅圖的字體是方正書宋簡體,但是你只訓練了楷體),這時候可以使用楷體自己編一個算式圖,
一、亮出效果
最近在線教育行業遭遇一點小波折,一些搜題、智能批改類的功能要下線,
退1024步講,要不要自己做一個自動批改的功能啊?萬一哪天孩子要用呢!
昨晚我做了一個夢,夢見我實作了這個功能,如下圖所示:
功能簡介: 作對了,能打對號;做錯了,能打叉號;沒做的,能補上答案,
醒來后,我環顧四周,趕緊再躺下,希望夢還能接上,
二、實作步驟
基本思路
其實,搞定兩點就成,第一是能識別數字,第二是能切分數字,
首先得能認識5是5,這是前提條件,其次是能找到5、6、7、8這些數字區域的位置,
前者是影像識別 ,后者是影像切割 ,
對于影像識別,一般的套路是下面這樣的(CNN卷積神經網路):
<style>#mermaid-svg-19CB7BMTJEaRusAf .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-19CB7BMTJEaRusAf .label text{fill:#333}#mermaid-svg-19CB7BMTJEaRusAf .node rect,#mermaid-svg-19CB7BMTJEaRusAf .node circle,#mermaid-svg-19CB7BMTJEaRusAf .node ellipse,#mermaid-svg-19CB7BMTJEaRusAf .node polygon,#mermaid-svg-19CB7BMTJEaRusAf .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-19CB7BMTJEaRusAf .node .label{text-align:center;fill:#333}#mermaid-svg-19CB7BMTJEaRusAf .node.clickable{cursor:pointer}#mermaid-svg-19CB7BMTJEaRusAf .arrowheadPath{fill:#333}#mermaid-svg-19CB7BMTJEaRusAf .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-19CB7BMTJEaRusAf .flowchart-link{stroke:#333;fill:none}#mermaid-svg-19CB7BMTJEaRusAf .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-19CB7BMTJEaRusAf .edgeLabel rect{opacity:0.9}#mermaid-svg-19CB7BMTJEaRusAf .edgeLabel span{color:#333}#mermaid-svg-19CB7BMTJEaRusAf .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-19CB7BMTJEaRusAf .cluster text{fill:#333}#mermaid-svg-19CB7BMTJEaRusAf div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-19CB7BMTJEaRusAf .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-19CB7BMTJEaRusAf text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-19CB7BMTJEaRusAf .actor-line{stroke:grey}#mermaid-svg-19CB7BMTJEaRusAf .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-19CB7BMTJEaRusAf .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-19CB7BMTJEaRusAf #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-19CB7BMTJEaRusAf .sequenceNumber{fill:#fff}#mermaid-svg-19CB7BMTJEaRusAf #sequencenumber{fill:#333}#mermaid-svg-19CB7BMTJEaRusAf #crosshead path{fill:#333;stroke:#333}#mermaid-svg-19CB7BMTJEaRusAf .messageText{fill:#333;stroke:#333}#mermaid-svg-19CB7BMTJEaRusAf .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-19CB7BMTJEaRusAf .labelText,#mermaid-svg-19CB7BMTJEaRusAf .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-19CB7BMTJEaRusAf .loopText,#mermaid-svg-19CB7BMTJEaRusAf .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-19CB7BMTJEaRusAf .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-19CB7BMTJEaRusAf .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-19CB7BMTJEaRusAf .noteText,#mermaid-svg-19CB7BMTJEaRusAf .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-19CB7BMTJEaRusAf .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-19CB7BMTJEaRusAf .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-19CB7BMTJEaRusAf .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-19CB7BMTJEaRusAf .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-19CB7BMTJEaRusAf .section{stroke:none;opacity:0.2}#mermaid-svg-19CB7BMTJEaRusAf .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-19CB7BMTJEaRusAf .section2{fill:#fff400}#mermaid-svg-19CB7BMTJEaRusAf .section1,#mermaid-svg-19CB7BMTJEaRusAf .section3{fill:#fff;opacity:0.2}#mermaid-svg-19CB7BMTJEaRusAf .sectionTitle0{fill:#333}#mermaid-svg-19CB7BMTJEaRusAf .sectionTitle1{fill:#333}#mermaid-svg-19CB7BMTJEaRusAf .sectionTitle2{fill:#333}#mermaid-svg-19CB7BMTJEaRusAf .sectionTitle3{fill:#333}#mermaid-svg-19CB7BMTJEaRusAf .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-19CB7BMTJEaRusAf .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-19CB7BMTJEaRusAf .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-19CB7BMTJEaRusAf .grid path{stroke-width:0}#mermaid-svg-19CB7BMTJEaRusAf .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-19CB7BMTJEaRusAf .task{stroke-width:2}#mermaid-svg-19CB7BMTJEaRusAf .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-19CB7BMTJEaRusAf .taskText:not([font-size]){font-size:11px}#mermaid-svg-19CB7BMTJEaRusAf .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-19CB7BMTJEaRusAf .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-19CB7BMTJEaRusAf .task.clickable{cursor:pointer}#mermaid-svg-19CB7BMTJEaRusAf .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-19CB7BMTJEaRusAf .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-19CB7BMTJEaRusAf .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-19CB7BMTJEaRusAf .taskText0,#mermaid-svg-19CB7BMTJEaRusAf .taskText1,#mermaid-svg-19CB7BMTJEaRusAf .taskText2,#mermaid-svg-19CB7BMTJEaRusAf .taskText3{fill:#fff}#mermaid-svg-19CB7BMTJEaRusAf .task0,#mermaid-svg-19CB7BMTJEaRusAf .task1,#mermaid-svg-19CB7BMTJEaRusAf .task2,#mermaid-svg-19CB7BMTJEaRusAf .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-19CB7BMTJEaRusAf .taskTextOutside0,#mermaid-svg-19CB7BMTJEaRusAf .taskTextOutside2{fill:#000}#mermaid-svg-19CB7BMTJEaRusAf .taskTextOutside1,#mermaid-svg-19CB7BMTJEaRusAf .taskTextOutside3{fill:#000}#mermaid-svg-19CB7BMTJEaRusAf .active0,#mermaid-svg-19CB7BMTJEaRusAf .active1,#mermaid-svg-19CB7BMTJEaRusAf .active2,#mermaid-svg-19CB7BMTJEaRusAf .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-19CB7BMTJEaRusAf .activeText0,#mermaid-svg-19CB7BMTJEaRusAf .activeText1,#mermaid-svg-19CB7BMTJEaRusAf .activeText2,#mermaid-svg-19CB7BMTJEaRusAf .activeText3{fill:#000 !important}#mermaid-svg-19CB7BMTJEaRusAf .done0,#mermaid-svg-19CB7BMTJEaRusAf .done1,#mermaid-svg-19CB7BMTJEaRusAf .done2,#mermaid-svg-19CB7BMTJEaRusAf .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-19CB7BMTJEaRusAf .doneText0,#mermaid-svg-19CB7BMTJEaRusAf .doneText1,#mermaid-svg-19CB7BMTJEaRusAf .doneText2,#mermaid-svg-19CB7BMTJEaRusAf .doneText3{fill:#000 !important}#mermaid-svg-19CB7BMTJEaRusAf .crit0,#mermaid-svg-19CB7BMTJEaRusAf .crit1,#mermaid-svg-19CB7BMTJEaRusAf .crit2,#mermaid-svg-19CB7BMTJEaRusAf .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-19CB7BMTJEaRusAf .activeCrit0,#mermaid-svg-19CB7BMTJEaRusAf .activeCrit1,#mermaid-svg-19CB7BMTJEaRusAf .activeCrit2,#mermaid-svg-19CB7BMTJEaRusAf .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-19CB7BMTJEaRusAf .doneCrit0,#mermaid-svg-19CB7BMTJEaRusAf .doneCrit1,#mermaid-svg-19CB7BMTJEaRusAf .doneCrit2,#mermaid-svg-19CB7BMTJEaRusAf .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-19CB7BMTJEaRusAf .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-19CB7BMTJEaRusAf .milestoneText{font-style:italic}#mermaid-svg-19CB7BMTJEaRusAf .doneCritText0,#mermaid-svg-19CB7BMTJEaRusAf .doneCritText1,#mermaid-svg-19CB7BMTJEaRusAf .doneCritText2,#mermaid-svg-19CB7BMTJEaRusAf .doneCritText3{fill:#000 !important}#mermaid-svg-19CB7BMTJEaRusAf .activeCritText0,#mermaid-svg-19CB7BMTJEaRusAf .activeCritText1,#mermaid-svg-19CB7BMTJEaRusAf .activeCritText2,#mermaid-svg-19CB7BMTJEaRusAf .activeCritText3{fill:#000 !important}#mermaid-svg-19CB7BMTJEaRusAf .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-19CB7BMTJEaRusAf g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-19CB7BMTJEaRusAf g.classGroup text .title{font-weight:bolder}#mermaid-svg-19CB7BMTJEaRusAf g.clickable{cursor:pointer}#mermaid-svg-19CB7BMTJEaRusAf g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-19CB7BMTJEaRusAf g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-19CB7BMTJEaRusAf .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-19CB7BMTJEaRusAf .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-19CB7BMTJEaRusAf .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-19CB7BMTJEaRusAf .dashed-line{stroke-dasharray:3}#mermaid-svg-19CB7BMTJEaRusAf #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-19CB7BMTJEaRusAf #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-19CB7BMTJEaRusAf #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-19CB7BMTJEaRusAf #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-19CB7BMTJEaRusAf #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-19CB7BMTJEaRusAf #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-19CB7BMTJEaRusAf #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-19CB7BMTJEaRusAf #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-19CB7BMTJEaRusAf .commit-id,#mermaid-svg-19CB7BMTJEaRusAf .commit-msg,#mermaid-svg-19CB7BMTJEaRusAf .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-19CB7BMTJEaRusAf .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-19CB7BMTJEaRusAf .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-19CB7BMTJEaRusAf g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-19CB7BMTJEaRusAf g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-19CB7BMTJEaRusAf g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-19CB7BMTJEaRusAf g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-19CB7BMTJEaRusAf g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-19CB7BMTJEaRusAf g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-19CB7BMTJEaRusAf .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-19CB7BMTJEaRusAf .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-19CB7BMTJEaRusAf .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-19CB7BMTJEaRusAf .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-19CB7BMTJEaRusAf .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-19CB7BMTJEaRusAf .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-19CB7BMTJEaRusAf .edgeLabel text{fill:#333}#mermaid-svg-19CB7BMTJEaRusAf .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-19CB7BMTJEaRusAf .node circle.state-start{fill:black;stroke:black}#mermaid-svg-19CB7BMTJEaRusAf .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-19CB7BMTJEaRusAf #statediagram-barbEnd{fill:#9370db}#mermaid-svg-19CB7BMTJEaRusAf .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-19CB7BMTJEaRusAf .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-19CB7BMTJEaRusAf .statediagram-state .divider{stroke:#9370db}#mermaid-svg-19CB7BMTJEaRusAf .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-19CB7BMTJEaRusAf .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-19CB7BMTJEaRusAf .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-19CB7BMTJEaRusAf .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-19CB7BMTJEaRusAf .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-19CB7BMTJEaRusAf .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-19CB7BMTJEaRusAf .note-edge{stroke-dasharray:5}#mermaid-svg-19CB7BMTJEaRusAf .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-19CB7BMTJEaRusAf .error-icon{fill:#522}#mermaid-svg-19CB7BMTJEaRusAf .error-text{fill:#522;stroke:#522}#mermaid-svg-19CB7BMTJEaRusAf .edge-thickness-normal{stroke-width:2px}#mermaid-svg-19CB7BMTJEaRusAf .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-19CB7BMTJEaRusAf .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-19CB7BMTJEaRusAf .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-19CB7BMTJEaRusAf .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-19CB7BMTJEaRusAf .marker{fill:#333}#mermaid-svg-19CB7BMTJEaRusAf .marker.cross{stroke:#333}
:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}</style>
<style>#mermaid-svg-19CB7BMTJEaRusAf {
color: rgba(0, 0, 0, 0.75);
font: ;
}</style>
輸入
識別輸出
字符圖片資料集
訓練
訓練結果
字符圖片
字符值
對于影像切割,一般的套路是下面的這樣(橫向縱向投影法):
既然思路能走得通,那么咱們先搞影像識別,
要自己搞影像識別,得準備資料 ->訓練資料并保存模型 ->使用訓練模型預測結果 ,
2.1 準備資料
對于男友,找一個油嘴滑舌的花花公子,不如找一個悶葫蘆IT男,親手把他培養成你期望的樣子,
咱們不用什么官方的mnist資料集,因為那是官方的,不是你的,你想要添加±×÷它也沒有,
有些通用的資料集,雖然很強大,很方便,但是一旦放到你的場景中,效果一點也不如你的愿,
只有訓練自己手里的資料,然后自己用起來才順手,更重要的是,我們享受創造的程序,
假設,我們只給口算做識別,那么我們需要的圖片資料有如下幾類:
索引:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
字符:0 1 2 3 4 5 6 7 8 9 = + - × ÷
如果能識別這些,基本上能滿足整數的加減乘除運算了,
好了,圖片哪里來?!
是啊,圖片哪里來?
嚇得我差點從夢里醒來,500萬都規劃好該怎么花了,居然雙色球還沒有選號!
夢里,一個老者跟我說,圖片要自己生成,我問他如何生成,他呵呵一笑,消失在迷霧中……
仔細一想,其實也不難,打字我們總會吧,生成數字無非就是用代碼把字寫在圖片上,
字之所以能展示,主要是因為有字體的支撐,
如果你用的是windows系統,那么打開KaTeX parse error: Undefined control sequence: \Windows at position 3: C:\?W?i?n?d?o?w?s?\Fonts 這個檔案夾,你會發現好多字體,
我們寫代碼呼叫這些字體,然后把它列印到一張圖片上,是不是就有資料了,
而且這些資料完全是由我們控制的,想多就多,想少就少,想數字、字母、漢字、符號都可以,今天你搞出來數字識別,也就相當于你同時擁有了所有識別!想想還有點小激動呢!
看看,這就是打工和創業的區別,你用別人的資料相當于打工,你是不用操心,但是他給你什么你才有什么,自己造資料就相當于創業,雖然前期辛苦,你可以完全自己把握節奏,需要就加上,沒用就去掉,
2.1.1 準備字體
建一個fonts檔案夾,從字體庫里拷一部分字體放進來,我這里是拷貝了13種字體檔案,
好的,準備作業做好了,肯定很累吧,休息休息休息,一會兒再搞!
2.1.2 生成圖片
代碼如下,可以直接運行,
from __future__ import print_function
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
import os
import shutil
import time
# %% 要生成的文本
label_dict = { 0 : '0' , 1 : '1' , 2 : '2' , 3 : '3' , 4 : '4' , 5 : '5' , 6 : '6' , 7 : '7' , 8 : '8' , 9 : '9' , 10 : '=' , 11 : '+' , 12 : '-' , 13 : '×' , 14 : '÷' }
# 文本對應的檔案夾,給每一個分類建一個檔案
for value, char in label_dict. items( ) :
train_images_dir = "dataset" + "/" + str ( value)
if os. path. isdir( train_images_dir) :
shutil. rmtree( train_images_dir)
os. makedirs( train_images_dir)
# %% 生成圖片
def makeImage ( label_dict, font_path, width= 24 , height= 24 , rotate = 0 ) :
# 從字典中取出鍵值對
for value, char in label_dict. items( ) :
# 創建一個黑色背景的圖片,大小是24*24
img = Image. new( "RGB" , ( width, height) , "black" )
draw = ImageDraw. Draw( img)
# 加載一種字體,字體大小是圖片寬度的90%
font = ImageFont. truetype( font_path, int ( width* 0.9 ) )
# 獲取字體的寬高
font_width, font_height = draw. textsize( char, font)
# 計算字體繪制的x,y坐標,主要是讓文字畫在圖示中心
x = ( width - font_width- font. getoffset( char) [ 0 ] ) / 2
y = ( height - font_height- font. getoffset( char) [ 1 ] ) / 2
# 繪制圖片,在那里畫,畫啥,什么顏色,什么字體
draw. text( ( x, y) , char, ( 255 , 255 , 255 ) , font)
# 設定圖片傾斜角度
img = img. rotate( rotate)
# 命名檔案保存,命名規則:dataset/編號/img-編號_r-選擇角度_時間戳.png
time_value = int ( round ( time. time( ) * 1000 ) )
img_path = "dataset/{}/img-{}_r-{}_{}.png" . format ( value, value, rotate, time_value)
img. save( img_path)
# %% 存放字體的路徑
font_dir = "./fonts"
for font_name in os. listdir( font_dir) :
# 把每種字體都取出來,每種字體都生成一批圖片
path_font_file = os. path. join( font_dir, font_name)
# 傾斜角度從-10到10度,每個角度都生成一批圖片
for k in range ( - 10 , 10 , 1 ) :
# 每個字符都生成圖片
makeImage( label_dict, path_font_file, rotate = k)
上面純代碼不到30行,相信大家應該能看懂!看不懂不是我的讀者,
核心代碼就是畫文字,
draw.text((x,y), char, (255, 255, 255), font)
翻譯一下就是:使用某字體在黑底圖片的(x,y)位置寫白色的char符號,
核心邏輯就是三層回圈,
<style>#mermaid-svg-DEUFBhZUwl8W6J0f .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-DEUFBhZUwl8W6J0f .label text{fill:#333}#mermaid-svg-DEUFBhZUwl8W6J0f .node rect,#mermaid-svg-DEUFBhZUwl8W6J0f .node circle,#mermaid-svg-DEUFBhZUwl8W6J0f .node ellipse,#mermaid-svg-DEUFBhZUwl8W6J0f .node polygon,#mermaid-svg-DEUFBhZUwl8W6J0f .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-DEUFBhZUwl8W6J0f .node .label{text-align:center;fill:#333}#mermaid-svg-DEUFBhZUwl8W6J0f .node.clickable{cursor:pointer}#mermaid-svg-DEUFBhZUwl8W6J0f .arrowheadPath{fill:#333}#mermaid-svg-DEUFBhZUwl8W6J0f .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-DEUFBhZUwl8W6J0f .flowchart-link{stroke:#333;fill:none}#mermaid-svg-DEUFBhZUwl8W6J0f .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-DEUFBhZUwl8W6J0f .edgeLabel rect{opacity:0.9}#mermaid-svg-DEUFBhZUwl8W6J0f .edgeLabel span{color:#333}#mermaid-svg-DEUFBhZUwl8W6J0f .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-DEUFBhZUwl8W6J0f .cluster text{fill:#333}#mermaid-svg-DEUFBhZUwl8W6J0f div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-DEUFBhZUwl8W6J0f .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-DEUFBhZUwl8W6J0f text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-DEUFBhZUwl8W6J0f .actor-line{stroke:grey}#mermaid-svg-DEUFBhZUwl8W6J0f .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-DEUFBhZUwl8W6J0f .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-DEUFBhZUwl8W6J0f #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-DEUFBhZUwl8W6J0f .sequenceNumber{fill:#fff}#mermaid-svg-DEUFBhZUwl8W6J0f #sequencenumber{fill:#333}#mermaid-svg-DEUFBhZUwl8W6J0f #crosshead path{fill:#333;stroke:#333}#mermaid-svg-DEUFBhZUwl8W6J0f .messageText{fill:#333;stroke:#333}#mermaid-svg-DEUFBhZUwl8W6J0f .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-DEUFBhZUwl8W6J0f .labelText,#mermaid-svg-DEUFBhZUwl8W6J0f .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-DEUFBhZUwl8W6J0f .loopText,#mermaid-svg-DEUFBhZUwl8W6J0f .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-DEUFBhZUwl8W6J0f .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-DEUFBhZUwl8W6J0f .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-DEUFBhZUwl8W6J0f .noteText,#mermaid-svg-DEUFBhZUwl8W6J0f .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-DEUFBhZUwl8W6J0f .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-DEUFBhZUwl8W6J0f .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-DEUFBhZUwl8W6J0f .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-DEUFBhZUwl8W6J0f .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-DEUFBhZUwl8W6J0f .section{stroke:none;opacity:0.2}#mermaid-svg-DEUFBhZUwl8W6J0f .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-DEUFBhZUwl8W6J0f .section2{fill:#fff400}#mermaid-svg-DEUFBhZUwl8W6J0f .section1,#mermaid-svg-DEUFBhZUwl8W6J0f .section3{fill:#fff;opacity:0.2}#mermaid-svg-DEUFBhZUwl8W6J0f .sectionTitle0{fill:#333}#mermaid-svg-DEUFBhZUwl8W6J0f .sectionTitle1{fill:#333}#mermaid-svg-DEUFBhZUwl8W6J0f .sectionTitle2{fill:#333}#mermaid-svg-DEUFBhZUwl8W6J0f .sectionTitle3{fill:#333}#mermaid-svg-DEUFBhZUwl8W6J0f .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-DEUFBhZUwl8W6J0f .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-DEUFBhZUwl8W6J0f .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-DEUFBhZUwl8W6J0f .grid path{stroke-width:0}#mermaid-svg-DEUFBhZUwl8W6J0f .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-DEUFBhZUwl8W6J0f .task{stroke-width:2}#mermaid-svg-DEUFBhZUwl8W6J0f .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-DEUFBhZUwl8W6J0f .taskText:not([font-size]){font-size:11px}#mermaid-svg-DEUFBhZUwl8W6J0f .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-DEUFBhZUwl8W6J0f .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-DEUFBhZUwl8W6J0f .task.clickable{cursor:pointer}#mermaid-svg-DEUFBhZUwl8W6J0f .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-DEUFBhZUwl8W6J0f .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-DEUFBhZUwl8W6J0f .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-DEUFBhZUwl8W6J0f .taskText0,#mermaid-svg-DEUFBhZUwl8W6J0f .taskText1,#mermaid-svg-DEUFBhZUwl8W6J0f .taskText2,#mermaid-svg-DEUFBhZUwl8W6J0f .taskText3{fill:#fff}#mermaid-svg-DEUFBhZUwl8W6J0f .task0,#mermaid-svg-DEUFBhZUwl8W6J0f .task1,#mermaid-svg-DEUFBhZUwl8W6J0f .task2,#mermaid-svg-DEUFBhZUwl8W6J0f .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-DEUFBhZUwl8W6J0f .taskTextOutside0,#mermaid-svg-DEUFBhZUwl8W6J0f .taskTextOutside2{fill:#000}#mermaid-svg-DEUFBhZUwl8W6J0f .taskTextOutside1,#mermaid-svg-DEUFBhZUwl8W6J0f .taskTextOutside3{fill:#000}#mermaid-svg-DEUFBhZUwl8W6J0f .active0,#mermaid-svg-DEUFBhZUwl8W6J0f .active1,#mermaid-svg-DEUFBhZUwl8W6J0f .active2,#mermaid-svg-DEUFBhZUwl8W6J0f .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-DEUFBhZUwl8W6J0f .activeText0,#mermaid-svg-DEUFBhZUwl8W6J0f .activeText1,#mermaid-svg-DEUFBhZUwl8W6J0f .activeText2,#mermaid-svg-DEUFBhZUwl8W6J0f .activeText3{fill:#000 !important}#mermaid-svg-DEUFBhZUwl8W6J0f .done0,#mermaid-svg-DEUFBhZUwl8W6J0f .done1,#mermaid-svg-DEUFBhZUwl8W6J0f .done2,#mermaid-svg-DEUFBhZUwl8W6J0f .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-DEUFBhZUwl8W6J0f .doneText0,#mermaid-svg-DEUFBhZUwl8W6J0f .doneText1,#mermaid-svg-DEUFBhZUwl8W6J0f .doneText2,#mermaid-svg-DEUFBhZUwl8W6J0f .doneText3{fill:#000 !important}#mermaid-svg-DEUFBhZUwl8W6J0f .crit0,#mermaid-svg-DEUFBhZUwl8W6J0f .crit1,#mermaid-svg-DEUFBhZUwl8W6J0f .crit2,#mermaid-svg-DEUFBhZUwl8W6J0f .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-DEUFBhZUwl8W6J0f .activeCrit0,#mermaid-svg-DEUFBhZUwl8W6J0f .activeCrit1,#mermaid-svg-DEUFBhZUwl8W6J0f .activeCrit2,#mermaid-svg-DEUFBhZUwl8W6J0f .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-DEUFBhZUwl8W6J0f .doneCrit0,#mermaid-svg-DEUFBhZUwl8W6J0f .doneCrit1,#mermaid-svg-DEUFBhZUwl8W6J0f .doneCrit2,#mermaid-svg-DEUFBhZUwl8W6J0f .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-DEUFBhZUwl8W6J0f .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-DEUFBhZUwl8W6J0f .milestoneText{font-style:italic}#mermaid-svg-DEUFBhZUwl8W6J0f .doneCritText0,#mermaid-svg-DEUFBhZUwl8W6J0f .doneCritText1,#mermaid-svg-DEUFBhZUwl8W6J0f .doneCritText2,#mermaid-svg-DEUFBhZUwl8W6J0f .doneCritText3{fill:#000 !important}#mermaid-svg-DEUFBhZUwl8W6J0f .activeCritText0,#mermaid-svg-DEUFBhZUwl8W6J0f .activeCritText1,#mermaid-svg-DEUFBhZUwl8W6J0f .activeCritText2,#mermaid-svg-DEUFBhZUwl8W6J0f .activeCritText3{fill:#000 !important}#mermaid-svg-DEUFBhZUwl8W6J0f .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-DEUFBhZUwl8W6J0f g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-DEUFBhZUwl8W6J0f g.classGroup text .title{font-weight:bolder}#mermaid-svg-DEUFBhZUwl8W6J0f g.clickable{cursor:pointer}#mermaid-svg-DEUFBhZUwl8W6J0f g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-DEUFBhZUwl8W6J0f g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-DEUFBhZUwl8W6J0f .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-DEUFBhZUwl8W6J0f .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-DEUFBhZUwl8W6J0f .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-DEUFBhZUwl8W6J0f .dashed-line{stroke-dasharray:3}#mermaid-svg-DEUFBhZUwl8W6J0f #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-DEUFBhZUwl8W6J0f #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-DEUFBhZUwl8W6J0f #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-DEUFBhZUwl8W6J0f #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-DEUFBhZUwl8W6J0f #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-DEUFBhZUwl8W6J0f #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-DEUFBhZUwl8W6J0f #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-DEUFBhZUwl8W6J0f #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-DEUFBhZUwl8W6J0f .commit-id,#mermaid-svg-DEUFBhZUwl8W6J0f .commit-msg,#mermaid-svg-DEUFBhZUwl8W6J0f .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-DEUFBhZUwl8W6J0f .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-DEUFBhZUwl8W6J0f .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-DEUFBhZUwl8W6J0f g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-DEUFBhZUwl8W6J0f g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-DEUFBhZUwl8W6J0f g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-DEUFBhZUwl8W6J0f g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-DEUFBhZUwl8W6J0f g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-DEUFBhZUwl8W6J0f g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-DEUFBhZUwl8W6J0f .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-DEUFBhZUwl8W6J0f .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-DEUFBhZUwl8W6J0f .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-DEUFBhZUwl8W6J0f .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-DEUFBhZUwl8W6J0f .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-DEUFBhZUwl8W6J0f .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-DEUFBhZUwl8W6J0f .edgeLabel text{fill:#333}#mermaid-svg-DEUFBhZUwl8W6J0f .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-DEUFBhZUwl8W6J0f .node circle.state-start{fill:black;stroke:black}#mermaid-svg-DEUFBhZUwl8W6J0f .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-DEUFBhZUwl8W6J0f #statediagram-barbEnd{fill:#9370db}#mermaid-svg-DEUFBhZUwl8W6J0f .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-DEUFBhZUwl8W6J0f .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-DEUFBhZUwl8W6J0f .statediagram-state .divider{stroke:#9370db}#mermaid-svg-DEUFBhZUwl8W6J0f .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-DEUFBhZUwl8W6J0f .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-DEUFBhZUwl8W6J0f .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-DEUFBhZUwl8W6J0f .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-DEUFBhZUwl8W6J0f .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-DEUFBhZUwl8W6J0f .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-DEUFBhZUwl8W6J0f .note-edge{stroke-dasharray:5}#mermaid-svg-DEUFBhZUwl8W6J0f .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-DEUFBhZUwl8W6J0f .error-icon{fill:#522}#mermaid-svg-DEUFBhZUwl8W6J0f .error-text{fill:#522;stroke:#522}#mermaid-svg-DEUFBhZUwl8W6J0f .edge-thickness-normal{stroke-width:2px}#mermaid-svg-DEUFBhZUwl8W6J0f .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-DEUFBhZUwl8W6J0f .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-DEUFBhZUwl8W6J0f .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-DEUFBhZUwl8W6J0f .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-DEUFBhZUwl8W6J0f .marker{fill:#333}#mermaid-svg-DEUFBhZUwl8W6J0f .marker.cross{stroke:#333}
:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}</style>
<style>#mermaid-svg-DEUFBhZUwl8W6J0f {
color: rgba(0, 0, 0, 0.75);
font: ;
}</style>
取一種字體
取一個角度
取一個字符
再來一次
再來一次
再來一次
字體庫
角度庫
字符庫
寫到圖片上
如果代碼你運行的沒有問題,最侄訓生成如下結果:
好了,資料準備好了,總共15個檔案夾,每個檔案夾下對應的各種字體各種傾斜角的字符圖片3900個(字符15類×字體13種×角度20個),圖片的大小是24×24 像素,
有了資料 ,我們就可以再進行下一步了,下一步是訓練 和使用 資料,
2.2 訓練資料
2.2.1 構建模型
你先看代碼,外行感覺好深奧,內行偷偷地笑,
# %% 匯入必要的包
import tensorflow as tf
import numpy as np
from tensorflow. keras import layers
from tensorflow. keras. models import Sequential
import pathlib
import cv2
# %% 構建模型
def create_model ( ) :
model = Sequential( [
layers. experimental. preprocessing. Rescaling( 1 . / 255 , input_shape= ( 24 , 24 , 1 ) ) ,
layers. Conv2D( 24 , 3 , activation= 'relu' ) ,
layers. MaxPooling2D( ( 2 , 2 ) ) ,
layers. Conv2D( 64 , 3 , activation= 'relu' ) ,
layers. MaxPooling2D( ( 2 , 2 ) ) ,
layers. Flatten( ) ,
layers. Dense( 128 , activation= 'relu' ) ,
layers. Dense( 15 ) ]
)
model. compile ( optimizer= 'adam' ,
loss= tf. keras. losses. SparseCategoricalCrossentropy( from_logits= True ) ,
metrics= [ 'accuracy' ] )
return model
這個模型的序列是下面這樣的,作用是輸入一個圖片資料,經過各個層揉搓,最終預測出這個圖片屬于哪個分類,
<style>#mermaid-svg-OwCeohPhZpAeMseo .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-OwCeohPhZpAeMseo .label text{fill:#333}#mermaid-svg-OwCeohPhZpAeMseo .node rect,#mermaid-svg-OwCeohPhZpAeMseo .node circle,#mermaid-svg-OwCeohPhZpAeMseo .node ellipse,#mermaid-svg-OwCeohPhZpAeMseo .node polygon,#mermaid-svg-OwCeohPhZpAeMseo .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-OwCeohPhZpAeMseo .node .label{text-align:center;fill:#333}#mermaid-svg-OwCeohPhZpAeMseo .node.clickable{cursor:pointer}#mermaid-svg-OwCeohPhZpAeMseo .arrowheadPath{fill:#333}#mermaid-svg-OwCeohPhZpAeMseo .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-OwCeohPhZpAeMseo .flowchart-link{stroke:#333;fill:none}#mermaid-svg-OwCeohPhZpAeMseo .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-OwCeohPhZpAeMseo .edgeLabel rect{opacity:0.9}#mermaid-svg-OwCeohPhZpAeMseo .edgeLabel span{color:#333}#mermaid-svg-OwCeohPhZpAeMseo .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-OwCeohPhZpAeMseo .cluster text{fill:#333}#mermaid-svg-OwCeohPhZpAeMseo div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-OwCeohPhZpAeMseo .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-OwCeohPhZpAeMseo text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-OwCeohPhZpAeMseo .actor-line{stroke:grey}#mermaid-svg-OwCeohPhZpAeMseo .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-OwCeohPhZpAeMseo .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-OwCeohPhZpAeMseo #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-OwCeohPhZpAeMseo .sequenceNumber{fill:#fff}#mermaid-svg-OwCeohPhZpAeMseo #sequencenumber{fill:#333}#mermaid-svg-OwCeohPhZpAeMseo #crosshead path{fill:#333;stroke:#333}#mermaid-svg-OwCeohPhZpAeMseo .messageText{fill:#333;stroke:#333}#mermaid-svg-OwCeohPhZpAeMseo .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-OwCeohPhZpAeMseo .labelText,#mermaid-svg-OwCeohPhZpAeMseo .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-OwCeohPhZpAeMseo .loopText,#mermaid-svg-OwCeohPhZpAeMseo .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-OwCeohPhZpAeMseo .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-OwCeohPhZpAeMseo .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-OwCeohPhZpAeMseo .noteText,#mermaid-svg-OwCeohPhZpAeMseo .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-OwCeohPhZpAeMseo .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-OwCeohPhZpAeMseo .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-OwCeohPhZpAeMseo .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-OwCeohPhZpAeMseo .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-OwCeohPhZpAeMseo .section{stroke:none;opacity:0.2}#mermaid-svg-OwCeohPhZpAeMseo .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-OwCeohPhZpAeMseo .section2{fill:#fff400}#mermaid-svg-OwCeohPhZpAeMseo .section1,#mermaid-svg-OwCeohPhZpAeMseo .section3{fill:#fff;opacity:0.2}#mermaid-svg-OwCeohPhZpAeMseo .sectionTitle0{fill:#333}#mermaid-svg-OwCeohPhZpAeMseo .sectionTitle1{fill:#333}#mermaid-svg-OwCeohPhZpAeMseo .sectionTitle2{fill:#333}#mermaid-svg-OwCeohPhZpAeMseo .sectionTitle3{fill:#333}#mermaid-svg-OwCeohPhZpAeMseo .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-OwCeohPhZpAeMseo .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-OwCeohPhZpAeMseo .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-OwCeohPhZpAeMseo .grid path{stroke-width:0}#mermaid-svg-OwCeohPhZpAeMseo .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-OwCeohPhZpAeMseo .task{stroke-width:2}#mermaid-svg-OwCeohPhZpAeMseo .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-OwCeohPhZpAeMseo .taskText:not([font-size]){font-size:11px}#mermaid-svg-OwCeohPhZpAeMseo .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-OwCeohPhZpAeMseo .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-OwCeohPhZpAeMseo .task.clickable{cursor:pointer}#mermaid-svg-OwCeohPhZpAeMseo .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-OwCeohPhZpAeMseo .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-OwCeohPhZpAeMseo .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-OwCeohPhZpAeMseo .taskText0,#mermaid-svg-OwCeohPhZpAeMseo .taskText1,#mermaid-svg-OwCeohPhZpAeMseo .taskText2,#mermaid-svg-OwCeohPhZpAeMseo .taskText3{fill:#fff}#mermaid-svg-OwCeohPhZpAeMseo .task0,#mermaid-svg-OwCeohPhZpAeMseo .task1,#mermaid-svg-OwCeohPhZpAeMseo .task2,#mermaid-svg-OwCeohPhZpAeMseo .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-OwCeohPhZpAeMseo .taskTextOutside0,#mermaid-svg-OwCeohPhZpAeMseo .taskTextOutside2{fill:#000}#mermaid-svg-OwCeohPhZpAeMseo .taskTextOutside1,#mermaid-svg-OwCeohPhZpAeMseo .taskTextOutside3{fill:#000}#mermaid-svg-OwCeohPhZpAeMseo .active0,#mermaid-svg-OwCeohPhZpAeMseo .active1,#mermaid-svg-OwCeohPhZpAeMseo .active2,#mermaid-svg-OwCeohPhZpAeMseo .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-OwCeohPhZpAeMseo .activeText0,#mermaid-svg-OwCeohPhZpAeMseo .activeText1,#mermaid-svg-OwCeohPhZpAeMseo .activeText2,#mermaid-svg-OwCeohPhZpAeMseo .activeText3{fill:#000 !important}#mermaid-svg-OwCeohPhZpAeMseo .done0,#mermaid-svg-OwCeohPhZpAeMseo .done1,#mermaid-svg-OwCeohPhZpAeMseo .done2,#mermaid-svg-OwCeohPhZpAeMseo .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-OwCeohPhZpAeMseo .doneText0,#mermaid-svg-OwCeohPhZpAeMseo .doneText1,#mermaid-svg-OwCeohPhZpAeMseo .doneText2,#mermaid-svg-OwCeohPhZpAeMseo .doneText3{fill:#000 !important}#mermaid-svg-OwCeohPhZpAeMseo .crit0,#mermaid-svg-OwCeohPhZpAeMseo .crit1,#mermaid-svg-OwCeohPhZpAeMseo .crit2,#mermaid-svg-OwCeohPhZpAeMseo .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-OwCeohPhZpAeMseo .activeCrit0,#mermaid-svg-OwCeohPhZpAeMseo .activeCrit1,#mermaid-svg-OwCeohPhZpAeMseo .activeCrit2,#mermaid-svg-OwCeohPhZpAeMseo .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-OwCeohPhZpAeMseo .doneCrit0,#mermaid-svg-OwCeohPhZpAeMseo .doneCrit1,#mermaid-svg-OwCeohPhZpAeMseo .doneCrit2,#mermaid-svg-OwCeohPhZpAeMseo .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-OwCeohPhZpAeMseo .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-OwCeohPhZpAeMseo .milestoneText{font-style:italic}#mermaid-svg-OwCeohPhZpAeMseo .doneCritText0,#mermaid-svg-OwCeohPhZpAeMseo .doneCritText1,#mermaid-svg-OwCeohPhZpAeMseo .doneCritText2,#mermaid-svg-OwCeohPhZpAeMseo .doneCritText3{fill:#000 !important}#mermaid-svg-OwCeohPhZpAeMseo .activeCritText0,#mermaid-svg-OwCeohPhZpAeMseo .activeCritText1,#mermaid-svg-OwCeohPhZpAeMseo .activeCritText2,#mermaid-svg-OwCeohPhZpAeMseo .activeCritText3{fill:#000 !important}#mermaid-svg-OwCeohPhZpAeMseo .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-OwCeohPhZpAeMseo g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-OwCeohPhZpAeMseo g.classGroup text .title{font-weight:bolder}#mermaid-svg-OwCeohPhZpAeMseo g.clickable{cursor:pointer}#mermaid-svg-OwCeohPhZpAeMseo g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-OwCeohPhZpAeMseo g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-OwCeohPhZpAeMseo .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-OwCeohPhZpAeMseo .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-OwCeohPhZpAeMseo .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-OwCeohPhZpAeMseo .dashed-line{stroke-dasharray:3}#mermaid-svg-OwCeohPhZpAeMseo #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-OwCeohPhZpAeMseo #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-OwCeohPhZpAeMseo #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-OwCeohPhZpAeMseo #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-OwCeohPhZpAeMseo #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-OwCeohPhZpAeMseo #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-OwCeohPhZpAeMseo #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-OwCeohPhZpAeMseo #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-OwCeohPhZpAeMseo .commit-id,#mermaid-svg-OwCeohPhZpAeMseo .commit-msg,#mermaid-svg-OwCeohPhZpAeMseo .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-OwCeohPhZpAeMseo .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-OwCeohPhZpAeMseo .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-OwCeohPhZpAeMseo g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-OwCeohPhZpAeMseo g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-OwCeohPhZpAeMseo g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-OwCeohPhZpAeMseo g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-OwCeohPhZpAeMseo g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-OwCeohPhZpAeMseo g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-OwCeohPhZpAeMseo .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-OwCeohPhZpAeMseo .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-OwCeohPhZpAeMseo .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-OwCeohPhZpAeMseo .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-OwCeohPhZpAeMseo .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-OwCeohPhZpAeMseo .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-OwCeohPhZpAeMseo .edgeLabel text{fill:#333}#mermaid-svg-OwCeohPhZpAeMseo .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-OwCeohPhZpAeMseo .node circle.state-start{fill:black;stroke:black}#mermaid-svg-OwCeohPhZpAeMseo .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-OwCeohPhZpAeMseo #statediagram-barbEnd{fill:#9370db}#mermaid-svg-OwCeohPhZpAeMseo .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-OwCeohPhZpAeMseo .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-OwCeohPhZpAeMseo .statediagram-state .divider{stroke:#9370db}#mermaid-svg-OwCeohPhZpAeMseo .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-OwCeohPhZpAeMseo .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-OwCeohPhZpAeMseo .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-OwCeohPhZpAeMseo .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-OwCeohPhZpAeMseo .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-OwCeohPhZpAeMseo .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-OwCeohPhZpAeMseo .note-edge{stroke-dasharray:5}#mermaid-svg-OwCeohPhZpAeMseo .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-OwCeohPhZpAeMseo .error-icon{fill:#522}#mermaid-svg-OwCeohPhZpAeMseo .error-text{fill:#522;stroke:#522}#mermaid-svg-OwCeohPhZpAeMseo .edge-thickness-normal{stroke-width:2px}#mermaid-svg-OwCeohPhZpAeMseo .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-OwCeohPhZpAeMseo .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-OwCeohPhZpAeMseo .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-OwCeohPhZpAeMseo .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-OwCeohPhZpAeMseo .marker{fill:#333}#mermaid-svg-OwCeohPhZpAeMseo .marker.cross{stroke:#333}
:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}</style>
<style>#mermaid-svg-OwCeohPhZpAeMseo {
color: rgba(0, 0, 0, 0.75);
font: ;
}</style>
輸入: 圖片24*24像素
卷積層1 Conv2D
池化層1 MaxPooling2D
卷積層2 Conv2D
池化層2 MaxPooling2D
全連接層1 Dense 128
全連接層2 Dense 15
0: 30%
1: 20%
2: 0.5%
...
=: 1%
這么多層都是干什么的,有什么用?和衣服一樣,肯定是有用的,內衣、襯衣、毛衣、棉衣各有各的用處,
2.2.2 卷積層 Conv2D
各個職能部門的調查員,搜集和整理某單位區域內的特定資料, 我們輸入的是一個影像,它是由像素組成的,這就是
R
e
s
c
a
l
i
n
g
(
1.
/
255
,
i
n
p
u
t
s
h
a
p
e
=
(
24
,
24
,
1
)
)
Rescaling(1./255, input_shape=(24, 24, 1))
R e s c a l i n g ( 1 . / 2 5 5 , i n p u t s ? h a p e = ( 2 4 , 2 4 , 1 ) ) 中,input_shape輸入形狀是24*24像素1個通道(彩色是RGB 3個通道)的影像,
卷積層代碼中的定義是Conv2D(24,3),意思是用3*3像素的卷積核,去提取24個特征,
我把圖轉到地圖上來,你就能理解了,以我大濟南的市中區為例子,
卷積的作用就相當于從地圖的某級單位區域中收集多組特定資訊,比如以小區為單位去提取住宅數量、車位數量、學校數量、人口數、年收入、學歷、年齡等等24個維度的資訊,小區相當于卷積核,
提取完成之后是這樣的,
第一次卷積之后,我們從市中區得到N個小區的資料,
卷積是可以進行多次的,
比如在小區卷積之后,我們還可在小區的基礎上再來一次卷積,在卷積就是街道了,
通過再次以街道為單位卷積小區,我們就從市中區得到了N個街道的資料,
這就是卷積的作用,
通過一次次卷積,就把一張大圖,通過特定的方法卷起來,最終留下來的是固定幾組有目的資料,以此方便后續的評選決策,這是評選一個區的資料,要是評選濟南市,甚至山東省,也是這么卷積,這和現實生活中評選文明城市、經濟強省也是一個道理,
2.2.3 池化層 MaxPooling2D
說白了就是四舍五入,
計算機的計算能力是強大的,比你我快,但也不是不用考慮成本,我們當然希望它越快越好,如果一個方法能省一半的時間,我們肯定愿意用這種方法,
池化層干的就是這個事情, 池化的代碼定義是這樣的
M
a
x
P
o
o
l
i
n
g
2
D
(
(
2
,
2
)
)
MaxPooling2D((2,2))
M a x P o o l i n g 2 D ( ( 2 , 2 ) ) ,這里是最大值池化,其中(2,2)是池化層的大小,其實就是在2*2的區域內,我們認為這一片可以合成一個單位,
再以地圖舉個例子,比如下面的16個格子里的資料,是16個街道的學校數量,
為了進一步提高計算效率,少計算一些資料,我們用2*2的池化層進行池化,
池化的方格是4個街道合成1個,新單位學校數量取成員中學校數量最大(也有取最小,取平均多種池化)的那一個,池化之后,16個格子就變為了4個格子,從而減少了資料,
這就是池化層的作用,
2.2.4 全連接層 Dense
弱水三千,只取一瓢,
在這里,它其實是一個分類器,
我們構建它時,代碼是這樣的
D
e
n
s
e
(
15
)
Dense(15)
D e n s e ( 1 5 ) ,
它所做的事情,不管你前面是怎么樣,有多少維度,到我這里我要強行轉化為固定的通道,
比如識別字母a~z,我有500個神經元參與判斷,但是最終輸出結果就是26個通道(a,b,c,……,y,z),
我們這里總共有15類字符,所以是15個通道,給定一個輸入后,輸出為每個分類的概率,
<style>#mermaid-svg-KOlq3k9O6H0Pw6m3 .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 .label text{fill:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 .node rect,#mermaid-svg-KOlq3k9O6H0Pw6m3 .node circle,#mermaid-svg-KOlq3k9O6H0Pw6m3 .node ellipse,#mermaid-svg-KOlq3k9O6H0Pw6m3 .node polygon,#mermaid-svg-KOlq3k9O6H0Pw6m3 .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-KOlq3k9O6H0Pw6m3 .node .label{text-align:center;fill:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 .node.clickable{cursor:pointer}#mermaid-svg-KOlq3k9O6H0Pw6m3 .arrowheadPath{fill:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-KOlq3k9O6H0Pw6m3 .flowchart-link{stroke:#333;fill:none}#mermaid-svg-KOlq3k9O6H0Pw6m3 .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-KOlq3k9O6H0Pw6m3 .edgeLabel rect{opacity:0.9}#mermaid-svg-KOlq3k9O6H0Pw6m3 .edgeLabel span{color:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-KOlq3k9O6H0Pw6m3 .cluster text{fill:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-KOlq3k9O6H0Pw6m3 .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-KOlq3k9O6H0Pw6m3 text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-KOlq3k9O6H0Pw6m3 .actor-line{stroke:grey}#mermaid-svg-KOlq3k9O6H0Pw6m3 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 .sequenceNumber{fill:#fff}#mermaid-svg-KOlq3k9O6H0Pw6m3 #sequencenumber{fill:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 #crosshead path{fill:#333;stroke:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 .messageText{fill:#333;stroke:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-KOlq3k9O6H0Pw6m3 .labelText,#mermaid-svg-KOlq3k9O6H0Pw6m3 .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-KOlq3k9O6H0Pw6m3 .loopText,#mermaid-svg-KOlq3k9O6H0Pw6m3 .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-KOlq3k9O6H0Pw6m3 .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-KOlq3k9O6H0Pw6m3 .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-KOlq3k9O6H0Pw6m3 .noteText,#mermaid-svg-KOlq3k9O6H0Pw6m3 .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-KOlq3k9O6H0Pw6m3 .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-KOlq3k9O6H0Pw6m3 .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-KOlq3k9O6H0Pw6m3 .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-KOlq3k9O6H0Pw6m3 .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-KOlq3k9O6H0Pw6m3 .section{stroke:none;opacity:0.2}#mermaid-svg-KOlq3k9O6H0Pw6m3 .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-KOlq3k9O6H0Pw6m3 .section2{fill:#fff400}#mermaid-svg-KOlq3k9O6H0Pw6m3 .section1,#mermaid-svg-KOlq3k9O6H0Pw6m3 .section3{fill:#fff;opacity:0.2}#mermaid-svg-KOlq3k9O6H0Pw6m3 .sectionTitle0{fill:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 .sectionTitle1{fill:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 .sectionTitle2{fill:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 .sectionTitle3{fill:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-KOlq3k9O6H0Pw6m3 .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-KOlq3k9O6H0Pw6m3 .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-KOlq3k9O6H0Pw6m3 .grid path{stroke-width:0}#mermaid-svg-KOlq3k9O6H0Pw6m3 .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-KOlq3k9O6H0Pw6m3 .task{stroke-width:2}#mermaid-svg-KOlq3k9O6H0Pw6m3 .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-KOlq3k9O6H0Pw6m3 .taskText:not([font-size]){font-size:11px}#mermaid-svg-KOlq3k9O6H0Pw6m3 .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-KOlq3k9O6H0Pw6m3 .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-KOlq3k9O6H0Pw6m3 .task.clickable{cursor:pointer}#mermaid-svg-KOlq3k9O6H0Pw6m3 .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-KOlq3k9O6H0Pw6m3 .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-KOlq3k9O6H0Pw6m3 .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-KOlq3k9O6H0Pw6m3 .taskText0,#mermaid-svg-KOlq3k9O6H0Pw6m3 .taskText1,#mermaid-svg-KOlq3k9O6H0Pw6m3 .taskText2,#mermaid-svg-KOlq3k9O6H0Pw6m3 .taskText3{fill:#fff}#mermaid-svg-KOlq3k9O6H0Pw6m3 .task0,#mermaid-svg-KOlq3k9O6H0Pw6m3 .task1,#mermaid-svg-KOlq3k9O6H0Pw6m3 .task2,#mermaid-svg-KOlq3k9O6H0Pw6m3 .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-KOlq3k9O6H0Pw6m3 .taskTextOutside0,#mermaid-svg-KOlq3k9O6H0Pw6m3 .taskTextOutside2{fill:#000}#mermaid-svg-KOlq3k9O6H0Pw6m3 .taskTextOutside1,#mermaid-svg-KOlq3k9O6H0Pw6m3 .taskTextOutside3{fill:#000}#mermaid-svg-KOlq3k9O6H0Pw6m3 .active0,#mermaid-svg-KOlq3k9O6H0Pw6m3 .active1,#mermaid-svg-KOlq3k9O6H0Pw6m3 .active2,#mermaid-svg-KOlq3k9O6H0Pw6m3 .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-KOlq3k9O6H0Pw6m3 .activeText0,#mermaid-svg-KOlq3k9O6H0Pw6m3 .activeText1,#mermaid-svg-KOlq3k9O6H0Pw6m3 .activeText2,#mermaid-svg-KOlq3k9O6H0Pw6m3 .activeText3{fill:#000 !important}#mermaid-svg-KOlq3k9O6H0Pw6m3 .done0,#mermaid-svg-KOlq3k9O6H0Pw6m3 .done1,#mermaid-svg-KOlq3k9O6H0Pw6m3 .done2,#mermaid-svg-KOlq3k9O6H0Pw6m3 .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-KOlq3k9O6H0Pw6m3 .doneText0,#mermaid-svg-KOlq3k9O6H0Pw6m3 .doneText1,#mermaid-svg-KOlq3k9O6H0Pw6m3 .doneText2,#mermaid-svg-KOlq3k9O6H0Pw6m3 .doneText3{fill:#000 !important}#mermaid-svg-KOlq3k9O6H0Pw6m3 .crit0,#mermaid-svg-KOlq3k9O6H0Pw6m3 .crit1,#mermaid-svg-KOlq3k9O6H0Pw6m3 .crit2,#mermaid-svg-KOlq3k9O6H0Pw6m3 .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-KOlq3k9O6H0Pw6m3 .activeCrit0,#mermaid-svg-KOlq3k9O6H0Pw6m3 .activeCrit1,#mermaid-svg-KOlq3k9O6H0Pw6m3 .activeCrit2,#mermaid-svg-KOlq3k9O6H0Pw6m3 .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-KOlq3k9O6H0Pw6m3 .doneCrit0,#mermaid-svg-KOlq3k9O6H0Pw6m3 .doneCrit1,#mermaid-svg-KOlq3k9O6H0Pw6m3 .doneCrit2,#mermaid-svg-KOlq3k9O6H0Pw6m3 .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-KOlq3k9O6H0Pw6m3 .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-KOlq3k9O6H0Pw6m3 .milestoneText{font-style:italic}#mermaid-svg-KOlq3k9O6H0Pw6m3 .doneCritText0,#mermaid-svg-KOlq3k9O6H0Pw6m3 .doneCritText1,#mermaid-svg-KOlq3k9O6H0Pw6m3 .doneCritText2,#mermaid-svg-KOlq3k9O6H0Pw6m3 .doneCritText3{fill:#000 !important}#mermaid-svg-KOlq3k9O6H0Pw6m3 .activeCritText0,#mermaid-svg-KOlq3k9O6H0Pw6m3 .activeCritText1,#mermaid-svg-KOlq3k9O6H0Pw6m3 .activeCritText2,#mermaid-svg-KOlq3k9O6H0Pw6m3 .activeCritText3{fill:#000 !important}#mermaid-svg-KOlq3k9O6H0Pw6m3 .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-KOlq3k9O6H0Pw6m3 g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-KOlq3k9O6H0Pw6m3 g.classGroup text .title{font-weight:bolder}#mermaid-svg-KOlq3k9O6H0Pw6m3 g.clickable{cursor:pointer}#mermaid-svg-KOlq3k9O6H0Pw6m3 g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-KOlq3k9O6H0Pw6m3 g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-KOlq3k9O6H0Pw6m3 .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-KOlq3k9O6H0Pw6m3 .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-KOlq3k9O6H0Pw6m3 .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-KOlq3k9O6H0Pw6m3 .dashed-line{stroke-dasharray:3}#mermaid-svg-KOlq3k9O6H0Pw6m3 #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-KOlq3k9O6H0Pw6m3 #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-KOlq3k9O6H0Pw6m3 #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-KOlq3k9O6H0Pw6m3 #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-KOlq3k9O6H0Pw6m3 #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-KOlq3k9O6H0Pw6m3 #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-KOlq3k9O6H0Pw6m3 #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-KOlq3k9O6H0Pw6m3 #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-KOlq3k9O6H0Pw6m3 .commit-id,#mermaid-svg-KOlq3k9O6H0Pw6m3 .commit-msg,#mermaid-svg-KOlq3k9O6H0Pw6m3 .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-KOlq3k9O6H0Pw6m3 .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-KOlq3k9O6H0Pw6m3 .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-KOlq3k9O6H0Pw6m3 g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-KOlq3k9O6H0Pw6m3 g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-KOlq3k9O6H0Pw6m3 g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-KOlq3k9O6H0Pw6m3 g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-KOlq3k9O6H0Pw6m3 g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-KOlq3k9O6H0Pw6m3 .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-KOlq3k9O6H0Pw6m3 .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-KOlq3k9O6H0Pw6m3 .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-KOlq3k9O6H0Pw6m3 .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-KOlq3k9O6H0Pw6m3 .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-KOlq3k9O6H0Pw6m3 .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-KOlq3k9O6H0Pw6m3 .edgeLabel text{fill:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-KOlq3k9O6H0Pw6m3 .node circle.state-start{fill:black;stroke:black}#mermaid-svg-KOlq3k9O6H0Pw6m3 .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-KOlq3k9O6H0Pw6m3 #statediagram-barbEnd{fill:#9370db}#mermaid-svg-KOlq3k9O6H0Pw6m3 .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-KOlq3k9O6H0Pw6m3 .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-KOlq3k9O6H0Pw6m3 .statediagram-state .divider{stroke:#9370db}#mermaid-svg-KOlq3k9O6H0Pw6m3 .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-KOlq3k9O6H0Pw6m3 .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-KOlq3k9O6H0Pw6m3 .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-KOlq3k9O6H0Pw6m3 .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-KOlq3k9O6H0Pw6m3 .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-KOlq3k9O6H0Pw6m3 .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-KOlq3k9O6H0Pw6m3 .note-edge{stroke-dasharray:5}#mermaid-svg-KOlq3k9O6H0Pw6m3 .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-KOlq3k9O6H0Pw6m3 .error-icon{fill:#522}#mermaid-svg-KOlq3k9O6H0Pw6m3 .error-text{fill:#522;stroke:#522}#mermaid-svg-KOlq3k9O6H0Pw6m3 .edge-thickness-normal{stroke-width:2px}#mermaid-svg-KOlq3k9O6H0Pw6m3 .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-KOlq3k9O6H0Pw6m3 .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-KOlq3k9O6H0Pw6m3 .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-KOlq3k9O6H0Pw6m3 .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-KOlq3k9O6H0Pw6m3 .marker{fill:#333}#mermaid-svg-KOlq3k9O6H0Pw6m3 .marker.cross{stroke:#333}
:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}</style>
<style>#mermaid-svg-KOlq3k9O6H0Pw6m3 {
color: rgba(0, 0, 0, 0.75);
font: ;
}</style>
其他型別的層
全連接層1 Dense 128
1
全連接層2 Dense 15
2
3
4
5
...
127
128
1: 30%
2: 20%
3: 0.5%
...
15: 1%
注意:上面都是二維的輸入,比如24×24,但是全連接層是一維的,所以代碼中使用了
l
a
y
e
r
s
.
F
l
a
t
t
e
n
(
)
layers.Flatten()
l a y e r s . F l a t t e n ( ) 將二維資料拉平為一維資料([[11,12],[21,22]]->[11,12,21,22]),
對于總體的模型,呼叫
m
o
d
e
l
.
s
u
m
m
a
r
y
(
)
model.summary()
m o d e l . s u m m a r y ( ) 列印序列的網路結構如下:
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
rescaling_2 (Rescaling) (None, 24, 24, 1) 0
_________________________________________________________________
conv2d_4 (Conv2D) (None, 22, 22, 24) 240
_________________________________________________________________
max_pooling2d_4 (MaxPooling2 (None, 11, 11, 24) 0
_________________________________________________________________
conv2d_5 (Conv2D) (None, 9, 9, 64) 13888
_________________________________________________________________
max_pooling2d_5 (MaxPooling2 (None, 4, 4, 64) 0
_________________________________________________________________
flatten_2 (Flatten) (None, 1024) 0
_________________________________________________________________
dense_4 (Dense) (None, 128) 131200
_________________________________________________________________
dense_5 (Dense) (None, 15) 1935
=================================================================
Total params: 147,263
Trainable params: 147,263
Non-trainable params: 0
_________________________________________________________________
我們看到conv2d_5 (Conv2D) (None, 9, 9, 64) 經過2*2的池化之后變為max_pooling2d_5 (MaxPooling2 (None, 4, 4, 64),(None, 4, 4, 64) 再經過
F
l
a
t
t
e
n
Flatten
F l a t t e n 拉成一維之后變為(None, 1024),經過全連接變為(None, 128)再一次全連接變為(None, 15),15就是我們的最終分類,這一切都是我們設計的,
m
o
d
e
l
.
c
o
m
p
i
l
e
model.compile
m o d e l . c o m p i l e 就是配置模型的幾個引數,這個現階段記住就可以,
2.2.5 訓練資料
執行就完了,
# 統計檔案夾下的所有圖片數量
data_dir = pathlib. Path( 'dataset' )
# 從檔案夾下讀取圖片,生成資料集
train_ds = tf. keras. preprocessing. image_dataset_from_directory(
data_dir, # 從哪個檔案獲取資料
color_mode= "grayscale" , # 獲取資料的顏色為灰度
image_size= ( 24 , 24 ) , # 圖片的大小尺寸
batch_size= 32 # 多少個圖片為一個批次
)
# 資料集的分類,對應dataset檔案夾下有多少圖片分類
class_names = train_ds. class_names
# 保存資料集分類
np. save( "class_name.npy" , class_names)
# 資料集快取處理
AUTOTUNE = tf. data. experimental. AUTOTUNE
train_ds = train_ds. cache( ) . shuffle( 1000 ) . prefetch( buffer_size= AUTOTUNE)
# 創建模型
model = create_model( )
# 訓練模型,epochs=10,所有資料集訓練10遍
model. fit( train_ds, epochs= 10 )
# 保存訓練后的權重
model. save_weights( 'checkpoint/char_checkpoint' )
執行之后會輸出如下資訊:
Found 3900 files belonging to 15 classes.
Epoch 1/10 122/122 [=========] - 2s 19ms/step - loss: 0.5795 - accuracy: 0.8615
Epoch 2/10 122/122 [=========] - 2s 18ms/step - loss: 0.0100 - accuracy: 0.9992
Epoch 3/10 122/122 [=========] - 2s 19ms/step - loss: 0.0027 - accuracy: 1.0000
Epoch 4/10 122/122 [=========] - 2s 19ms/step - loss: 0.0013 - accuracy: 1.0000
Epoch 5/10 122/122 [=========] - 2s 20ms/step - loss: 8.4216e-04 - accuracy: 1.0000
Epoch 6/10 122/122 [=========] - 2s 18ms/step - loss: 5.5273e-04 - accuracy: 1.0000
Epoch 7/10 122/122 [=========] - 3s 21ms/step - loss: 4.0966e-04 - accuracy: 1.0000
Epoch 8/10 122/122 [=========] - 2s 20ms/step - loss: 3.0308e-04 - accuracy: 1.0000
Epoch 9/10 122/122 [=========] - 3s 23ms/step - loss: 2.3446e-04 - accuracy: 1.0000
Epoch 10/10 122/122 [=========] - 3s 21ms/step - loss: 1.8971e-04 - accuracy: 1.0000
我們看到,第3遍時候,準確率達到100%了, 最后結束的時候,我們發現檔案夾checkpoint下多了幾個檔案:
char_checkpoint.data-00000-of-00001
char_checkpoint.index
checkpoint
上面那幾個檔案是訓練結果,訓練保存之后就不用動了,后面可以直接用這些資料進行預測,
2.3 預測資料
終于到了享受成果的時候了,
# 設定待識別的圖片
img1= cv2. imread( 'img1.png' , 0 )
img2= cv2. imread( 'img2.png' , 0 )
imgs = np. array( [ img1, img2] )
# 構建模型
model = create_model( )
# 加載前期訓練好的權重
model. load_weights( 'checkpoint/char_checkpoint' )
# 讀出圖片分類
class_name = np. load( 'class_name.npy' )
# 預測圖片,獲取預測值
predicts = model. predict( imgs)
results = [ ] # 保存結果的陣列
for predict in predicts: #遍歷每一個預測結果
index = np. argmax( predict) # 尋找最大值
result = class_name[ index] # 取出字符
results. append( result)
print ( results)
我們找兩張圖片img1.png ,img2.png ,一張是數字6,一張是數字8,兩張圖放到代碼同級目錄下,驗證一下識別效果如何,
圖片要通過cv2.imread('img1.png',0) 轉化為二維陣列結構,0引數是灰度圖片,經過處理后,圖片轉成的陣列是如下所示(24,24)的結構:
我們要同時驗證兩張圖,所以把兩張圖再組成imgs放到一起,imgs的結構是(2,24,24),
下面是構建模型,然后加載權重,通過呼叫predicts = model.predict(imgs)將imgs傳遞給模型進行預測得出predicts,
predicts的結構是(2,15),數值如下面所示:
[[ 16.134243 -12.10675 -1.1994154 -27.766754 -43.4324 -9.633694 -12.214878 1.6287893 2.562174 3.2222707 13.834648 28.254173 -6.102874 16.76582 7.2586184] [ 5.022571 -8.762314 -6.7466817 -23.494259 -30.170597 2.4392672 -14.676962 5.8255725 8.855118 -2.0998626 6.820853 7.6578817 1.5132296 24.4664 2.4192357]]
意思是有2個預測結果,每一個圖片的預測結果有15種可能,
然后根據 index = np.argmax(predict) 找出最大可能的索引,
根據索引找到字符的數值結果是[‘6’, ‘8’],
下面是資料在記憶體中的監控:
可見,我們的預測是準確的,
下面,我們將要把圖片中數字切割 出來,進行識別 了,
之前我們準備了資料,訓練了資料,并且拿圖片進行了識別,識別結果正確,
到目前為止,看來問題不大……沒有大問題,有問題也大不了,
下面就是把圖片進行切割識別了,
下面這張大圖片,怎么把它搞一搞,搞成單個小數字的圖片,
2.4 切割影像
上帝說要有光,就有了光,
于是,當光投過來時,物體的背后就有了影,
我們就知道了,有影的地方就有東西,沒影的地方是空白,
這就是投影,
這個簡單的道理放在影像切割上也很實用,
我們把文字的像素做個投影,這樣我們就知道某個區間有沒有文字,并且知道這個區間文字是否集中,
下面是示意圖:
2.4.1 投影大法
最有效的方法,往往都是用回圈實作的,
要計算投影,就得一個像素一個像素地數,查看有幾個像素,然后記錄下這一行有N個像素點,如此回圈,
首先匯入包:
import numpy as np
import cv2
from PIL import Image, ImageDraw, ImageFont
import PIL
import matplotlib. pyplot as plt
import os
import shutil
from numpy. core. records import array
from numpy. core. shape_base import block
import time
比如說要看垂直方向的投影,代碼如下:
# 整幅圖片的Y軸投影,傳入圖片陣列,圖片經過二值化并反色
def img_y_shadow ( img_b) :
### 計算投影 ###
( h, w) = img_b. shape
# 初始化一個跟影像高一樣長度的陣列,用于記錄每一行的黑點個數
a= [ 0 for z in range ( 0 , h) ]
# 遍歷每一列,記錄下這一列包含多少有效像素點
for i in range ( 0 , h) :
for j in range ( 0 , w) :
if img_b[ i, j] == 255 :
a[ i] += 1
return a
最終得到是這樣的結構: [0, 79, 67, 50, 50, 50, 109, 137, 145, 136, 125, 117, 123, 124, 134, 71, 62, 68, 104, 102, 83, 14, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, ……38, 44, 56, 106, 97, 83, 0, 0, 0, 0, 0, 0, 0]表示第幾行總共有多少個像素點,第1行是0,表示是空白的白紙,第2行有79個像素點,
如果我們想要從視覺呈現出來怎么處理呢?那可以把它立起來拉直畫出來,
<style>#mermaid-svg-QK2WyvOlyH4KUSp0 .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 .label text{fill:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 .node rect,#mermaid-svg-QK2WyvOlyH4KUSp0 .node circle,#mermaid-svg-QK2WyvOlyH4KUSp0 .node ellipse,#mermaid-svg-QK2WyvOlyH4KUSp0 .node polygon,#mermaid-svg-QK2WyvOlyH4KUSp0 .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-QK2WyvOlyH4KUSp0 .node .label{text-align:center;fill:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 .node.clickable{cursor:pointer}#mermaid-svg-QK2WyvOlyH4KUSp0 .arrowheadPath{fill:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-QK2WyvOlyH4KUSp0 .flowchart-link{stroke:#333;fill:none}#mermaid-svg-QK2WyvOlyH4KUSp0 .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-QK2WyvOlyH4KUSp0 .edgeLabel rect{opacity:0.9}#mermaid-svg-QK2WyvOlyH4KUSp0 .edgeLabel span{color:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-QK2WyvOlyH4KUSp0 .cluster text{fill:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-QK2WyvOlyH4KUSp0 .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-QK2WyvOlyH4KUSp0 text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-QK2WyvOlyH4KUSp0 .actor-line{stroke:grey}#mermaid-svg-QK2WyvOlyH4KUSp0 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 .sequenceNumber{fill:#fff}#mermaid-svg-QK2WyvOlyH4KUSp0 #sequencenumber{fill:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 #crosshead path{fill:#333;stroke:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 .messageText{fill:#333;stroke:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-QK2WyvOlyH4KUSp0 .labelText,#mermaid-svg-QK2WyvOlyH4KUSp0 .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-QK2WyvOlyH4KUSp0 .loopText,#mermaid-svg-QK2WyvOlyH4KUSp0 .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-QK2WyvOlyH4KUSp0 .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-QK2WyvOlyH4KUSp0 .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-QK2WyvOlyH4KUSp0 .noteText,#mermaid-svg-QK2WyvOlyH4KUSp0 .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-QK2WyvOlyH4KUSp0 .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-QK2WyvOlyH4KUSp0 .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-QK2WyvOlyH4KUSp0 .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-QK2WyvOlyH4KUSp0 .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-QK2WyvOlyH4KUSp0 .section{stroke:none;opacity:0.2}#mermaid-svg-QK2WyvOlyH4KUSp0 .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-QK2WyvOlyH4KUSp0 .section2{fill:#fff400}#mermaid-svg-QK2WyvOlyH4KUSp0 .section1,#mermaid-svg-QK2WyvOlyH4KUSp0 .section3{fill:#fff;opacity:0.2}#mermaid-svg-QK2WyvOlyH4KUSp0 .sectionTitle0{fill:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 .sectionTitle1{fill:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 .sectionTitle2{fill:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 .sectionTitle3{fill:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-QK2WyvOlyH4KUSp0 .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-QK2WyvOlyH4KUSp0 .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-QK2WyvOlyH4KUSp0 .grid path{stroke-width:0}#mermaid-svg-QK2WyvOlyH4KUSp0 .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-QK2WyvOlyH4KUSp0 .task{stroke-width:2}#mermaid-svg-QK2WyvOlyH4KUSp0 .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-QK2WyvOlyH4KUSp0 .taskText:not([font-size]){font-size:11px}#mermaid-svg-QK2WyvOlyH4KUSp0 .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-QK2WyvOlyH4KUSp0 .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-QK2WyvOlyH4KUSp0 .task.clickable{cursor:pointer}#mermaid-svg-QK2WyvOlyH4KUSp0 .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-QK2WyvOlyH4KUSp0 .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-QK2WyvOlyH4KUSp0 .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-QK2WyvOlyH4KUSp0 .taskText0,#mermaid-svg-QK2WyvOlyH4KUSp0 .taskText1,#mermaid-svg-QK2WyvOlyH4KUSp0 .taskText2,#mermaid-svg-QK2WyvOlyH4KUSp0 .taskText3{fill:#fff}#mermaid-svg-QK2WyvOlyH4KUSp0 .task0,#mermaid-svg-QK2WyvOlyH4KUSp0 .task1,#mermaid-svg-QK2WyvOlyH4KUSp0 .task2,#mermaid-svg-QK2WyvOlyH4KUSp0 .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-QK2WyvOlyH4KUSp0 .taskTextOutside0,#mermaid-svg-QK2WyvOlyH4KUSp0 .taskTextOutside2{fill:#000}#mermaid-svg-QK2WyvOlyH4KUSp0 .taskTextOutside1,#mermaid-svg-QK2WyvOlyH4KUSp0 .taskTextOutside3{fill:#000}#mermaid-svg-QK2WyvOlyH4KUSp0 .active0,#mermaid-svg-QK2WyvOlyH4KUSp0 .active1,#mermaid-svg-QK2WyvOlyH4KUSp0 .active2,#mermaid-svg-QK2WyvOlyH4KUSp0 .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-QK2WyvOlyH4KUSp0 .activeText0,#mermaid-svg-QK2WyvOlyH4KUSp0 .activeText1,#mermaid-svg-QK2WyvOlyH4KUSp0 .activeText2,#mermaid-svg-QK2WyvOlyH4KUSp0 .activeText3{fill:#000 !important}#mermaid-svg-QK2WyvOlyH4KUSp0 .done0,#mermaid-svg-QK2WyvOlyH4KUSp0 .done1,#mermaid-svg-QK2WyvOlyH4KUSp0 .done2,#mermaid-svg-QK2WyvOlyH4KUSp0 .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-QK2WyvOlyH4KUSp0 .doneText0,#mermaid-svg-QK2WyvOlyH4KUSp0 .doneText1,#mermaid-svg-QK2WyvOlyH4KUSp0 .doneText2,#mermaid-svg-QK2WyvOlyH4KUSp0 .doneText3{fill:#000 !important}#mermaid-svg-QK2WyvOlyH4KUSp0 .crit0,#mermaid-svg-QK2WyvOlyH4KUSp0 .crit1,#mermaid-svg-QK2WyvOlyH4KUSp0 .crit2,#mermaid-svg-QK2WyvOlyH4KUSp0 .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-QK2WyvOlyH4KUSp0 .activeCrit0,#mermaid-svg-QK2WyvOlyH4KUSp0 .activeCrit1,#mermaid-svg-QK2WyvOlyH4KUSp0 .activeCrit2,#mermaid-svg-QK2WyvOlyH4KUSp0 .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-QK2WyvOlyH4KUSp0 .doneCrit0,#mermaid-svg-QK2WyvOlyH4KUSp0 .doneCrit1,#mermaid-svg-QK2WyvOlyH4KUSp0 .doneCrit2,#mermaid-svg-QK2WyvOlyH4KUSp0 .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-QK2WyvOlyH4KUSp0 .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-QK2WyvOlyH4KUSp0 .milestoneText{font-style:italic}#mermaid-svg-QK2WyvOlyH4KUSp0 .doneCritText0,#mermaid-svg-QK2WyvOlyH4KUSp0 .doneCritText1,#mermaid-svg-QK2WyvOlyH4KUSp0 .doneCritText2,#mermaid-svg-QK2WyvOlyH4KUSp0 .doneCritText3{fill:#000 !important}#mermaid-svg-QK2WyvOlyH4KUSp0 .activeCritText0,#mermaid-svg-QK2WyvOlyH4KUSp0 .activeCritText1,#mermaid-svg-QK2WyvOlyH4KUSp0 .activeCritText2,#mermaid-svg-QK2WyvOlyH4KUSp0 .activeCritText3{fill:#000 !important}#mermaid-svg-QK2WyvOlyH4KUSp0 .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-QK2WyvOlyH4KUSp0 g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-QK2WyvOlyH4KUSp0 g.classGroup text .title{font-weight:bolder}#mermaid-svg-QK2WyvOlyH4KUSp0 g.clickable{cursor:pointer}#mermaid-svg-QK2WyvOlyH4KUSp0 g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-QK2WyvOlyH4KUSp0 g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-QK2WyvOlyH4KUSp0 .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-QK2WyvOlyH4KUSp0 .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-QK2WyvOlyH4KUSp0 .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-QK2WyvOlyH4KUSp0 .dashed-line{stroke-dasharray:3}#mermaid-svg-QK2WyvOlyH4KUSp0 #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-QK2WyvOlyH4KUSp0 #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-QK2WyvOlyH4KUSp0 #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-QK2WyvOlyH4KUSp0 #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-QK2WyvOlyH4KUSp0 #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-QK2WyvOlyH4KUSp0 #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-QK2WyvOlyH4KUSp0 #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-QK2WyvOlyH4KUSp0 #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-QK2WyvOlyH4KUSp0 .commit-id,#mermaid-svg-QK2WyvOlyH4KUSp0 .commit-msg,#mermaid-svg-QK2WyvOlyH4KUSp0 .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-QK2WyvOlyH4KUSp0 .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-QK2WyvOlyH4KUSp0 .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-QK2WyvOlyH4KUSp0 g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-QK2WyvOlyH4KUSp0 g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-QK2WyvOlyH4KUSp0 g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-QK2WyvOlyH4KUSp0 g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-QK2WyvOlyH4KUSp0 g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-QK2WyvOlyH4KUSp0 .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-QK2WyvOlyH4KUSp0 .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-QK2WyvOlyH4KUSp0 .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-QK2WyvOlyH4KUSp0 .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-QK2WyvOlyH4KUSp0 .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-QK2WyvOlyH4KUSp0 .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-QK2WyvOlyH4KUSp0 .edgeLabel text{fill:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-QK2WyvOlyH4KUSp0 .node circle.state-start{fill:black;stroke:black}#mermaid-svg-QK2WyvOlyH4KUSp0 .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-QK2WyvOlyH4KUSp0 #statediagram-barbEnd{fill:#9370db}#mermaid-svg-QK2WyvOlyH4KUSp0 .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-QK2WyvOlyH4KUSp0 .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-QK2WyvOlyH4KUSp0 .statediagram-state .divider{stroke:#9370db}#mermaid-svg-QK2WyvOlyH4KUSp0 .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-QK2WyvOlyH4KUSp0 .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-QK2WyvOlyH4KUSp0 .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-QK2WyvOlyH4KUSp0 .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-QK2WyvOlyH4KUSp0 .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-QK2WyvOlyH4KUSp0 .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-QK2WyvOlyH4KUSp0 .note-edge{stroke-dasharray:5}#mermaid-svg-QK2WyvOlyH4KUSp0 .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-QK2WyvOlyH4KUSp0 .error-icon{fill:#522}#mermaid-svg-QK2WyvOlyH4KUSp0 .error-text{fill:#522;stroke:#522}#mermaid-svg-QK2WyvOlyH4KUSp0 .edge-thickness-normal{stroke-width:2px}#mermaid-svg-QK2WyvOlyH4KUSp0 .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-QK2WyvOlyH4KUSp0 .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-QK2WyvOlyH4KUSp0 .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-QK2WyvOlyH4KUSp0 .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-QK2WyvOlyH4KUSp0 .marker{fill:#333}#mermaid-svg-QK2WyvOlyH4KUSp0 .marker.cross{stroke:#333}
:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}</style>
<style>#mermaid-svg-QK2WyvOlyH4KUSp0 {
color: rgba(0, 0, 0, 0.75);
font: ;
}</style>
1
.
5
.....
2
..
# 展示圖片
def img_show_array ( a) :
plt. imshow( a)
plt. show( )
# 展示投影圖, 輸入引數arr是圖片的二維陣列,direction是x,y軸
def show_shadow ( arr, direction = 'x' ) :
a_max = max ( arr)
if direction == 'x' : # x軸方向的投影
a_shadow = np. zeros( ( a_max, len ( arr) ) , dtype= int )
for i in range ( 0 , len ( arr) ) :
if arr[ i] == 0 :
continue
for j in range ( 0 , arr[ i] ) :
a_shadow[ j] [ i] = 255
elif direction == 'y' : # y軸方向的投影
a_shadow = np. zeros( ( len ( arr) , a_max) , dtype= int )
for i in range ( 0 , len ( arr) ) :
if arr[ i] == 0 :
continue
for j in range ( 0 , arr[ i] ) :
a_shadow[ i] [ j] = 255
img_show_array( a_shadow)
我們來試驗一下效果:
我們將上面的原圖片命名為question.jpg放到代碼同級目錄,
# 讀入圖片
img_path = 'question.jpg'
img= cv2. imread( img_path, 0 )
thresh = 200
# 二值化并且反色
ret, img_b= cv2. threshold( img, thresh, 255 , cv2. THRESH_BINARY_INV)
二值化并反色后的變化如下所示:
上面的操作很有作用,通過二值化,過濾掉雜色,通過反色將黑白對調,原來白紙區域都是255,現在黑色都是0,更利于計算,
計算投影并展示的代碼:
img_y_shadow_a = img_y_shadow( img_b)
show_shadow( img_y_shadow_a, 'y' ) # 如果要顯示投影
下面的圖是上面圖在Y軸上的投影
從視覺上看,基本上能區分出來哪一行是哪一行,
2.4.2 根據投影找區域
最有效的方法,往往還得用回圈來實作,
上面投影那張圖,你如何計算哪里到哪里是一行,雖然肉眼可見,但是計算機需要規則和演算法,
# 圖片獲取文字塊,傳入投影串列,回傳標記的陣列區域坐標[[左,上,右,下]]
def img2rows ( a, w, h) :
### 根據投影切分圖塊 ###
inLine = False # 是否已經開始切分
start = 0 # 某次切分的起始索引
mark_boxs = [ ]
for i in range ( 0 , len ( a) ) :
if inLine == False and a[ i] > 10 :
inLine = True
start = i
# 記錄這次選中的區域[左,上,右,下],上下就是圖片,左右是start到當前
elif i- start > 5 and a[ i] < 10 and inLine:
inLine = False
if i- start > 10 :
top = max ( start- 1 , 0 )
bottom = min ( h, i+ 1 )
box = [ 0 , top, w, bottom]
mark_boxs. append( box)
return mark_boxs
通過投影,計算哪些區域在一定范圍內是連續的,如果連續了很長時間,我們就認為是同一區域,如果斷開了很長一段時間,我們就認為是另一個區域,
通過這項操作,我們就可以獲得Y軸上某一行的上下兩個邊界點的坐標,再結合圖片寬度,其實我們也就知道了一行圖片的四個頂點的坐標了mark_boxs存下的是[坐,上,右,下],
如果呼叫如下代碼:
( img_h, img_w) = img. shape
row_mark_boxs = img2rows( img_y_shadow_a, img_w, img_h)
print ( row_mark_boxs)
我們獲取到的是所有識別出來每行圖片的坐標,格式是這樣的:[[0, 26, 596, 52], [0, 76, 596, 103], [0, 130, 596, 155], [0, 178, 596, 207], [0, 233, 596, 259], [0, 282, 596, 311], [0, 335, 596, 363], [0, 390, 596, 415]]
2.4.3 根據區域切圖片
最有效的方法,最終也得用回圈來實作,這也是計算機體現它強大的地方,
# 裁剪圖片,img 圖片陣列, mark_boxs 區域標記
def cut_img ( img, mark_boxs) :
img_items = [ ] # 存放裁剪好的圖片
for i in range ( 0 , len ( mark_boxs) ) :
img_org = img. copy( )
box = mark_boxs[ i]
# 裁剪圖片
img_item = img_org[ box[ 1 ] : box[ 3 ] , box[ 0 ] : box[ 2 ] ]
img_items. append( img_item)
return img_items
這一步驟是拿著方框,從大圖上用小刀劃下小圖,核心代碼是img_org[box[1]:box[3], box[0]:box[2]]圖片裁剪,引數是陣列的[上:下,左:右],獲取的資料還是二維的陣列,
如果保存下來:
# 保存圖片
def save_imgs ( dir_name, imgs) :
if os. path. exists( dir_name) :
shutil. rmtree( dir_name)
if not os. path. exists( dir_name) :
os. makedirs( dir_name)
img_paths = [ ]
for i in range ( 0 , len ( imgs) ) :
file_path = dir_name+ '/part_' + str ( i) + '.jpg'
cv2. imwrite( file_path, imgs[ i] )
img_paths. append( file_path)
return img_paths
# 切圖并保存
row_imgs = cut_img( img, row_mark_boxs)
imgs = save_imgs( 'rows' , row_imgs) # 如果要保存切圖
print ( imgs)
圖片是下面這樣的:
2.4.4 回圈可去油膩
還是回圈, 橫著行我們掌握了,那么針對每一行圖片,我們豎著切成三塊是不是也會了,一個道理,
需要注意的是,橫豎是稍微有區別的,下面是上圖的x軸投影,
橫著的時候,字與字之間本來就是有空隙的,然后塊與塊也有空隙,這個空隙的度需要掌握好,以便更好地區分出來是字的間距還是算式塊的間距,
幸好,有種方法叫膨脹,
膨脹對人來說不積極,但是對于技術來說,不管是膨脹(dilate),還是腐蝕(erode),只要能達到目的,都是好的,
kernel= np. ones( ( 3 , 3 ) , np. uint8) # 膨脹核大小
row_img_b= cv2. dilate( img_b, kernel, iterations= 6 ) # 影像膨脹6次
膨脹之后再投影,就很好地區分出了塊,
根據投影裁剪之后如下圖所示:
同理,不膨脹可截取單個字符,
這樣,這是一塊區域的字符,
一行的,一頁的,通過回圈,都可以截取出來,
有了圖片,就可以識別了,有了位置,就可以判斷識別結果的關系了,
下面提供一些代碼,這些代碼不全,有些函式你可能找不到,但是思路可以參考,詳細的代碼可以去我的github去看,
def divImg ( img_path, save_file = False ) :
img_o= cv2. imread( img_path, 1 )
# 讀入圖片
img= cv2. imread( img_path, 0 )
( img_h, img_w) = img. shape
thresh = 200
# 二值化整個圖,用于分行
ret, img_b= cv2. threshold( img, thresh, 255 , cv2. THRESH_BINARY_INV)
# 計算投影,并截取整個圖片的行
img_y_shadow_a = img_y_shadow( img_b)
row_mark_boxs = img2rows( img_y_shadow_a, img_w, img_h)
# 切行的圖片,切的是原圖
row_imgs = cut_img( img, row_mark_boxs)
all_mark_boxs = [ ]
all_char_imgs = [ ]
# ===============從行切塊======================
for i in range ( 0 , len ( row_imgs) ) :
row_img = row_imgs[ i]
( row_img_h, row_img_w) = row_img. shape
# 二值化一行的圖,用于切塊
ret, row_img_b= cv2. threshold( row_img, thresh, 255 , cv2. THRESH_BINARY_INV)
kernel= np. ones( ( 3 , 3 ) , np. uint8)
#影像膨脹6次
row_img_b_d= cv2. dilate( row_img_b, kernel, iterations= 6 )
img_x_shadow_a = img_x_shadow( row_img_b_d)
block_mark_boxs = row2blocks( img_x_shadow_a, row_img_w, row_img_h)
row_char_boxs = [ ]
row_char_imgs = [ ]
# 切塊的圖,切的是原圖
block_imgs = cut_img( row_img, block_mark_boxs)
if save_file:
b_imgs = save_imgs( 'cuts/row_' + str ( i) , block_imgs) # 如果要保存切圖
print ( b_imgs)
# =============從塊切字====================
for j in range ( 0 , len ( block_imgs) ) :
block_img = block_imgs[ j]
( block_img_h, block_img_w) = block_img. shape
# 二值化塊,因為要切字符圖片了
ret, block_img_b= cv2. threshold( block_img, thresh, 255 , cv2. THRESH_BINARY_INV)
block_img_x_shadow_a = img_x_shadow( block_img_b)
row_top = row_mark_boxs[ i] [ 1 ]
block_left = block_mark_boxs[ j] [ 0 ]
char_mark_boxs, abs_char_mark_boxs = block2chars( block_img_x_shadow_a, block_img_w, block_img_h, row_top, block_left)
row_char_boxs. append( abs_char_mark_boxs)
# 切的是二值化的圖
char_imgs = cut_img( block_img_b, char_mark_boxs, True )
row_char_imgs. append( char_imgs)
if save_file:
c_imgs = save_imgs( 'cuts/row_' + str ( i) + '/blocks_' + str ( j) , char_imgs) # 如果要保存切圖
print ( c_imgs)
all_mark_boxs. append( row_char_boxs)
all_char_imgs. append( row_char_imgs)
return all_mark_boxs, all_char_imgs, img_o
最后回傳的值是3個,all_mark_boxs是標記的字符位置的坐標集合,[左,上,右,下]是指某個字符在一張大圖里的坐標,列印一下是這樣的: [[[[19, 26, 34, 53], [36, 26, 53, 53], [54, 26, 65, 53], [66, 26, 82, 53], [84, 26, 101, 53], [102, 26, 120, 53], [120, 26, 139, 53]], [[213, 26, 229, 53], [231, 26, 248, 53], [249, 26, 268, 53], [268, 26, 285, 53]], [[408, 26, 426, 53], [427, 26, 437, 53], [438, 26, 456, 53], [456, 26, 474, 53], [475, 26, 492, 53]]], [[[20, 76, 36, 102], [38, 76, 48, 102], [50, 76, 66, 102], [67, 76, 85, 102], [85, 76, 104, 102]], [[214, 76, 233, 102], [233, 76, 250, 102], [252, 76, 268, 102], [270, 76, 287, 102]], [[411, 76, 426, 102], [428, 76, 445, 102], [446, 76, 457, 102], [458, 76, 474, 102], [476, 76, 493, 102], [495, 76, 511, 102]]]]
它是有結構的,它的結構是:
<style>#mermaid-svg-iZaEdgc9jTIppBrG .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-iZaEdgc9jTIppBrG .label text{fill:#333}#mermaid-svg-iZaEdgc9jTIppBrG .node rect,#mermaid-svg-iZaEdgc9jTIppBrG .node circle,#mermaid-svg-iZaEdgc9jTIppBrG .node ellipse,#mermaid-svg-iZaEdgc9jTIppBrG .node polygon,#mermaid-svg-iZaEdgc9jTIppBrG .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-iZaEdgc9jTIppBrG .node .label{text-align:center;fill:#333}#mermaid-svg-iZaEdgc9jTIppBrG .node.clickable{cursor:pointer}#mermaid-svg-iZaEdgc9jTIppBrG .arrowheadPath{fill:#333}#mermaid-svg-iZaEdgc9jTIppBrG .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-iZaEdgc9jTIppBrG .flowchart-link{stroke:#333;fill:none}#mermaid-svg-iZaEdgc9jTIppBrG .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-iZaEdgc9jTIppBrG .edgeLabel rect{opacity:0.9}#mermaid-svg-iZaEdgc9jTIppBrG .edgeLabel span{color:#333}#mermaid-svg-iZaEdgc9jTIppBrG .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-iZaEdgc9jTIppBrG .cluster text{fill:#333}#mermaid-svg-iZaEdgc9jTIppBrG div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-iZaEdgc9jTIppBrG .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-iZaEdgc9jTIppBrG text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-iZaEdgc9jTIppBrG .actor-line{stroke:grey}#mermaid-svg-iZaEdgc9jTIppBrG .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-iZaEdgc9jTIppBrG .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-iZaEdgc9jTIppBrG #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-iZaEdgc9jTIppBrG .sequenceNumber{fill:#fff}#mermaid-svg-iZaEdgc9jTIppBrG #sequencenumber{fill:#333}#mermaid-svg-iZaEdgc9jTIppBrG #crosshead path{fill:#333;stroke:#333}#mermaid-svg-iZaEdgc9jTIppBrG .messageText{fill:#333;stroke:#333}#mermaid-svg-iZaEdgc9jTIppBrG .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-iZaEdgc9jTIppBrG .labelText,#mermaid-svg-iZaEdgc9jTIppBrG .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-iZaEdgc9jTIppBrG .loopText,#mermaid-svg-iZaEdgc9jTIppBrG .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-iZaEdgc9jTIppBrG .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-iZaEdgc9jTIppBrG .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-iZaEdgc9jTIppBrG .noteText,#mermaid-svg-iZaEdgc9jTIppBrG .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-iZaEdgc9jTIppBrG .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-iZaEdgc9jTIppBrG .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-iZaEdgc9jTIppBrG .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-iZaEdgc9jTIppBrG .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iZaEdgc9jTIppBrG .section{stroke:none;opacity:0.2}#mermaid-svg-iZaEdgc9jTIppBrG .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-iZaEdgc9jTIppBrG .section2{fill:#fff400}#mermaid-svg-iZaEdgc9jTIppBrG .section1,#mermaid-svg-iZaEdgc9jTIppBrG .section3{fill:#fff;opacity:0.2}#mermaid-svg-iZaEdgc9jTIppBrG .sectionTitle0{fill:#333}#mermaid-svg-iZaEdgc9jTIppBrG .sectionTitle1{fill:#333}#mermaid-svg-iZaEdgc9jTIppBrG .sectionTitle2{fill:#333}#mermaid-svg-iZaEdgc9jTIppBrG .sectionTitle3{fill:#333}#mermaid-svg-iZaEdgc9jTIppBrG .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iZaEdgc9jTIppBrG .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-iZaEdgc9jTIppBrG .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iZaEdgc9jTIppBrG .grid path{stroke-width:0}#mermaid-svg-iZaEdgc9jTIppBrG .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-iZaEdgc9jTIppBrG .task{stroke-width:2}#mermaid-svg-iZaEdgc9jTIppBrG .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iZaEdgc9jTIppBrG .taskText:not([font-size]){font-size:11px}#mermaid-svg-iZaEdgc9jTIppBrG .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iZaEdgc9jTIppBrG .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-iZaEdgc9jTIppBrG .task.clickable{cursor:pointer}#mermaid-svg-iZaEdgc9jTIppBrG .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-iZaEdgc9jTIppBrG .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-iZaEdgc9jTIppBrG .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-iZaEdgc9jTIppBrG .taskText0,#mermaid-svg-iZaEdgc9jTIppBrG .taskText1,#mermaid-svg-iZaEdgc9jTIppBrG .taskText2,#mermaid-svg-iZaEdgc9jTIppBrG .taskText3{fill:#fff}#mermaid-svg-iZaEdgc9jTIppBrG .task0,#mermaid-svg-iZaEdgc9jTIppBrG .task1,#mermaid-svg-iZaEdgc9jTIppBrG .task2,#mermaid-svg-iZaEdgc9jTIppBrG .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-iZaEdgc9jTIppBrG .taskTextOutside0,#mermaid-svg-iZaEdgc9jTIppBrG .taskTextOutside2{fill:#000}#mermaid-svg-iZaEdgc9jTIppBrG .taskTextOutside1,#mermaid-svg-iZaEdgc9jTIppBrG .taskTextOutside3{fill:#000}#mermaid-svg-iZaEdgc9jTIppBrG .active0,#mermaid-svg-iZaEdgc9jTIppBrG .active1,#mermaid-svg-iZaEdgc9jTIppBrG .active2,#mermaid-svg-iZaEdgc9jTIppBrG .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-iZaEdgc9jTIppBrG .activeText0,#mermaid-svg-iZaEdgc9jTIppBrG .activeText1,#mermaid-svg-iZaEdgc9jTIppBrG .activeText2,#mermaid-svg-iZaEdgc9jTIppBrG .activeText3{fill:#000 !important}#mermaid-svg-iZaEdgc9jTIppBrG .done0,#mermaid-svg-iZaEdgc9jTIppBrG .done1,#mermaid-svg-iZaEdgc9jTIppBrG .done2,#mermaid-svg-iZaEdgc9jTIppBrG .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-iZaEdgc9jTIppBrG .doneText0,#mermaid-svg-iZaEdgc9jTIppBrG .doneText1,#mermaid-svg-iZaEdgc9jTIppBrG .doneText2,#mermaid-svg-iZaEdgc9jTIppBrG .doneText3{fill:#000 !important}#mermaid-svg-iZaEdgc9jTIppBrG .crit0,#mermaid-svg-iZaEdgc9jTIppBrG .crit1,#mermaid-svg-iZaEdgc9jTIppBrG .crit2,#mermaid-svg-iZaEdgc9jTIppBrG .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-iZaEdgc9jTIppBrG .activeCrit0,#mermaid-svg-iZaEdgc9jTIppBrG .activeCrit1,#mermaid-svg-iZaEdgc9jTIppBrG .activeCrit2,#mermaid-svg-iZaEdgc9jTIppBrG .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-iZaEdgc9jTIppBrG .doneCrit0,#mermaid-svg-iZaEdgc9jTIppBrG .doneCrit1,#mermaid-svg-iZaEdgc9jTIppBrG .doneCrit2,#mermaid-svg-iZaEdgc9jTIppBrG .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-iZaEdgc9jTIppBrG .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-iZaEdgc9jTIppBrG .milestoneText{font-style:italic}#mermaid-svg-iZaEdgc9jTIppBrG .doneCritText0,#mermaid-svg-iZaEdgc9jTIppBrG .doneCritText1,#mermaid-svg-iZaEdgc9jTIppBrG .doneCritText2,#mermaid-svg-iZaEdgc9jTIppBrG .doneCritText3{fill:#000 !important}#mermaid-svg-iZaEdgc9jTIppBrG .activeCritText0,#mermaid-svg-iZaEdgc9jTIppBrG .activeCritText1,#mermaid-svg-iZaEdgc9jTIppBrG .activeCritText2,#mermaid-svg-iZaEdgc9jTIppBrG .activeCritText3{fill:#000 !important}#mermaid-svg-iZaEdgc9jTIppBrG .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iZaEdgc9jTIppBrG g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-iZaEdgc9jTIppBrG g.classGroup text .title{font-weight:bolder}#mermaid-svg-iZaEdgc9jTIppBrG g.clickable{cursor:pointer}#mermaid-svg-iZaEdgc9jTIppBrG g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-iZaEdgc9jTIppBrG g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-iZaEdgc9jTIppBrG .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-iZaEdgc9jTIppBrG .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-iZaEdgc9jTIppBrG .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-iZaEdgc9jTIppBrG .dashed-line{stroke-dasharray:3}#mermaid-svg-iZaEdgc9jTIppBrG #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-iZaEdgc9jTIppBrG #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-iZaEdgc9jTIppBrG #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-iZaEdgc9jTIppBrG #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-iZaEdgc9jTIppBrG #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-iZaEdgc9jTIppBrG #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-iZaEdgc9jTIppBrG #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-iZaEdgc9jTIppBrG #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-iZaEdgc9jTIppBrG .commit-id,#mermaid-svg-iZaEdgc9jTIppBrG .commit-msg,#mermaid-svg-iZaEdgc9jTIppBrG .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iZaEdgc9jTIppBrG .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iZaEdgc9jTIppBrG .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iZaEdgc9jTIppBrG g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iZaEdgc9jTIppBrG g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-iZaEdgc9jTIppBrG g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-iZaEdgc9jTIppBrG g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-iZaEdgc9jTIppBrG g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-iZaEdgc9jTIppBrG g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-iZaEdgc9jTIppBrG .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-iZaEdgc9jTIppBrG .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-iZaEdgc9jTIppBrG .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-iZaEdgc9jTIppBrG .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-iZaEdgc9jTIppBrG .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-iZaEdgc9jTIppBrG .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-iZaEdgc9jTIppBrG .edgeLabel text{fill:#333}#mermaid-svg-iZaEdgc9jTIppBrG .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-iZaEdgc9jTIppBrG .node circle.state-start{fill:black;stroke:black}#mermaid-svg-iZaEdgc9jTIppBrG .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-iZaEdgc9jTIppBrG #statediagram-barbEnd{fill:#9370db}#mermaid-svg-iZaEdgc9jTIppBrG .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-iZaEdgc9jTIppBrG .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-iZaEdgc9jTIppBrG .statediagram-state .divider{stroke:#9370db}#mermaid-svg-iZaEdgc9jTIppBrG .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-iZaEdgc9jTIppBrG .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-iZaEdgc9jTIppBrG .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-iZaEdgc9jTIppBrG .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-iZaEdgc9jTIppBrG .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-iZaEdgc9jTIppBrG .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-iZaEdgc9jTIppBrG .note-edge{stroke-dasharray:5}#mermaid-svg-iZaEdgc9jTIppBrG .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-iZaEdgc9jTIppBrG .error-icon{fill:#522}#mermaid-svg-iZaEdgc9jTIppBrG .error-text{fill:#522;stroke:#522}#mermaid-svg-iZaEdgc9jTIppBrG .edge-thickness-normal{stroke-width:2px}#mermaid-svg-iZaEdgc9jTIppBrG .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-iZaEdgc9jTIppBrG .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-iZaEdgc9jTIppBrG .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-iZaEdgc9jTIppBrG .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-iZaEdgc9jTIppBrG .marker{fill:#333}#mermaid-svg-iZaEdgc9jTIppBrG .marker.cross{stroke:#333}
:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}</style>
<style>#mermaid-svg-iZaEdgc9jTIppBrG {
color: rgba(0, 0, 0, 0.75);
font: ;
}</style>
第一層-陣列
行1
行2
第二層-行3
行4
行5
塊1
第三層-塊2
塊3
字符1
第四層-字符2
字符3
左上右下 495, 76, 511, 102
all_char_imgs這個回傳值,里面是上面坐標結構對應位置的圖片,img_o就是原圖了,
2.5 識別
回圈,回圈,還是TM回圈!
對于識別,2.3 預測資料已經講過了,那次是對于2張獨立圖片的識別,現在我們要對整張大圖切分后的小圖集合進行識別,這就又用到了回圈,
翠花,上代碼!
all_mark_boxs, all_char_imgs, img_o = divImg( path, save)
model = cnn. create_model( )
model. load_weights( 'checkpoint/char_checkpoint' )
class_name = np. load( 'class_name.npy' )
# 遍歷行
for i in range ( 0 , len ( all_char_imgs) ) :
row_imgs = all_char_imgs[ i]
# 遍歷塊
for j in range ( 0 , len ( row_imgs) ) :
block_imgs = row_imgs[ j]
block_imgs = np. array( block_imgs)
results = cnn. predict( model, block_imgs, class_name)
print ( 'recognize result:' , results)
上面代碼做的就是以塊為單位,傳遞給神經網路進行預測,然后回傳識別結果,
針對這張圖,我們來進行裁剪和識別,
看底部的最后一行
recognize result: ['1', '0', '12', '2', '10']
recognize result: ['8', '12', '6', '10']
recognize result: ['1', '0', '12', '7', '10']
結果是索引,不是真實的字符,我們根據字典10: '=', 11: '+', 12: '-', 13: '×', 14: '÷'轉換過來之后結果是:
recognize result: ['1', '0', '-', '2', '=']
recognize result: ['8', '-', '6', '=']
recognize result: ['1', '0', '-', '7', '=']
和圖片是對應的:
2.6 計算并反饋
回圈……
我們獲取到了10-2=、8-6=2,也獲取到了他們在原圖的位置坐標[左,上,右,下],那么怎么把結果反饋到原圖上呢?
往往到這里就剩最后一步了,
再來溫習一遍需求:作對了,能打對號;做錯了,能打叉號;沒做的,能補上答案,
實作分兩步走:計算(是作對做錯還是沒錯)和反饋(把預期結果寫到原圖上),
2.6.1 計算
python有個函式很強大,就是eval函式,能計算字串算式,比如直接計算eval("5+3-2"),
所以,一切都靠它了,
# 計算數值并回傳結果 引數chars:['8', '-', '6', '=']
def calculation ( chars) :
cstr = '' . join( chars)
result = ''
if ( "=" in cstr) : # 有等號
str_arr = cstr. split( '=' )
c_str = str_arr[ 0 ]
r_str = str_arr[ 1 ]
c_str = c_str. replace( "×" , "*" )
c_str = c_str. replace( "÷" , "/" )
try :
c_r = int ( eval ( c_str) )
except Exception as e:
print ( "Exception" , e)
if r_str == "" :
result = c_r
else :
if str ( c_r) == str ( r_str) :
result = "√"
else :
result = "×"
return result
執行之后獲得的結果是:
recognize result: ['8', '×', '4', '=']
calculate result: 32
recognize result: ['2', '-', '1', '=', '1']
calculate result: √
recognize result: ['1', '0', '-', '5', '=']
calculate result: 5
2.6.2 反饋
有了結果之后,把結果寫到圖片上,這是最后一步,也是最簡單的一步,
但是實作起來,居然很繁瑣,
得找坐標吧,得計算結果呈現的位置吧,我們還想標記不同的顏色,比如對了是綠色,錯了是紅色,補齊答案是灰色,
下面代碼是在一個圖img上,把文本內容text畫到(left,top)位置,以特定顏色和大小,
# 繪制文本
def cv2ImgAddText ( img, text, left, top, textColor= ( 255 , 0 , 0 ) , textSize= 20 ) :
if ( isinstance ( img, np. ndarray) ) : # 判斷是否OpenCV圖片型別
img = Image. fromarray( cv2. cvtColor( img, cv2. COLOR_BGR2RGB) )
# 創建一個可以在給定影像上繪圖的物件
draw = ImageDraw. Draw( img)
# 字體的格式
fontStyle = ImageFont. truetype( "fonts/fangzheng_shusong.ttf" , textSize, encoding= "utf-8" )
# 繪制文本
draw. text( ( left, top) , text, textColor, font= fontStyle)
# 轉換回OpenCV格式
return cv2. cvtColor( np. asarray( img) , cv2. COLOR_RGB2BGR)
結合著切圖的資訊、計算的資訊,下面代碼提供思路參考:
# 獲取切圖示注,切圖圖片,原圖圖圖片
all_mark_boxs, all_char_imgs, img_o = divImg( path, save)
# 恢復模型,用于圖片識別
model = cnn. create_model( )
model. load_weights( 'checkpoint/char_checkpoint' )
class_name = np. load( 'class_name.npy' )
# 遍歷行
for i in range ( 0 , len ( all_char_imgs) ) :
row_imgs = all_char_imgs[ i]
# 遍歷塊
for j in range ( 0 , len ( row_imgs) ) :
block_imgs = row_imgs[ j]
block_imgs = np. array( block_imgs)
# 圖片識別
results = cnn. predict( model, block_imgs, class_name)
print ( 'recognize result:' , results)
# 計算結果
result = calculation( results)
print ( 'calculate result:' , result)
# 獲取塊的標注坐標
block_mark = all_mark_boxs[ i] [ j]
# 獲取結果的坐標,寫在塊的最后一個字
answer_box = block_mark[ - 1 ]
# 計算最后一個字的位置
x = answer_box[ 2 ]
y = answer_box[ 3 ]
iw = answer_box[ 2 ] - answer_box[ 0 ]
ih = answer_box[ 3 ] - answer_box[ 1 ]
# 計算字體大小
textSize = max ( iw, ih)
# 根據結果設定字體顏色
if str ( result) == "√" :
color = ( 0 , 255 , 0 )
elif str ( result) == "×" :
color = ( 255 , 0 , 0 )
else :
color = ( 192 , 192 , 192 )
# 將結果寫到原圖上
img_o = cv2ImgAddText( img_o, str ( result) , answer_box[ 2 ] , answer_box[ 1 ] , color, textSize)
# 將寫滿結果的原圖保存
cv2. imwrite( 'result.jpg' , img_o)
結果是下面這樣的: