免费离线A3试卷分割工具:原理、Python实现与避坑指南

发布时间:2026/10/1 12:19:37
免费离线A3试卷分割工具:原理、Python实现与避坑指南
每年考试季结束办公室和家里就会堆起一摞一摞的A3大卷子。学校为了省纸、方便排版经常把一张A3横向排成左右两栏对折起来正好是一份A4大小的卷子。可到了要打印、扫描、传网盘、拿去复印店的时候A3就非常尴尬普通家用打印机不支持A3幅面扫描上传后双栏挤在一起根本没法看存档更是占地方。我一直在用的这个A3试卷分割工具就是专门解决这个问题的把A3双栏试卷自动从中间切成两张A4单页全程本地离线运行不花一分钱不需要注册账号也没有上传服务器的环节。老师可以用它整理试卷库学生可以用它把大卷子拆成方便携带和书写的单页办公处理扫描件时同样顺手。今天这篇把思路、实现和踩过的坑都写出来希望能帮到同样被A3试卷折磨的人。1. 为什么要把A3试卷拆成A4说清楚三个最实际的使用场景1.1 学校存档与试卷库统一管理学校每学期的期中、期末、单元测验试卷量非常大。多数学校打印试卷用A3因为一张纸能放下完整的两栏内容判卷、折页、分发都方便。但归档时问题就来了档案系统里扫描件通常是A4版式A3横版图片插入Word、PDF、成绩分析表里要么被压得很小要么被旋转90度版面很难看。打印出来存档时A3纸张成本明显高于A4档案盒也不适合放大纸。把A3试卷按中缝切成两张A4后所有材料规格统一封面、目录、正文完全对齐后续检索、复印、借阅都轻松很多。我见过不少学校的试卷库早期没注意这套流程几百份A3扫描件堆在服务器里每次要用都得手动缩放截图效率极低。如果提前用分割工具整理一遍建库工作量虽然多一步但以后每一次调用都能省下大把时间。1.2 家用打印和在线学习场景另一个更常见的场景在家庭。现在不少学校把试卷电子版发到家长群文件是A3横向扫描件。家用打印机几乎都是A4幅面直接打印的话要么选择“适合页面”把A3缩到A4字体缩小到原来的七成左右题目基本看不清要么打印成两张横向A4版面奇怪且错位。如果家长在手机上给孩子辅导看A3缩略图简直是对眼睛的折磨。先把A3分割成两张A4再按原始尺寸打印清晰度和阅读体验完全不一样。这个需求在学生网课和在线作业征集中尤其强烈手机上打开A3双栏图片时想放大看其中一栏触控缩放总是乱跳分割后就变成普通单页体验顺畅得多。1.3 为什么非“免费离线”不可我做这个工具时最先考虑的就是免费和离线。市面上的在线分割工具其实不少上传、在线切割、下载看起来方便但仔细想想就明白问题在哪试卷属于教学资料上面往往有学校名称、学生姓名、成绩信息上传到第三方服务器完全不可控在线工具大多有文件大小限制为了控制流量还会压缩画质300dpi的清晰扫描图传上去可能被压到72dpi再加上部分工具用几次就要求付费、注册账号、看广告体验很差。学校里有些办公室电脑还在内网环境根本无法访问外网这时候一个完全离线、运行在本地的工具就成了唯一可行方案。所以从动手做这个工具开始我就把“离线可跑”当作硬指标所有功能不依赖任何网络服务这也是它和大多数在线工具最本质的区别。2. 分割工具的核心原理从A3到A4的几次关键计算2.1 纸张尺寸关系与等分原则先理清一个基础概念。A3纸的尺寸是420×297mmA4纸的尺寸是210×297mm两张A4横向并排正好拼成一张A3横向。换句话说一张A3试卷在印刷时左右两栏各占210mm宽度中间的折叠线就是天然分割线。因此把A3分割成A4本质就是沿垂直中缝对半裁剪这是一个数学上非常简单的操作不需要复杂的版面识别。实际换算成像素时以300dpi扫描分辨率为例420mm约等于4961像素297mm约等于3508像素从中间切开后左右各2480像素宽、3508像素高像素比例210:297等于1:1.414和A4完全一致。所以只要原图是标准的A3横向扫描件直接对半裁输出的图像就是标准的A4竖幅比例不需要再做任何缩放和补边。理解这个关系后面调参数时就不会慌。2.2 中缝定位直接等分还是智能检测部分工具会做“自动检测中缝”听起来更智能实际我测试下来并不比直接等分可靠。原因很简单大多数A3试卷的中缝就在纸张几何中心印刷厂的排版辊统一按A4双联排版左右几乎完全对称直接取宽度一半就是最佳分割线。而自动检测依赖的内容特征比如中缝的空白间隙、折痕阴影、装订线位置在不同的扫描件里表现差异很大。有的卷子中缝处正好是一个跨栏表格投影检测会把中缝判到别的位置有的试卷两侧页边距不对称装订边宽窄不一检测算法很容易被带偏。真功夫不在于检测而在于把“默认等分”这一步做扎实再允许用户通过一个偏移参数微调分割线位置用来补偿特殊版式。我这套工具默认不做花哨检测只提供左右边距参数供遇到非标准卷子时手动修正。2.3 分割前的方向判断与输出参数实际操作中还得分清一件事扫描件不一定是正放的横向A3。有的老师用手机对着试卷拍照图片可能是竖向的有的扫描仪会自动旋转保存成宽小于高的图片还有的图片带了EXIF旋转信息直接打开是正的被脚本读进来却是横的。处理逻辑很简单先读取图片宽高如果宽大于高认为是标准横向A3直接分割如果宽小于高先用EXIF信息转正转正后还不对就再手动旋转90度。这一步看似简单但漏了它后面所有输出都是横着的A4打印出来非常别扭。输出参数方面我的建议是源图是什么分辨率就保留什么分辨率不压缩、不重采样。扫描时代默认300dpi分割后的单页完全能满足打印和OCR需求。如果只是为了在手机、平板上看或者上传到作业平台150dpi也够用能明显减小文件体积。这里要格外注意裁剪不会改变图片的DPI数值只是把宽高切掉一半所以保存时尽量选PNG或高质量JPG不要用默认的高压缩比JPG否则文字边缘会出现明显的压缩噪点。3. 离线免费实操用Python从零搭一个批量分割工具3.1 准备工作与依赖安装不依赖任何在线服务Python脚本是最可控的方案。需要装的东西很少Python解释器以及Pillow和OpenCV两个图像处理库。Pillow负责基本的图片读写、旋转和裁剪OpenCV只用于增强版里的倾斜纠偏不需要纠偏功能的话只用Pillow就够了。安装命令很简单pip install pillow opencv-python如果你工作在离线环境里可以提前在有网络的电脑上把这些库的wheel包下载好拷到目标机器用pip install --no-index --find-links目录安装或者直接用我后面提到的打包方案把脚本打成免安装exe连Python都不用装。这一点也是离线需求的一部分工具本身只要下载一次使用过程中完全不联网。3.2 基础版脚本读取、纠转方向、等分裁剪我把最基础的分割逻辑抽成一个小脚本放在任意文件夹里即可批量运行。import os from PIL import Image, ImageOps def split_a3_to_a4(src_dir, dst_dir, left_margin0, right_margin0): 把A3横向试卷按中缝切成左右两张A4。 left_margin/right_margin: 中缝两侧需要裁掉的像素用于去掉装订孔或阴影。 os.makedirs(dst_dir, exist_okTrue) files [f for f in os.listdir(src_dir) if f.lower().endswith((.jpg, .jpeg, .png, .tif, .tiff, .bmp))] for file_name in files: path os.path.join(src_dir, file_name) img Image.open(path) img ImageOps.exif_transpose(img) # 处理手机照片的旋转信息 if img.width img.height: # 这里默认图片是横向排版但被竖放扫描按需旋转90度 img img.rotate(90, expandTrue) half img.width // 2 left_box (0, 0, half - left_margin, img.height) right_box (half right_margin, 0, img.width, img.height) base os.path.splitext(file_name)[0] img.crop(left_box).save(os.path.join(dst_dir, f{base}_L.png)) img.crop(right_box).save(os.path.join(dst_dir, f{base}_R.png)) print(f完成: {file_name}) print(f处理了 {len(files)} 个文件输出到 {dst_dir}) if __name__ __main__: split_a3_to_a4(输入目录, 输出目录, left_margin8, right_margin8)这段代码有几个细节值得说。exif_transpose必须先执行否则手机拍出来的照片会带着旋转标记后面的宽高判断全是错的。旋转那行默认令图片按逆时针旋转90度如果你的扫描件实际需要的是顺时针把90改成-90就行我后面会讲怎么快速判断。等分点half取宽度整除2标准A3扫描件宽度一般是个偶数像素值如果有奇数像素的余数多出来那1像素给左边或者右边都无所谓肉眼完全看不出。左右边距参数默认给8像素是为了把中缝附近的装订孔、折痕阴影裁掉实测对绝大多数扫描件有效但要注意有些卷子题目离中缝特别近边距太大会切到字这种情况设0。3.3 增强版自动纠偏与分割线微调遇到过不少扫描件是歪的纸没有对齐扫描仪边缘整体转了两三度直接等分后左右两页的顶端不在同一条水平线打印出来特别明显。我用OpenCV写了一个自动纠偏的环节原理很直白先把图片转成灰度然后用Canny算子提取边缘再用概率霍夫变换找长直线统计这些直线的倾斜角取中位数作为整张图的校正角度。试卷页面上有大量文字行和表格线当歪斜不太严重时那些接近水平的文字行就能给出足够可靠的参考线。import cv2 import numpy as np def estimate_angle(image): gray cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) edges cv2.Canny(gray, 50, 150) lines cv2.HoughLinesP(edges, 1, np.pi / 180, threshold300, minLineLength400, maxLineGap20) if lines is None: return 0.0 angles [] for line in lines: x1, y1, x2, y2 line[0] if abs(x2 - x1) 1: continue angle np.degrees(np.arctan2(y2 - y1, x2 - x1)) if abs(angle) 4: angles.append(angle) return float(np.median(angles)) if angles else 0.0 def rotate_image(image, angle): h, w image.shape[:2] matrix cv2.getRotationMatrix2D((w // 2, h // 2), angle, 1.0) return cv2.warpAffine(image, matrix, (w, h), borderValue(255, 255, 255))实际用的时候把基础版里的img从PIL对象转成OpenCV的BGR数组调用rotate_image后再转回PIL对象继续裁剪就行。角度符号有个坑图像向右歪斜和向左歪斜对应的角度正负不一样如果发现纠偏后更歪了就把angle取反。我在本地测试时大约七成扫描件靠这个方法能校正到0.2度以内剩下三成是本身文字行太少或者页面有大块图片算法找不到足够的长线这时候只能靠扫描时放正了。分割线微调可以直接改基础版里的left_margin和right_margin参数这两个值同时控制左右页的裁剪边距中缝偏移则通过给左边多裁、右边少裁来实现。3.4 批量重命名、排序与PDF导出分割出来的文件默认叫原文件名_L.png和原文件名_R.png但双面扫描的试卷需要按翻页顺序整理。一张A3纸如果两面都印了内容扫描后会有两个文件正面和反面。按正常翻页习惯双栏A3折起来后第1页是正面左栏第2页是正面右栏翻到背面后第3页应该是背面右栏第4页是背面左栏。所以顺序是正L、正R、反R、反L这和普通人直觉里的“正L、正R、反L、反R”完全不同。整理顺序时可以写一个小排序脚本把文件按这个规则排列然后用img2pdf把PNG列表转成一个PDF文档这样老师发给家长的就是一个连贯的A4版试卷PDF方便微信传阅、直接打印。img2pdf这个库对图像不做重压缩只重新打包成PDF质量几乎无损比在Word里插入图片再导出的体积和清晰度都好得多。import img2pdf pages [正L.png, 正R.png, 反R.png, 反L.png] with open(merged.pdf, wb) as f: f.write(img2pdf.convert(pages))3.5 打包成免安装工具配合右键菜单使用脚本虽然好用但办公室同事未必会运行Python代码。我后来用PyInstaller把脚本打包成了单个exe文件放在共享文件夹和U盘里谁需要谁拿去用。打包命令是pyinstaller -F --onefile a3_splitter.py这样一个文件就能独立运行目标电脑不需要装Python和任何依赖库。更进一步的用法是发送到桌面快捷方式然后把要处理的图片拖到exe图标上脚本通过sys.argv接收文件路径弹出一个提示框告诉用户处理完了多少张。这已经完全达到了一个成熟小工具的预期离线、免费、批量、无学习成本。如果杀毒软件误报加个白名单就行这是打包脚本常见的事。当然如果只是自己偶尔用不打包也完全没问题关键是把脚本源码保存好方便后续加功能。4. 不想写代码这几款免费离线工具可以换着用4.1 ImageMagick一行命令完成分割如果你能接受命令行操作ImageMagick是最快的一站式方案。它是一款老牌的开源图像处理工具支持所有主流系统完全本地运行。分割一张A3图片只需要一条命令magick input.jpg -crop 50%x100% repage output_%d.png-crop 50%x100%表示把原图按宽度切成两半、高度完整保留repage会移除原始画布信息让输出文件尺寸恰好是原图的一半。output_%d.png会自动生成output_0.png和output_1.png分别对应左半和右半。批量处理时在Linux/macOS下可以用for循环遍历文件夹里的jpg文件Windows的PowerShell里写循环同样很简单。如果图片带EXIF旋转标记先加-auto-orient参数转正。注意如果你电脑上同时装有Windows系统自带的convert命令千万别用convert作为ImageMagick的命令名必须用magick否则会触发系统磁盘转换工具这个坑我踩过。4.2 XnConvert图形界面批量分割图形界面党我更推荐XnConvert免费、中文界面、支持批量。操作流程是打开XnConvert在“输入”里添加一个文件夹或拖入一堆图片切到“操作”标签页点击“添加操作”在“图像”分类下找“裁剪”把裁剪方式设为百分比尺寸宽度50%、高度100%偏移x为0、y为0这是左边那一页再添加一次裁剪动作偏移x设为50%y为0应用到右边那一页。最后在“输出”里指定目标文件夹和输出格式点“转换”就行。一个容易忽略的地方XnConvert的“裁剪”是按图像当前尺寸算的批量处理时所有图片都会按各自尺寸的50%切这对扫描分辨率统一的情况毫无问题。如果某些图片分辨率不一样只要它们都是标准A3横向扫描结果依然正确因为比例是固定的最后裁出的都是A4比例不会出现尺寸混乱。遇到需要反复调整裁剪偏移量的时候图形界面比代码直观得多你可以实时看预览。4.3 手动分割利器 IrfanViewIrfanView是很多老用户电脑里必备的免费看图工具它也能用来手动分割。对着一张大图鼠标框选左边区域按快捷键裁剪再另存为然后用撤销回到裁剪前框选右边区域再另存为。这个操作模式适合只有三五张试卷要处理的场景速度并不慢因为不需要安装任何额外插件IrfanView本身就能直接打开扫描件。它的缺点也很明显没有针对“对半分割”的批处理模式几十张以上的文件用它逐张手动操作会崩溃。但它的亮点是完全离线、单文件绿色版拷到U盘即用老电脑跑起来也毫不费力。我自己的做法是批量处理优先用脚本或XnConvert单张补录和临时校对用IrfanView两种方式配合起来效率最高。4.4 工具横向对比表工具类型是否免费离线运行批量处理上手难度适合场景Python脚本代码是是强中大量、需要自动纠偏和自定义逻辑ImageMagick命令行是是强中熟悉命令行的快速处理XnConvert图形界面免费版是强低普通办公人员批量处理IrfanView图形界面免费是弱低少量手动分割、绿色便携在线分割网站网页部分免费否一般低不推荐处理含隐私内容试卷这张表能直接帮你做决策。我的原则就一句话试卷这类可能包含学生信息和学校信息的资料完全不建议拿到在线网站上切离线工具之间挑一个顺手的即可。5. 常见问题与避坑指南我把踩过的坑一次说全5.1 扫描件歪斜严重分割线像刀切歪了这是个高频问题。歪斜超过2度的时候分割出来的两页纸乍一看没事放大了会发现文字行是倾斜的打印出来更明显。处理优先级我建议这样排扫描时把试卷纸张贴紧扫描仪边缘这是成本最低的方案其次是自动纠偏用前面OpenCV的增强版脚本最后才是人为判断。如果真的遇到大角度歪斜的图片自动纠偏算法可能找不到足够长的水平线不用硬调参数重新扫描最靠谱。扫描仪玻璃面板上通常有刻度线和角标把纸张右下角对齐那个角标大多数情况下能保证偏差在1度内。5.2 中缝有装订孔、阴影或墨迹A3卷子如果是装订成册扫描的中缝区域通常有一排孔或者深色阴影。直接等分后左右两页的内侧边缘会各带一部分脏东西。处理方法是在分割参数里给left_margin和right_margin各设一个值比如8到15像素把中缝周围裁掉。注意别贪心边距设太大容易切到题目尤其是有跨栏题目或表格贴在中缝线附近时宁可留一点阴影也不要切字。另外扫描前把试卷完全摊平、顶部用书压住中缝阴影会明显减少。5.3 跨栏题目/图片被切到怎么办这是所有A3分割工具都绕不开的问题。比如试卷标题居中横跨两栏或者某道大题在页面中央跨栏印刷了配图沿中缝切割后标题被分到两页、图片被切成两半。我的处理方式是先看跨栏内容是否影响阅读。大多数情况下标题断了不影响做题跨栏图片左右两页各占一半也能大概看出来是什么。如果确实需要完整保留某一跨栏内容就用IrfanView手动选择切割位置把跨栏部分留在左页或右页另一页相应偏移或者干脆先用截图工具把跨栏部分单独截出来插到Word里重新排版。这种方法适合量少的特殊卷子批量处理时不要指望自动算法能完美处理因为跨栏内容的识别本身需要语义理解。5.4 双面扫描之后顺序全乱了双面扫描的试卷很多人按文件名排序后就直接打印结果页序完全不对。我前面已经说过规则正L、正R、反R、反L。原因不复杂A3纸左右对折后背面物理上和正面是镜像关系背面的右栏其实是正面右栏的背面。把扫描件按这个顺序重新命名或排序再导出PDF就得到一个正确的A4双面文档。实际操作时我的脚本会读取文件名里的face和back标记自动重组顺序。如果没有标记就只能通过图片内容人工判断哪一页是正面、哪一页是背面判断点一般是页眉或页码位置。5.5 文件太大跑不动、导出半天300dpi的彩色扫描件一张能到三五十MB批量处理几十张会让内存和磁盘都很吃力。我的经验是纯文字试卷扫描时用灰度模式文件体积能缩小到三分之一而且文字清晰度几乎不受影响。如果只要手机阅读或上传平台150dpi就够分割前先统一缩放分辨率处理速度会快很多。我脚本里加了一个目标DPI参数扫描件先按目标分辨率重采样再做等分。但归档打印用的原图就不要压缩了保持原始分辨率分割后直接导出无损PNG或高画质JPG。5.6 分割后打印尺寸对不上最后再讲一个很容易被忽略的坑。分割出来的图片本身是A4比例但打印时如果打印软件默认“适合页面”可能会再按页面实际可打印区域缩放一次导致左右两页内容大小不一致或者边缘出现白边。正确做法是在打印设置里选择“实际大小”或“100%缩放”这样左页和右页才能保持同尺寸。用PDF导出后打印更稳定因为PDF自带的页面尺寸就是A4打印驱动会直接按A4处理不会出现莫名其妙的缩放偏差。最后说点个人经验。最初写这个脚本只是为了处理办公室积攒的几百张期中期末卷子当时用的还是最暴力的“等分切割”。后来用得多了陆续加了自动纠偏、边距微调、PDF导出但每一次改动都坚持同一个原则默认参数必须稳让第一次用的人不需要理解底层逻辑也能直接跑。实际用下来最值的投资不是自动识别这些花哨功能而是扫描时把纸放正、把纸压平扫描质量上去了后面的分割算法几乎不需要干预。如果你手头正好积了一堆A3电子版试卷先拿两三张试试上面的步骤分完打印出来看看效果再决定要不要批量跑全库。离线运行、免费处理这套工具最大的价值就是让你放心把整个试卷库都整理干净不用把学生信息交给任何第三方平台。