纸张图像边框提取、摆正以及是否填写检测-python

纸张图像边框提取、摆正以及是否填写检测-python前言 前面也分享过一些 opencv 的一些图像处理方式 那我今天介绍一个用 opencv 来提取合同 纸张或者证件的边框并去掉背景 将图像摆正的做法 然后也根据这个思路 介绍下校验是否填写 或者签名的一个思路 话不多说 来看下实现的效果图 图片是我无聊的时候乱写的纸 逃

大家好,我是讯享网,很高兴认识大家。


前言


讯享网

首先来检验介绍一下实现的步骤
1、将图像转为固定高度的图片(这一步是为了适配边缘检测的阈值,下面会介绍)
2、用opencv的边缘检测算法提取边缘
3、找出闭合的轮廓并计算他们的面积,提取最大面积
4、拟合最大面积的的四边形的4个顶点
5、通过opencv的透视变化拟合出长方形的纸张边缘

一、边缘检测

import cv2 import numpy as np # 固定尺寸 def resizeImg(image, height=900):     h, w = image.shape[:2]     pro = height / h     size = (int(w * pro), int(height))     img = cv2.resize(image, size)     return img # 边缘检测 def getCanny(image):     # 高斯模糊     binary = cv2.GaussianBlur(image, (3, 3), 2, 2)     # 边缘检测     binary = cv2.Canny(binary, 60, 240, apertureSize=3)     # 膨胀操作,尽量使边缘闭合     kernel = np.ones((3, 3), np.uint8)     binary = cv2.dilate(binary, kernel, iterations=1)     return binary path = r'C:\Users\wzg\Desktop\test.jpg' outpath = r'C:\Users\wzg\Desktop\getCanny.jpg' img = cv2.imread(path) img = resizeImg(img) print('shape =', img.shape) binary_img = getCanny(img) cv2.imwrite(outpath, binary_img) # output:    shape = (900, 420, 3)

讯享网


二、找出纸张边缘

讯享网# 代码承接上文 # 求出面积最大的轮廓 def findMaxContour(image):     # 寻找边缘     _, contours, _ = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)     # 计算面积     max_area = 0.0     max_contour = []     for contour in contours:         currentArea = cv2.contourArea(contour)         if currentArea > max_area:             max_area = currentArea             max_contour = contour     return max_contour, max_area path = r'C:\Users\wzg\Desktop\test.jpg' outpath = r'C:\Users\wzg\Desktop\findMaxContour.jpg' img = cv2.imread(path) img = resizeImg(img) binary_img = getCanny(img) max_contour, max_area = findMaxContour(binary_img) cv2.drawContours(img, max_contour, -1, (0, 0, 255), 3) cv2.imwrite(outpath, img)


三、找出四边形的四个顶点

# 代码承接上文 # 多边形拟合凸包的四个顶点 def getBoxPoint(contour):     # 多边形拟合凸包     hull = cv2.convexHull(contour)     epsilon = 0.02 * cv2.arcLength(contour, True)     approx = cv2.approxPolyDP(hull, epsilon, True)     approx = approx.reshape((len(approx), 2))     return approx path = r'C:\Users\wzg\Desktop\test.jpg' outpath = r'C:\Users\wzg\Desktop\getBoxPoint.jpg' img = cv2.imread(path) img = resizeImg(img) binary_img = getCanny(img) max_contour, max_area = findMaxContour(binary_img) boxes = getBoxPoint(max_contour) for box in boxes:    cv2.circle(img, tuple(box), 5, (0, 0, 255), 2) print(boxes) cv2.imwrite(outpath, img)


四、透视变换

讯享网# 代码承接上文 # 适配原四边形点集 def adaPoint(box, pro):     box_pro = box     if pro != 1.0:         box_pro = box/pro     box_pro = np.trunc(box_pro)     return box_pro # 四边形顶点排序,[top-left, top-right, bottom-right, bottom-left] def orderPoints(pts):     rect = np.zeros((4, 2), dtype="float32")     s = pts.sum(axis=1)     rect[0] = pts[np.argmin(s)]     rect[2] = pts[np.argmax(s)]     diff = np.diff(pts, axis=1)     rect[1] = pts[np.argmin(diff)]     rect[3] = pts[np.argmax(diff)]     return rect # 计算长宽 def pointDistance(a, b):     return int(np.sqrt(np.sum(np.square(a - b)))) # 透视变换 def warpImage(image, box):     w, h = pointDistance(box[0], box[1]), \            pointDistance(box[1], box[2])     dst_rect = np.array([[0, 0],                          [w - 1, 0],                          [w - 1, h - 1],                          [0, h - 1]], dtype='float32')     M = cv2.getPerspectiveTransform(box, dst_rect)     warped = cv2.warpPerspective(image, M, (w, h))     return warped path = r'C:\Users\wzg\Desktop\test.jpg' outpath = r'C:\Users\wzg\Desktop\result.jpg' image = cv2.imread(path) ratio = 900 / image.shape[0] img = resizeImg(image) binary_img = getCanny(img) max_contour, max_area = findMaxContour(binary_img) boxes = getBoxPoint(max_contour) boxes = adaPoint(boxes, ratio) boxes = orderPoints(boxes) # 透视变化 warped = warpImage(image, boxes) cv2.imwrite(outpath, warped)


五、其他

解决思路是这样的:
1、将两张合同通过我上面的算法提取出正四边形的纸张
2、通过合同的预设点设置检测区域(比如上面在空白合同的位置标注矩形的左上角和右下角)
3、裁剪出标注区域(同样像素)并做二值化处理(转为只有0 和 1的矩阵)
4、因为写了的和没写的合同像素值有差别,那么如校验的大于一个阈值,那么就签了名,反之亦然
解决效果可以如下示(我就不贴代码了,逃~)


总结

小讯
上一篇 2025-03-28 16:38
下一篇 2025-01-26 11:52

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/62002.html