温州网站建设大全,wordpress正在连接,网络运营工程师,重庆公司建设网站文章目录1 概述2 流程解读2.1 生成文字mask2.2 plane2xyz的bug2.3 文字上色2.4 图像融合参考资料1 概述
SynthText是OCR领域生成数据集非常经典#xff0c;且至今看来无人超越的方法。整体可以分为三个大的步骤#xff0c;分别是生成文字的mask#xff0c;这里用到了图像的…
文章目录1 概述2 流程解读2.1 生成文字mask2.2 plane2xyz的bug2.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) 会对分割区域进行筛选得到可用于分割的区域。
筛选分为两步 1regions TextRegions.filter(seg,area,label) 筛除面积过小或者长宽比极端的区域 2regions 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所示。
图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表示平面axbyczd0axbyczd0axbyczd0。 图2-9 图像平面和实际平面示意图图像上点(xi,yi)(x_i, y_i)(xi,yi)经过原点的直线可以表示为 x−0xi−0y−0yi−0z−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} xi−0x−0yi−0y−0zi−0z−0(2-1)
于是可以有
xxizzi,yyizzi,zif(2-2)x \frac{x_iz}{z_i}, y \frac{y_iz}{z_i}, z_if \tag{2-2} xzixiz,yziyiz,zif(2-2)
将式(2−2)(2-2)(2−2)代入axbyczd0axbyczd0axbyczd0计算直线与planar scene的交点可以得到
z−daxifbyifc(2-3)z -\frac{d}{a\frac{x_i}{f} b\frac{y_i}{f} c} \tag{2-3} z−afxibfyicd(2-3)
代码中plane[2]就是cccplane[3]就是ddd所有原来是反的。
代码中的xy_ray就是xif\frac{x_i}{f}fxi和yif\frac{y_i}{f}fyi。要求xxx和yyy再利用式(2−2)(2-2)(2−2)就可以了这也就有了
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为表示方便称为colors。colors[:, :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