Mythsman


乐极生悲,苦尽甘来。


用投影法矫正字符旋转

这是段简单的代码,目的是处理旋转验证码的问题,主要思想就是通过将字符以45°到135°的角度投影下来,得到一系列的投影范围,然后得到这当中投影长度最小的一个角度。这个角度我们就可以简单的把他看成是字符的偏转角。然后用这个角度通过仿射变换得到矫正后的字符。

代码

#coding=utf-8
import cv2,os,sys,Image,math
import numpy as np
from pylab import *
%matplotlib inline

def getBinary(path):#传入图片名,返回二值化的图片
 im=cv2.imread(path,0)
 thresh,im=cv2.threshold(255-im,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
 return im

def shadow(im,angel):#传入图像im以及角度(角度制)angle,返回图像在该角度下的投影长度
    x=[]
    height , width = im.shape
    for i in xrange(height):
        for j in xrange(width):
            if im[i][j]==255:
                x.append(j-1.0*i/math.tan(math.radians(angel)))
    x=np.array(x)
    return x.max()-x.min()

def shadowTest():#测试shadow函数,需要weibo文件夹下的图片
    directory='weibo'
    pics=os.listdir(directory)
    for pic in pics[:10]:
        im=getBinary(os.path.join(directory,pic))
        print shadow(im,50)
        figure()
        gray()
        imshow(im)

def getAngle(im):#传入图片,返回使他投影最小的角度
    minShadow=500
    ans=90
    for angle in np.linspace(45,135,91):#我这里范围设置的是45到135度,分度值是1度
        thisShadow=shadow(im,angle)
        if minShadow>thisShadow:
            ans=angle
            minShadow=thisShadow
    return ans

def getAngleTest():#测试getAngle函数
    directory='weibo'
    pics=os.listdir(directory)
    for pic in pics[:5]:
        im=getBinary(os.path.join(directory,pic))
        print getAngle(im)
        figure()
        imshow(im)

def affine(im):#将结合上面的函数,输入图片,输出矫正后的图片
 height,width=im.shape
 angle=getAngle(im)
 #下面是仿射变换,通过确定三点的原值和新值来确定变换的过程,这里我们选取的三点是中心点,顶部中心点,和左部中心点。
 pts1=np.float32([[width/2,height/2],[width/2,0],[0,height/2]])
 pts2=np.float32([[width/2,height/2],[width/2+height/2/math.tan(math.radians(angle)),0],[0,height/2]])
 M=cv2.getAffineTransform(pts1,pts2)
 dst=cv2.warpAffine(im,M,(width,height))

 return dst

def affineTest():#测试affine函数
 directory='weibo'
 pics=os.listdir(directory)
 for pic in pics[:1]:
 im=getBinary(os.path.join(directory,pic))
 dst=affine(im)
 gray()
 figure()
 imshow(np.hstack([im,dst]))
 axis('off')

affineTest()#测试效果

效果图

可以发现这个方法还是有点效果的。