SynthText流程解读 - 不看代码不知道的那些事

文章目录

    • 1 概述
    • 2 流程解读
      • 2.1 生成文字mask
      • 2.2 plane2xyz的bug
      • 2.3 文字上色
      • 2.4 图像融合
    • 参考资料

1 概述

SynthText是OCR领域生成数据集非常经典,且至今看来无人超越的方法。整体可以分为三个大的步骤,分别是生成文字的mask,这里用到了图像的分割信息来选取区域,图像的深度信息来拟合该区域的3D平面,单应性变换来旋转平面;文字上色,用于选取适合背景色的文字颜色;图像融合,用来了泊松图像融合。

整体思路是非常棒的,挑不出毛病。目前有些文本贴图不真实,主要原因是分割的区域不是同一个平面内的区域,加之图像的深度信息也不准,导致了3D平面拟合不准,文字贴上去也就不准了。

2 流程解读

2.1 生成文字mask

这部分需要用到图像的分割信息和深度信息,示意图如图2-1所示。

分割和深度信息示意图

图2-1 分割和深度信息示意图

在当前的场景当中,最好的分割结果是可以把同一个物体的不同平面分割出来;次好的结果是把同一个平面分割出来,可以是不同物体。比如一座房子,不同的墙最好可以单独分开,两座平行的房子上平行的墙,分割在一起也是可以的。对于曲面,整个分割成一个instance就可以了,这个可以通过无法拟合成一个平面来删除。

最好的深度信息,就是准确的深度信息。

xyz = su.DepthCamera.depth2xyz(depth) 这步就是将深度信息转化为空间3D坐标。

regions = TextRegions.get_regions(xyz,seg,area,label) 会对分割区域进行筛选,得到可用于分割的区域。

筛选分为两步:
(1)regions = TextRegions.filter(seg,area,label) 筛除面积过小,或者长宽比极端的区域
(2)regions = TextRegions.filter_depth(xyz,seg,regions) 筛除区域内的点不能构成一个平面的区域,也就是曲面或者多个面,这里会得到平面的拟合结果

筛选后的区域示意图如下图2-2所示。
选择区域示意图

图2-2 选择区域示意图

regions = self.filter_for_placement(xyz,seg,regions) 对图2-2中的区域进行warp的变换,并获取warp变换所使用的单应性变换矩阵。

这部分有些难理解,我这里举个例子。比如我们有原图2-3。

例子原图

图2-3 例子原图

我们选取的区域为图2-4,也就是床下面那块黑影。
例子选取的区域

图2-4 例子选取的区域

该区域的部分截取下来为图2-5。
例子区域截图

图2-5 例子区域截图

该区域拟合的平面为图2-6。

例子区域拟合的平面

图2-6 例子区域拟合的平面

将图2-6中的平面绕中点转正,也就是转到平面的法向量对准我们,即法向量与Y轴平行。记录下这个变换过程所用到的单应性变换矩阵及其逆变换矩阵。转正后的图片如下图2-7所示。

例子区域变换结果图

图2-7 例子区域变换结果图

其mask如图2-8所示。
例子区域变换mask

图2-8 例子区域变换mask结果图

我们这里得到的单应性变换矩阵就是图2-4变为图2-8的矩阵。接下来只要往图2-8上贴上文字,然后整体变回图2-4就可以了。

这部分直接关系到了文字贴上图片能否有背景在同一个空间的效果。有许多的深度信息和分割信息是不准的,如果可以优化的话,可以有更好的效果。拿自动驾驶的数据集去当背景图应该是个不错的选择。

2.2 plane2xyz的bug

在将预估出来的平面转正的时候,发现转出来的z的值总是不同的,这和我们的理解是由偏差了。查了半天问题,发现是place2xyz代码中的两个系数写反了。修正后的代码为

