这是段简单的代码,目的是处理旋转验证码的问题,主要思想就是通过将字符以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()#测试效果
可以发现这个方法还是有点效果的。