本文实例为大家分享了opencv实现文档矫正的具体代码,供大家参考,具体内容如下
原始文档
矫正后文档
思路:只要获得倾斜文档的倾斜角度,然后通过仿射变化旋转一下就可以实现矫正了,这里获取倾斜角度的方法有两个,下面分别介绍
1、利用霍夫变换,文档内容都是平行的,首先利用利用霍夫变换检测直线,然后将所有直线的平均倾斜角度当做文档的倾斜角度,最后再进行仿射变换就可以了。
import cv2
import numpy as np
def imshow(img):
cv2.imshow("img",img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread("2.webp",1)
img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
img2 = img.copy()
img_canny = cv2.Canny(img,75,200)
img_line = cv2.HoughLines(img_canny,1,np.pi/180,280)
average = 0
for line in img_line:
for rho,theta in line:
average = average + theta
average = average / len(img_line)
angel = average/np.pi * 180 - 90
def rotateImg(img,angel):
rows, cols = img.shape
M = cv2.getRotationMatrix2D(((cols - 1) / 2.0, (rows - 1) / 2.0), angel, 1) # 旋转中心x,旋转中心y,旋转角度,缩放因子
img = cv2.warpAffine(img, M, (cols, rows),borderValue = (255,255,255)) #在内存里完成了旋转
imshow(img)
rotateImg(img2,angle)
2、求文档内容的最小包围矩形。首先检测轮廓,利用形态学操作求mask,然后再检测轮廓,求最下包围矩形,最小包围矩形会返回一个倾斜角度(度数,霍夫变换的倾斜角度是弧度制),可以对轮廓进行筛选,将面积最大的轮廓的倾斜角度作为文档的倾斜角度,然后做仿射变换。
import cv2
import numpy as np
def imshow(img):
cv2.imshow("img",img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread("2.webp",1)
img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
img2 = img.copy()
imgth = cv2.threshold(img,0,255,cv2.THRESH_OTSU|cv2.THRESH_BINARY_INV)[1]
kernel = np.ones((17,17))
img_open = cv2.morphologyEx(imgth,cv2.MORPH_CLOSE,kernel,10)
# imshow(img_open)
cons = cv2.findContours(img_open,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)[0]
areas = []
for con in cons:
area = cv2.contourArea(con)
areas.append(area)
index = areas.index(max(areas))
# 度数形式,霍夫变换的返回值是弧度制
rect = cv2.minAreaRect(cons[index])
angle = rect[2]
mat = cv2.getRotationMatrix2D((img.shape[1]/2,img.shape[0]/2),angle,1)
img_fin = cv2.warpAffine(img,mat,(img.shape[1],img.shape[0]),borderValue = (255,255,255))
imshow(img_fin)
补充:
利用仿射变换实现图像旋转指定度数
mat = cv2.getRotationMatrix2D(center,angle,c) (center: 旋转中心,angle:旋转角度,c:缩放大小)
img_final = cv2.warpAffine(img,mat, (img.shape[1],img.shape[0]), borderValue = (255,255,255)) (borderValue为可选参数,填充色,默认为黑色)
另外旋转指定90,180,270可以使用transpose、flip来实现
旋转90度(顺时针)
img = cv2.transpose(img)
res_img = cv2.flip(img,1)
旋转180度
img = cv2.flip(img,0)
img = cv2.flip(img,1)