图像倾斜可以分为两种情况,一种是平面倾斜,这种情况下拍照设备与试卷平行,拍出来的图像只需要进行旋转即可完成矫正;另一种是Z轴倾斜,这种情况下拍照设备与试卷存在一定的角度,拍出来的图像要先进行透视变换,然后再进行旋转等操作才可以完成矫正。
图像倾斜矫正关键在于根据图像特征自动检测出图像倾斜方向和倾斜角度。
对于平面倾斜,先利用边缘(轮廓)检测算法算法找到图像的边界,然后利用 Radon变换法(基于投影的方法) 、 Hough变换法 、线性回归法等找到倾斜角度,然后再利用 仿射变换 进行旋转。
对于Z轴倾斜,先利用边缘(轮廓)检测算法找到图像的边界,然后利用 透视变换 把视平面上的点投影到现实平面,然后再利用仿射变换进行旋转。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import numpy as np
import cv2
img = cv2.imread('./qingxie.png')
img = cv2.GaussianBlur(img,(3,3),0)#高斯模糊 去噪 以免影响边缘检测
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,250,apertureSize = 3)#边缘检测
cv2.imwrite("canny.jpg", edges)
原图:
边缘检测后:
cv2.Canny()函数的函数原型为:
edge = cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient ]]])
其中maxVal用于检测图像中明显的边缘,但一般情况下检测的效果不会那么完美,边缘检测出来是断断续续的。所以这时候用minVal将这些间断的边缘连接起来。
可选参数中apertureSize就是Sobel算子的大小。而L2gradient参数是一个布尔值,如果为真,则使用更精确的L2范数进行计算(即两个方向的倒数的平方和再开放),否则使用L1范数(直接将两个方向导数的绝对值相加)。
python Canny参考资料
可以看到,在上述步骤后,内部线条也被检测了出来,下面就利用霍夫变换得到边缘(霍夫变换参考):