@staticmethod
def plane2xyz(center, ij, plane):"""converts image pixel indices to xyz on the PLANE.center : 2-tupleij : nx2 int arrayplane : 4-tuplereturn nx3 array."""ij = np.atleast_2d(ij)n = ij.shape[0]ij = ij.astype('float')xy_ray = (ij-center[None,:]) / DepthCamera.fz = -plane[3]/(xy_ray.dot(plane[:2])+plane[2])# z = -plane[2]/(xy_ray.dot(plane[:2])+plane[3])xyz = np.c_[xy_ray, np.ones(n)] * z[:,None]return xyz

接下来解释一下为何如此。如下图2-9,我们的目的是将左边图像平面上的点,转换到右侧的实际平面上,中间的原点是小孔,原点到左侧图像的距离为焦距。实际平面就是代码中的plane,它有四个值,分别是a,b,c,da, b, c, da,b,c,d,表示平面ax+by+cz+d=0ax+by+cz+d=0ax+by+cz+d=0

plane

图2-9 图像平面和实际平面示意图

图像上点(xi,yi)(x_i, y_i)(xi,yi)经过原点的直线可以表示为
x−0xi−0=y−0yi−0=z−0zi−0(2-1)\frac{x-0}{x_i - 0} = \frac{y-0}{y_i - 0} = \frac{z-0}{z_i - 0} \tag{2-1} xi0x0=yi0y0=zi0z0(2-1)

于是可以有

x=xizzi,y=yizzi,zi=f(2-2)x = \frac{x_iz}{z_i}, y = \frac{y_iz}{z_i}, z_i=f \tag{2-2} x=zixiz,y=ziyiz,zi=f(2-2)

将式(2−2)(2-2)(22)代入ax+by+cz+d=0ax+by+cz+d=0ax+by+cz+d=0,计算直线与planar scene的交点可以得到

z=−daxif+byif+c(2-3)z = -\frac{d}{a\frac{x_i}{f} + b\frac{y_i}{f} + c} \tag{2-3} z=afxi+bfyi+cd(2-3)

代码中plane[2]就是cccplane[3]就是ddd,所有原来是反的。

代码中的xy_ray就是xif\frac{x_i}{f}fxiyif\frac{y_i}{f}fyi。要求xxxyyy,再利用式(2−2)(2-2)(22)就可以了,这也就有了

xyz = np.c_[xy_ray, np.ones(n)] * z[:,None]

把这行代码改了,有奇效!

2.3 文字上色

我们往图2-8上贴文字的时候,需要确定文字的字体和颜色,字体随机即可,文字的颜色是需要根据背景色来确定的。

render_res = self.text_renderer.render_sample(font,collision_mask) 就是贴文字的过程。这部分的位置选取,字体选取,文字尺寸什么的就不说了,说一下这个文字颜色的选取。

选取颜色的过程在 def color_text(self, text_arr, h, bg_arr) 函数当中,这里依赖于一个文件 colors_new.cp ,这个文件中存储的是shape为 (4941, 12) 的array,为表示方便称为colorscolors[:, :6]表示颜色A的RGB值和各通道方差,colors[:, 6:12]表示颜色B的RGB值和各通道方差。表示背景色为A时,文字颜色可以用B;背景色为B时,文字颜色可以用A。

在寻找最匹配的背景色的时候,使用了LAB颜色空间,也就是将所有的RGB值转为到了LAB空间,然后取候选区域的所有LAB值的平均作为背景色LAB色,然后根据LAB色的距离来选取最合适的RGB值。方差就是取值的时候,加上方差,来得到多样性的作用。

这部分是可以优化的,背景色直接取LAB平均也太暴力了,万一颜色比较花,或者有极端值,就会影响很大。可以改成聚类或者mmcq的方式来获取主体色作为背景色。

2.4 图像融合

