1 Star 0 Fork 197

qi/doc_scanner_homework

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
doc_scanner.py 4.71 KB
一键复制 编辑 原始数据 按行查看 历史
qi 提交于 2023-06-11 11:25 . 完善
'''
"doc_scanner.py" 文件中的 DocScanner 类提供了文档扫描的核心功能,功能包括
- 加载图片
- 找到文档的角落
- 裁剪图片
- 通过将文档扫描功能封装在一个独立的类中,我们可以将其作为一个模块,方便在其他项目中重用。
- 这种模块化的设计使得代码更加模块化、可扩展和可测试。
- 它可以独立于其他部分进行开发、测试和维护,而不会对其他组件产生影响。
- 此外,将文档扫描功能单独放在一个文件中,使得代码结构更清晰、易于理解和维护。
- 通过将不同的功能分割到不同的文件中,我们可以更好地组织代码,减少文件的复杂性,并促进团队合作开发。
'''
import cv2 as cv # 导入 OpenCV 库,用于图片处理和计算机视觉任务
import numpy as np # 导入 numpy 库,用于进行数值计算
class DocScanner:
def __init__(self):
pass # DocScanner 的初始化方法,目前为空
def load_image(self, file_path):
"""加载图片并找到文档的四个角落。"""
img = cv.imread(file_path) # 读取图片
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 将图片转换为灰度图
# 对灰度图进行二值化,得到二值图
thresh, binary_img = cv.threshold(img_gray,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
# 找到二值图的所有轮廓
contours, hierarchy = cv.findContours(binary_img,cv.RETR_TREE,cv.CHAIN_APPROX_NONE)
# 找到最大的周长的四边形的四个顶点 extreme_pnts
#TODO
for c in contours:
# 计算轮廓周长
perimeter = cv.arcLength(c, True)
# 计算近似轮廓
epsilon = 0.1 * perimeter
approx = cv.approxPolyDP(c, epsilon, True)
# # 计算轮廓周长
# extreme_pnts = cv.arcLength(c, True)
max_perimeter=0
if len(approx) == 4 and perimeter > max_perimeter:
extreme_pnts = approx
max_perimeter = perimeter
corners = self.order_points(extreme_pnts.reshape(4, 2)) # 对四个顶点进行排序
return img, corners # 返回图片和排序后的顶点
def order_points(self, 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)] # 左下角的点坐标差最大的那个点
print(f"0:左上角:{rect[0]},因为x,y的坐标和是: np.min(s)={np.min(s)}")
print(f"1:右上角:{rect[1]},因为x,y的坐标差是: np.min(diff)={np.min(diff)}")
print(f"2:右下角:{rect[2]},因为x,y的坐标和是: np.max(s)={np.max(s)}")
print(f"3:左下角:{rect[3]},因为x,y的坐标差是: np.max(diff)={np.max(diff)}")
return rect # 返回排序后的点
def crop_image(self, img, corners):
"""根据四个角落裁剪图片。"""
top_left_corner = corners[0]
top_right_corner = corners[1]
bottom_right_corner = corners[2]
bottom_left_corner = corners[3]
# 计算目标图片的宽度和高度
width, height = self.get_image_dimensions((top_left_corner, top_right_corner, bottom_right_corner, bottom_left_corner))
# 根据以上宽度和高度创建与原有四个点顺序对应的目标四个点的坐标
dst_points = np.array([ [0, 0], [width - 1, 0], [width - 1, height - 1], [0, height - 1]], dtype=np.float32)
# 通过投影变换展平文档
M = cv.getPerspectiveTransform(corners.astype(np.float32), dst_points) # 获取透视变换矩阵
dst = cv.warpPerspective(img, M, ([int(width), int(height)])) # 对图片进行透视变换
return dst # 返回展平后的图像
def get_image_dimensions(self, corners):
"""计算图片的宽度和高度。"""
# distance = np.linalg.norm() # 使用 numpy 的 linalg.norm 函数计算向量的范数(长度)
width1 = np.linalg.norm(corners[0] - corners[1])
width2 = np.linalg.norm(corners[2] - corners[3])
width = max(width1, width2)
height1 = np.linalg.norm(corners[0] - corners[3])
height2 = np.linalg.norm(corners[1] - corners[2])
height = max(height1, height2)
return width, height
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/liyanxiaxiaoqi/doc_scanner_homework.git
git@gitee.com:liyanxiaxiaoqi/doc_scanner_homework.git
liyanxiaxiaoqi
doc_scanner_homework
doc_scanner_homework
master

搜索帮助