- 同级新建fonts文件夹里拷贝一些字体文件,从这里找C:\Windows\Fonts,几十个就行。
- get_character_pic.py 生成字体
- cnn.py 训练数据
- main.py 裁剪指定图片并识别,素材图片新建imgs文件夹,在imgs/question.png下,结果文件保存在imgs/result.png。
- 注意如果识别不成功,很可能是question.png的字体你没有训练(这幅图的字体是方正书宋简体,但是你只训练了楷体),这时候可以使用楷体自己编一个算式图。
一、亮出效果
最近在线教育行业遭遇一点小波折,一些搜题、智能批改类的功能要下线。
退1024步讲,要不要自己做一个自动批改的功能啊?万一哪天孩子要用呢!
昨晚我做了一个梦,梦见我实现了这个功能,如下图所示:
功能简介:作对了,能打对号;做错了,能打叉号;没做的,能补上答案。
醒来后,我环顾四周,赶紧再躺下,希望梦还能接上。
二、实现步骤
基本思路
其实,搞定两点就成,第一是能识别数字,第二是能切分数字。
首先得能认识5是5,这是前提条件,其次是能找到5、6、7、8这些数字区域的位置。
前者是图像识别,后者是图像切割。
- 对于图像识别,一般的套路是下面这样的(CNN卷积神经网络):
#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;}#mermaid-svg-19CB7BMTJEaRusAf {
color: rgba(0, 0, 0, 0.75);
font: ;
}
输入
识别输出
字符图片数据集
训练
训练结果
字符图片
字符值
- 对于图像切割,一般的套路是下面的这样(横向纵向投影法):
既然思路能走得通,那么咱们先搞图像识别。
要自己搞图像识别,得准备数据->训练数据并保存模型->使用训练模型预测结果。
2.1 准备数据
对于男友,找一个油嘴滑舌的花花公子,不如找一个闷葫芦IT男,亲手把他培养成你期望的样子。
咱们不用什么官方的mnist数据集,因为那是官方的,不是你的,你想要添加±×÷它也没有。
有些通用的数据集,虽然很强大,很方便,但是一旦放到你的场景中,效果一点也不如你的愿。
只有训练自己手里的数据,然后自己用起来才顺手。更重要的是,我们享受创造的过程。
假设,我们只给口算做识别,那么我们需要的图片数据有如下几类:
索引:01234567891011121314
字符:0123456789=+- × ÷
如果能识别这些,基本上能满足整数的加减乘除运算了。
好了,图片哪里来?!
是啊,图片哪里来?
吓得我差点从梦里醒来,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)# %% 生成图片defmakeImage(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 inrange(-10,10,1):# 每个字符都生成图片
makeImage(label_dict, path_font_file, rotate = k)
上面纯代码不到30行,相信大家应该能看懂!看不懂不是我的读者。
核心代码就是画文字。
draw.text((x,y), char, (255, 255, 255), font)
翻译一下就是:使用某字体在黑底图片的(x,y)位置写白色的char符号。
核心逻辑就是三层循环。
#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;}#mermaid-svg-DEUFBhZUwl8W6J0f {
color: rgba(0, 0, 0, 0.75);
font: ;
}
取一种字体
取一个角度
取一个字符
再来一次
再来一次
再来一次
字体库
角度库
字符库
写到图片上
如果代码你运行的没有问题,最终会生成如下结果:
好了,数据准备好了。总共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
# %% 构建模型defcreate_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
这个模型的序列是下面这样的,作用是输入一个图片数据,经过各个层揉搓,最终预测出这个图片属于哪个分类。
#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;}#mermaid-svg-OwCeohPhZpAeMseo {
color: rgba(0, 0, 0, 0.75);
font: ;
}
输入: 图片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,inputshape=(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个通道。给定一个输入后,输出为每个分类的概率。
#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;}#mermaid-svg-KOlq3k9O6H0Pw6m3 {
color: rgba(0, 0, 0, 0.75);
font: ;
}
其他类型的层
全连接层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轴投影,传入图片数组,图片经过二值化并反色defimg_y_shadow(img_b):### 计算投影 ###(h,w)=img_b.shape
# 初始化一个跟图像高一样长度的数组,用于记录每一行的黑点个数
a=[0for z inrange(0,h)]# 遍历每一列,记录下这一列包含多少有效像素点for i inrange(0,h):for j inrange(0,w):if img_b[i,j]==255:
a[i]+=1return 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个像素点。
如果我们想要从视觉呈现出来怎么处理呢?那可以把它立起来拉直画出来。
#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;}#mermaid-svg-QK2WyvOlyH4KUSp0 {
color: rgba(0, 0, 0, 0.75);
font: ;
}
1
.
5
.....
2
..
# 展示图片defimg_show_array(a):
plt.imshow(a)
plt.show()# 展示投影图, 输入参数arr是图片的二维数组,direction是x,y轴defshow_shadow(arr, direction ='x'):
a_max =max(arr)if direction =='x':# x轴方向的投影
a_shadow = np.zeros((a_max,len(arr)), dtype=int)for i inrange(0,len(arr)):if arr[i]==0:continuefor j inrange(0, arr[i]):
a_shadow[j][i]=255elif direction =='y':# y轴方向的投影
a_shadow = np.zeros((len(arr),a_max), dtype=int)for i inrange(0,len(arr)):if arr[i]==0:continuefor j inrange(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 根据投影找区域
最有效的方法,往往还得用循环来实现。
上面投影那张图,你如何计算哪里到哪里是一行,虽然肉眼可见,但是计算机需要规则和算法。
# 图片获取文字块,传入投影列表,返回标记的数组区域坐标[[左,上,右,下]]defimg2rows(a,w,h):### 根据投影切分图块 ###
inLine =False# 是否已经开始切分
start =0# 某次切分的起始索引
mark_boxs =[]for i inrange(0,len(a)):if inLine ==Falseand a[i]>10:
inLine =True
start = i
# 记录这次选中的区域[左,上,右,下],上下就是图片,左右是start到当前elif i-start >5and a[i]<10and inLine:
inLine =Falseif 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 区域标记defcut_img(img, mark_boxs):
img_items =[]# 存放裁剪好的图片for i inrange(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]]
图片裁剪,参数是数组的
[上:下,左:右]
,获取的数据还是二维的数组。
如果保存下来:
# 保存图片defsave_imgs(dir_name, imgs):if os.path.exists(dir_name):
shutil.rmtree(dir_name)ifnot os.path.exists(dir_name):
os.makedirs(dir_name)
img_paths =[]for i inrange(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去看。
defdivImg(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 inrange(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 inrange(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]]]]
它是有结构的。它的结构是:
#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;}#mermaid-svg-iZaEdgc9jTIppBrG {
color: rgba(0, 0, 0, 0.75);
font: ;
}
第一层-数组
行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 inrange(0,len(all_char_imgs)):
row_imgs = all_char_imgs[i]# 遍历块for j inrange(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', '=']defcalculation(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:ifstr(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)位置,以特定颜色和大小。
# 绘制文本defcv2ImgAddText(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 inrange(0,len(all_char_imgs)):
row_imgs = all_char_imgs[i]# 遍历块for j inrange(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)# 根据结果设置字体颜色ifstr(result)=="√":
color =(0,255,0)elifstr(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)
结果是下面这样的:
版权归原作者 newlw 所有, 如有侵权,请联系我们删除。