直到上述部分,文字仍旧还是和背景分离的,得到带有文本的图像和贴图的区域之后,使用了泊松融合的方式来自然融合两图,这里不推荐使用cv2.seamlessClone,因为cv2.seamlessClone暴露的参数太少了,作者自己写的blit_images就非常好,scale_grad 这个参数可以用来调整前景的梯度,也就是前景贴到背景上的明显程度。

比如有前景图和背景图,如图2-10所示。
前景图和背景图

图2-10 前景图和背景图

使用不同的 scale_grad 参数和 cv2.seamlessClone 的效果如下图2-11所示,cv2.seamlessClone甚至丢失掉了边界。
泊松融合对比图

图2-11 泊松融合对比图

将文本贴到warp过的区域之后,就可以使用单应性变换逆矩阵,把warp的区域还原回去,得到最终的效果图。

最终效果图

图2-12 泊松融合对比图

这么好的效果,其实是挑选过结果的,实际情况下,还是有很多都是效果没那么出色的。怪就怪分割和深度信息不准。

参考资料

[1] Synthetic Data for Text Localisation in Natural Images
[2] https://github.com/ankush-me/SynthText

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/470500.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python if name main 的作用_Python中if __name__ == '__main__':的作用和原理

if __name__ __main__:的作用 一个python文件通常有两种使用方法,第一是作为脚本直接执行,第二是 import 到其他的 python 脚本中被调用(模块重用)执行。因此 if __name__ main: 的作用就是控制这两种情况执行代码的过程&#x…

1+X web中级 Laravel学习笔记——Eloquent ORM查询、更新、删除、新增

Eloquent ORM简介 larave1所自带的Eloquent oRM是一个非常优美简洁的ActiveRecord实现,用来实现数据库的操作他的每个数据的表都有对应的模型(model)用于数据表的交互模型的建立 一、Eloquent ORM的查询 二、Eloquent ORM新增 通过模型新增…

使用复合设计模式扩展持久化的CURD,Select能力

大家可能会经常遇到接口需要经常增加新的方法和实现,可是我们原则上是不建议平凡的增加修改删除接口方法,熟不知这样使用接口是不是正确的接口用法,比如我见到很多的项目分层都是IDAL,DAL,IBLL,BLL&#xf…

1+X web中级 Laravel学习笔记——blade模版

一、blade模版简介 Blade是larave1提供的一个既简单又强大的模版引擎和其他的流行的php模版引擎不一样,blade并不限制你在视图(view)中使用原生php代码 二、 模版继承 section yield extents parent 三、基本语法以及include的使用 1…

matplotlib 散点图_matplotlib画图 绘制散点图案例

假设通过爬虫你获取到了北京2016年3,10月份 每天白天的最高气温(分别位于列表a,b), 那么此时如何寻找出气温和随时间(天)变化的某种规律? a [11,17,16,11,12,11,12,6,6,7,8,9,12,15,14,17,18,21,16,17,20,14,15,15,15,19,21,22,22,22,23] b [26,26,28,19,21,17,16,19,18,20,…

深度学习基础-1

文章目录0 前言1 图像分类简介1.1 什么是图像分类1.2 图像分类任务的难点1.3 分类任务的评价指标1.3.1 Accuracy1.3.2 Precision和Recall1.3.3 F1 Score1.4 分类图像模型总体框架2 线性分类器2.1 图像的表示方法2.2 Cifar10数据集介绍2.3 分类算法输入2.4 线性分类器3 损失函数…

一、PHP基础——表单传值、上传文件

表单传值 概念: 表单传值即浏览器通过表单元素将用户的选择或者输入的数据提交给后台服务器语言。 为什么使用表单传值? 动态网站(Web2.0)的特点就是后台根据用户的需求定制数据,所谓的“需求”就是用户通过当前的选择或者输入的数据信息&a…

利用微信搜索抓取公众号文章(转载)

来源:http://www.shareditor.com/blogshow/44 自动收集我关注的微信公众号文章 2016.7.14 更新 搜狐微信增加对referer验证 var page require(webpage).create();page.customHeaders{"referer":"http://weixin.sogou.com/weixin?oq&query关键词…

二、PHP基础——连接msql数据库进行增删改查操作 实战:新闻管理项目

Mysql扩展 PHP针对MySQL数据库操作提供的扩展:允许PHP当做MySQL的一个客户端连接服务器进行操作。 连库基本操作 连接数据库服务器 1)资源 mysql_connect(服务器地址,用户名,密码) 连接资源默认也是超全局的,任何地方都…

