如何用OpenCV遍历图片文件夹并分割文本行保存单字图像?
批量处理图片分割单词的问题修复
你的代码在批量处理时只导出一张图片,核心原因是轮廓处理逻辑完全在遍历文件的循环外部,只执行了最后一张图的分割,加上代码里还有几处变量错误和文件覆盖问题,以下是修复后的完整代码:
from PIL import Image import cv2 import numpy as np from pathlib import Path corpus_dir = Path('data') files = list(corpus_dir.glob(pattern='*.jpg')) # 遍历每个文件 for idx, f in enumerate(files): # 读取图片(PIL的读取可以去掉,直接用cv2读就行) image = cv2.imread(str(f)) if image is None: print(f"无法读取图片: {f}") continue # 预处理流程 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (5,5), 0) ret, thresh1 = cv2.threshold(blur, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY_INV) # 保存中间结果时加上文件名前缀,避免覆盖 cv2.imwrite(f'threshold_image_{f.stem}.jpg', thresh1) rect_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (4,30)) dilation = cv2.dilate(thresh1, rect_kernel, iterations = 6) cv2.imwrite(f'dilation_image_{f.stem}.jpg', dilation) # 查找轮廓 contours, hierarchy = cv2.findContours(dilation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 修复变量错误:用image.copy()而不是未定义的img.copy() im2 = image.copy() # 初始化当前文件的分割计数,放在循环内部,每个文件从1开始计数 crop_number = 1 # 按坐标排序轮廓(按y轴,再x轴,保证从左到右分割) sorted_contours = sorted(contours, key=lambda x: (cv2.boundingRect(x)[1], cv2.boundingRect(x)[0])) # 遍历排序后的轮廓 for cnt in sorted_contours: x, y, w, h = cv2.boundingRect(cnt) # 过滤过小的轮廓,避免噪点 if h > 50 and w > 50: # 绘制矩形框 rect = cv2.rectangle(im2, (x, y), (x + w, y + h), (0, 255, 0), 2) # 裁剪区域 cropped = im2[y:y + h, x:x + w] # 保存时加上原文件名前缀,避免不同文件的分割图互相覆盖 cv2.imwrite(f"{f.stem}_sawir_{crop_number}.jpeg", cropped) crop_number += 1 # 可选:保存带框的原图 cv2.imwrite(f'boxed_image_{f.stem}.jpg', im2)
关键修改说明
- 修复变量错误:把
im2 = img.copy()改成im2 = image.copy(),原代码中img未定义,单张运行时可能依赖全局变量,批量处理会直接报错 - 把轮廓处理逻辑移到文件遍历循环内部:原代码中
crop_number初始化、轮廓排序、遍历分割都在文件循环外,导致只处理最后一张图的轮廓 - 避免文件覆盖:
- 中间结果(阈值图、膨胀图)加上原文件名前缀,不会被后续文件覆盖
- 分割后的单词图片也加上原文件名前缀,不同文件的分割图不会互相覆盖
- 正确排序轮廓:原代码排序了轮廓但没用到,现在用
sorted_contours遍历,按y轴(行)和x轴(列)排序,保证从左到右分割单词 - 修复缩进问题:把裁剪和保存代码放到
if h >50 and w>50的条件块内,避免处理过小的噪点轮廓 - 增加错误处理:判断图片是否读取成功,避免无效文件导致程序崩溃
内容的提问来源于stack exchange,提问作者Yasin1
相关产品推荐
相关产品推荐

