注册 登录
编程论坛 Python论坛

一段代码,用于提取照片中的A4纸,拉升铺满为一A4大小的PDF

书生牛犊 发布于 6 天前 20:53, 52 次点击
注意传入的图片需要提前将图片旋转角度,使之上下窄边,左右为纸张的宽边。因为最后的PDF拉升就是按照这样的A4比例去啦,如果传入的照片里的纸张是横的,就会使最终的PDF被拉伸失真。。。
程序代码:
import cv2
import numpy as np
from fpdf import FPDF
import os

def correct_perspective(image_path, output_pdf_path):
    # 读取图像
    image = cv2.imread(image_path)
    if image is None:
        print("无法读取图像,请检查路径是否正确。")
        return

    # 转换为灰度图
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # 高斯模糊
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)

    # 边缘检测
    edged = cv2.Canny(blurred, 50, 150)

    # 查找轮廓
    contours, _ = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    contours = sorted(contours, key=cv2.contourArea, reverse=True)[:5]

    # 找到文档的轮廓
    for contour in contours:
        peri = cv2.arcLength(contour, True)
        approx = cv2.approxPolyDP(contour, 0.02 * peri, True)

        if len(approx) == 4:
            doc_contour = approx
            break

    # 如果没有找到四边形轮廓,直接保存原图
    if 'doc_contour' not in locals():
        print("未找到文档轮廓,保存原图。")
        cv2.imwrite(output_pdf_path.replace('.pdf', '.jpg'), image)
        return

    # 透视变换
    def order_points(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 four_point_transform(image, pts):
        rect = order_points(pts)
        (tl, tr, br, bl) = rect

        widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
        widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
        maxWidth = max(int(widthA), int(widthB))

        heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
        heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
        maxHeight = max(int(heightA), int(heightB))

        dst = np.array([
            [0, 0],
            [maxWidth - 1, 0],
            [maxWidth - 1, maxHeight - 1],
            [0, maxHeight - 1]], dtype="float32")

        M = cv2.getPerspectiveTransform(rect, dst)
        warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
        return warped

    warped = four_point_transform(image, doc_contour.reshape(4, 2))

    # 保存矫正后的图像
    corrected_image_path = output_pdf_path.replace('.pdf', '.jpg')
    cv2.imwrite(corrected_image_path, warped)

    # 将图像转换为PDF并铺满A4纸张
    pdf = FPDF(format='A4')  # 设置PDF为A4尺寸
    pdf.add_page()

    # 获取A4纸张的尺寸(单位:毫米)
    a4_width = 210
    a4_height = 297

    # 将图像铺满A4纸张
    pdf.image(corrected_image_path, x=0, y=0, w=a4_width, h=a4_height)

    # 保存PDF
    pdf.output(output_pdf_path, "F")

    # 删除临时图像文件
    os.remove(corrected_image_path)

    print(f"PDF文件已保存到:{output_pdf_path}")

# 使用示例
image_path = "path_to_your_image.jpg"  # 替换为你的图片路径
output_pdf_path = os.path.join(os.path.expanduser("~"), "Desktop", "corrected_document.pdf")
correct_perspective(image_path, output_pdf_path)






0 回复
1