深度学习基础-2

文章目录0 前言1 全连接神经网络2 激活函数2.1 Sigmoid2.2 Tanh2.3 ReLU2.4 Leaky ReLU3 交叉熵损失4 计算图与反向传播4.1 计算图4.2 梯度消失与梯度爆炸4.3 动量法5 权重初始化5.1 全零初始化5.2 标准随机初始化5.3 Xavier初始化5.4 Kaming初始化6 批归一化7 参考资料0 前言 …

三、PHP基础——HTTP协议 文件编程

一、HTTP协议初步认识 HTTP协议概念 HTTP协议,即超文本传输协议(Hypertext transfer protocol)。是一种详细规定了浏览器和万维网(WWW World Wide Web)服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议。 HTTP协议是用于从WWW服务器传…

四、PHP基础——会话技术Cookie 和 Session

会话技术初步认识 会话技术介绍 web会话可简单理解为:用户开一个浏览器,访问某一个web站点,在这个站点点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。 HTTP协议的特点是…

python三级菜单设计题目_Python三级菜单

广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 三级菜单:打印省、市、县三级菜单。 可返回上一级,可随时退出程序首先准备基础数据zone{山东:{青…

c#复习-2

输入三个学生的信息学号、姓名、分数从大到小排序 1 using System;2 using System.Collections;3 using System.Collections.Generic;4 using System.Linq;5 using System.Text;6 7 namespace 复习CS8 {9 class Program 10 { 11 struct Student 12 { 1…

long类型python_Python类型long vs C'long long'

I would like to represent a value as a 64bit signed long, such that values larger than (2**63)-1 are represented as negative, however Python long has infinite precision. Is there a quick way for me to achieve this? 解决方案>>> from ctypes import …

Vue中富文本编辑器的使用

基于 Vue 的富文本编辑器有很多,例如官方就收录推荐了一些: https://github.com/vuejs/awesome-vue#rich-text-editing 。 这里我们以 element-tiptap 为例。 GitHub 仓库:https://github.com/Leecason/element-tiptap 在线示例&#xff1a…

Vue项目中使用Echarts(一)

Echarts官方文档 1. 安装Echarts 在cmd命令行输入: npm install echarts --save 2. 代码中使用 注意:import 引入echarts 包时,不要使用 import echarts from ‘echarts’ 而要使用import * as echarts from echarts 否则会报错如下: 3. 页…

Google Guava缓存实现接口的限流

一.项目背景 最近项目中需要进行接口保护,防止高并发的情况把系统搞崩,因此需要对一个查询接口进行限流,主要的目的就是限制单位时间内请求此查询的次数,例如1000次,来保护接口。 参考了 开涛的博客聊聊高并发系统限流…

javaweb 常用jar包_使用javaweb写一个登录案例

下载地址:https://gitee.com/dl_shrimp/java_web_login_case.githttps://www.zhihu.com/video/1241780888599699456讲一下如何使用javaweb写一个登录案例Dao就是用来操作数据库的一些类的统称(1)DAO是Data Access Object数据访问接口。数据访…

Vue项目中使用图片裁切器 cropperjs (头像裁切)

cropperjs官方文档 cropperjs结合element-ui 组件后的显示效果: 1. npm 安装 cropperjs cmd命令行输入:npm install cropperjs --save 2. 导入相关js和css文件 import cropperjs/dist/cropper.css import Cropper from cropperjs3. 用块元素(容器&…