原文链接 https://mzucker.github.io/2016/10/11/unprojecting-text-with-ellipses.html
将普通 2D 文本图片转换成类似 3D 文本图片的映射过程叫做单应性。
借用原文中星球大战的图片, 这就是转换之后的图片.
对每个像素点而言, 在 2D 到 3D 转换过程中满足下列式子
x ′ = a x + b y + c g x + h y + 1 , y ′ = d x + e y + f g x + h y + 1 x' = \frac{ax+by+c}{gx+hy+1}, y'=\frac{dx+ey+f}{gx+hy+1} x′=gx+hy+1ax+by+c,y′=gx+hy+1dx+ey+f
x , y x,y x,y 表示转换前的像素坐标
x ′ , y ′ x',y' x′,y′ 表示转换后的像素坐标
有未知参数 a , b , c , d , e , f , g , h a,b,c,d,e,f,g,h a,b,c,d,e,f,g,h
这些参数控制着图片是如何转换的, 其中就有
a a a 控制图片左右拉伸, e e e 控制图片上下拉伸
b , d b,d b,d 控制图片左右倾斜, 类似于矩阵变为平行四边形的过程
c c c 控制图片左右移动, f f f 控制图片上下移动
g g g 控制图片左右透视失真, h h h 控制图片透视失真
上面列出的星球大战字幕图片就是由单由参数 h h h 控制转换所得
我们可以找到一个完美的算法求出式子中的所有参数, 然后就能将图片还原,但是这是理想状态. 所以原文提出了一个很棒的思路.
我们现在拍摄了一张照片, 然后对它进行三步骤的处理.
步骤一 : 解决透视失真的问题
步骤二 : 解决图片旋转的问题
步骤三 : 解决图片中文字倾斜的问题
首先通过 opencv 获取到图片中字符的轮廓 (这一步可能会有其他干扰).
作者提出了一个观点, 当处理后的图片中每一个字符各占面积几乎相等时就认为解决了透视失真这个问题. 转换成数学表达式则是
通过找到 g , h g,h g,h 两个参数, 使得
S t o t a l = ∑ i = 1 n ( A i − A ˉ ) 2 S_{total} = \sum_{i=1}^{n}(A_i - \bar{A})^2 Stotal=i=1∑n(Ai−Aˉ)2
最小, 其中 S t o t a l S_{total} Stotal 表示面积差总平方和, A i A_i Ai 表示第 i i i 个字符的面积, A ˉ \bar{A} Aˉ 表示字符平均面积.
!!! 这里更准确一点应该被称为轮廓面积, 而不是字符面积, 因为通过 opencv 会检测到其他干扰项. 我们假设最佳情况就是只检测到字符. 以下步骤都是居于此来完成.
椭圆方程
f ( x , y ) = A x 2 + B x y + C y 2 + D x + E y + F = 0 f(x,y) = Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0 f(x,y)=Ax2+Bxy+Cy2+Dx+Ey+F=0
通过一定手段使得列入计算的字符转换成相同面积的椭圆, 用椭圆方程中的 A , B , C , D , E , F A,B,C,D,E,F A,B,C,D,E,F六个参数来描述该字符. 由此构建出一个矩阵用于解决透视失真问题.
霍夫变换
用凸包表示一个字符, 构建一个矩阵使得图片中字符宽度最小化. 构建出的矩阵中的参数就是单应性所提到的参数 b , d b,d b,d
输入图片
获取字符轮廓和面积
字符轮廓进行椭圆化处理, 解决透视失真
霍夫变换, 解决图片旋转问题
凸包代理, 解决文字倾斜问题
处理结果
当使用如下图片进行处理时
在处理这个图片时就会误把边框进行处理, 且不能检测到所有字符.
未处理的图片识别
处理后的图片识别
未处理的图片识别
处理后的图片识别
未处理的图片识别 (不能识别)
处理后的图片识别
未处理的图片识别
处理后的图片识别