TF-IDF改造应用于LLM任务理解评估的方法与实践
2026/5/5 9:04:26
本文将带你从零开始,掌握如何使用纯算法方式实现文档图像的自动矫正与增强。通过本教程,你将学会:
最终成果是一个功能完整的“AI智能文档扫描仪”,可处理发票、合同、白板笔记等各类平面文档,效果媲美商业应用如“全能扫描王”。
为顺利理解并实践本教程内容,建议具备以下基础:
无需深度学习或神经网络背景,所有操作均基于传统计算机视觉算法。
与市面上依赖预训练模型的方案不同,本项目完全基于 OpenCV 的数学运算和图像处理逻辑,具有以下优势:
opencv-python和numpy适合嵌入办公自动化流程、移动端轻量应用或边缘设备部署。
整个文档扫描与矫正如图所示,分为四个关键步骤:
该流程完全基于几何变换和图像统计特性,无需任何机器学习模型。
Canny 是一种多阶段边缘检测算法,包含以下步骤:
在代码中调用如下:
edges = cv2.Canny(gray, threshold1=50, threshold2=150)OpenCV 提供findContours函数提取所有闭合轮廓。我们按面积排序,选择最大的四边形作为文档主体:
contours, _ = cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) contours = sorted(contours, key=cv2.contourArea, reverse=True)随后使用cv2.approxPolyDP对轮廓进行多边形逼近,若近似为四边形,则认为是目标文档。
一旦获取四个角点坐标,即可构造透视变换矩阵:
src_points = np.float32([tl, tr, br, bl]) # 原图中的四角 dst_points = np.float32([[0, 0], [w, 0], [w, h], [0, h]]) # 目标矩形坐标 M = cv2.getPerspectiveTransform(src_points, dst_points) warped = cv2.warpPerspective(image, M, (w, h))此变换能将任意角度拍摄的文档“展平”为正视图。
确保已安装必要库:
pip install opencv-python numpy matplotlibimport cv2 import numpy as np import matplotlib.pyplot as plt def order_points(pts): """将四个点按左上、右上、右下、左下排序""" rect = np.zeros((4, 2), dtype="float32") s = pts.sum(axis=1) rect[0] = pts[np.argmin(s)] # 左上角:x+y最小 rect[2] = pts[np.argmax(s)] # 右下角:x+y最大 diff = np.diff(pts, axis=1) rect[1] = pts[np.argmin(diff)] # 右上角:x-y最小 rect[3] = pts[np.argmax(diff)] # 左下角:x-y最大 return rect def scan_document(image_path): # 读取图像 image = cv2.imread(image_path) orig = image.copy() height, width = image.shape[:2] # 调整图像大小以便处理 ratio = 800.0 / height new_size = (int(width * ratio), 800) image_resized = cv2.resize(image, new_size, interpolation=cv2.INTER_AREA) # 转为灰度图 gray = cv2.cvtColor(image_resized, cv2.COLOR_BGR2GRAY) # 高斯模糊 + Canny 边缘检测 blurred = cv2.GaussianBlur(gray, (5, 5), 0) edges = cv2.Canny(blurred, 50, 150) # 查找轮廓 contours, _ = cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) contours = sorted(contours, key=cv2.contourArea, reverse=True)[:5] doc_contour = None for c in contours: peri = cv2.arcLength(c, True) approx = cv2.approxPolyDP(c, 0.02 * peri, True) if len(approx) == 4: doc_contour = approx break if doc_contour is None: print("未检测到四边形轮廓,请检查输入图像") return None # 显示原图轮廓 cv2.drawContours(image_resized, [doc_contour], -1, (0, 255, 0), 3) # 将角点坐标还原到原始图像尺度 doc_contour_orig = doc_contour.reshape(4, 2) * (orig.shape[1]/new_size[0], orig.shape[0]/new_size[1]) doc_contour_ordered = order_points(doc_contour_orig) # 计算输出图像尺寸 tl, tr, br, bl = doc_contour_ordered width_a = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2)) width_b = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2)) max_width = max(int(width_a), int(width_b)) height_a = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2)) height_b = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2)) max_height = max(int(height_a), int(height_b)) # 构造目标坐标 dst = np.array([ [0, 0], [max_width - 1, 0], [max_width - 1, max_height - 1], [0, max_height - 1]], dtype="float32") # 获取变换矩阵并执行透视变换 M = cv2.getPerspectiveTransform(doc_contour_ordered, dst) warped = cv2.warpPerspective(orig, M, (max_width, max_height)) # 图像增强:自适应阈值去阴影 warped_gray = cv2.cvtColor(warped, cv2.COLOR_BGR2GRAY) enhanced = cv2.adaptiveThreshold( warped_gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) return orig, image_resized, warped, enhanced # 使用示例 def display_results(orig, resized, warped, enhanced): plt.figure(figsize=(15, 5)) plt.subplot(1, 4, 1) plt.imshow(cv2.cvtColor(orig, cv2.COLOR_BGR2RGB)) plt.title('原始图像') plt.axis('off') plt.subplot(1, 4, 2) plt.imshow(resized) plt.title('边缘检测结果') plt.axis('off') plt.subplot(1, 4, 3) plt.imshow(cv2.cvtColor(warped, cv2.COLOR_BGR2RGB)) plt.title('透视矫正后') plt.axis('off') plt.subplot(1, 4, 4) plt.imshow(enhanced, cmap='gray') plt.title('增强扫描件') plt.axis('off') plt.tight_layout() plt.show() # 执行处理 result = scan_document("document.jpg") # 替换为你的图片路径 if result: orig, resized, warped, enhanced = result display_results(orig, resized, warped, enhanced)| 代码段 | 功能说明 |
|---|---|
order_points | 将检测到的四个角点按顺时针顺序排列,确保变换正确 |
cv2.Canny | 提取图像边缘,用于后续轮廓识别 |
cv2.findContours | 找出所有封闭轮廓,从中筛选最大四边形 |
cv2.approxPolyDP | 多边形逼近,判断是否为四边形 |
cv2.getPerspectiveTransform | 计算从源四边形到目标矩形的投影变换矩阵 |
cv2.warpPerspective | 执行真正的“拉直”操作 |
cv2.adaptiveThreshold | 自适应二值化,有效去除光照不均和阴影 |
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 无法检测轮廓 | 图像对比度低 | 改善拍摄环境,增加亮度 |
| 错误识别其他物体 | 背景复杂干扰 | 更换为纯色背景,或手动指定ROI区域 |
| 角点错位 | 文档边缘模糊 | 调整 Canny 阈值参数,如(30, 100) |
| 输出图像扭曲 | 四边形拟合失败 | 检查approxPolyDP的 epsilon 参数 |
| 扫描件有噪点 | 自适应阈值参数不当 | 调整 blockSize 和 C 值 |
完成本教程后,你可以进一步探索以下方向:
opencv/opencv/samples/python/perspective_transform.py获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。