主頁 >  其他 > 基于Python的作業自動批改系統

基于Python的作業自動批改系統

2022-01-20 11:18:51 其他

  1. 同級新建fonts檔案夾里拷貝一些字體檔案,從這里找C:\Windows\Fonts,幾十個就行,
  2. get_character_pic.py 生成字體
  3. cnn.py 訓練資料
  4. main.py 裁剪指定圖片并識別,素材圖片新建imgs檔案夾,在imgs/question.png下,結果檔案保存在imgs/result.png,
  5. 注意如果識別不成功,很可能是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)) Rescaling(1./255,inputs?hape=(24,24,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)) MaxPooling2D((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) Dense(15)

它所做的事情,不管你前面是怎么樣,有多少維度,到我這里我要強行轉化為固定的通道,

比如識別字母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() layers.Flatten()將二維資料拉平為一維資料([[11,12],[21,22]]->[11,12,21,22]),

對于總體的模型,呼叫 m o d e l . s u m m a r y ( ) model.summary() model.summary()列印序列的網路結構如下:

_________________________________________________________________
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 Flatten拉成一維之后變為(None, 1024),經過全連接變為(None, 128)再一次全連接變為(None, 15),15就是我們的最終分類,這一切都是我們設計的,

m o d e l . c o m p i l e model.compile model.compile就是配置模型的幾個引數,這個現階段記住就可以,

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)

結果是下面這樣的:

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/416167.html

標籤:AI

上一篇:神經網路-人臉表情識別

下一篇:最新ACM Fellow名單發布,唐杰等4名中國大陸學者當選,中國機構入選人數排名第二

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more