You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于空白区域检测的OpenCV图像裁剪技术方案咨询

OpenCV实现文本图像按空白区域裁剪的思路

一、图像预处理

  • 灰度化:将彩色图像转为灰度图,减少计算维度,使用cv.cvtColor(img, cv.COLOR_BGR2GRAY)实现
  • 二值化反转:将文本区域转为黑色、背景转为白色,方便后续轮廓与投影分析,用cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)自动计算阈值完成二值化
  • 可选形态学膨胀:如果文本存在零散断裂,用cv.dilate(thresh, cv.getStructuringElement(cv.MORPH_RECT, (5,5)), iterations=1)将文本区域连接成整体,避免误分割

二、检测空白分割线

针对垂直排列的文本(如你的输入图),重点检测水平空白区域:

  • 计算行投影:统计二值图中每一行的非零像素(文本)数量,得到行投影数组
  • 判定空白行:设定阈值(如连续行的非零像素数小于5),将符合条件的行标记为空白行
  • 提取分割边界:合并连续的空白行,得到文本块之间的分割区间坐标

如果是水平排列的文本,只需改为计算列投影,同理检测垂直空白线即可。

三、提取并裁剪精准文本块

  • 分割初始文本块:根据空白分割线的坐标,将原图像切割为多个包含文本的子区域
  • 优化子区域边界:对每个子区域再次计算行/列投影,找到文本的上下左右边界,去掉边缘冗余空白,得到仅包含文本的精准块

四、代码示例框架

import cv2 as cv
import numpy as np

def crop_text_blocks(img_path):
    # 读取图像
    img = cv.imread(img_path)
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    
    # 二值化反转
    _, thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)
    
    # 计算行投影,找空白行
    row_proj = np.sum(thresh, axis=1)
    blank_threshold = 5
    blank_rows = np.where(row_proj < blank_threshold)[0]
    
    # 合并连续空白行,生成分割区间
    splits = []
    start = None
    for i in range(len(blank_rows)):
        if start is None:
            start = blank_rows[i]
        if i+1 >= len(blank_rows) or blank_rows[i+1] != blank_rows[i]+1:
            splits.append((start, blank_rows[i]))
            start = None
    
    # 确定文本块的上下边界
    block_bounds = []
    prev_end = 0
    for (s, e) in splits:
        if s - prev_end > 10:  # 过滤过小的空白区域
            block_bounds.append((prev_end, s))
        prev_end = e + 1
    # 添加最后一个文本块
    if prev_end < img.shape[0]:
        block_bounds.append((prev_end, img.shape[0]))
    
    # 裁剪并优化每个文本块
    cropped_blocks = []
    for (top, bottom) in block_bounds:
        block = img[top:bottom, :]
        block_gray = cv.cvtColor(block, cv.COLOR_BGR2GRAY)
        _, block_thresh = cv.threshold(block_gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)
        
        # 找文本左右边界
        col_proj = np.sum(block_thresh, axis=0)
        non_zero_cols = np.where(col_proj > blank_threshold)[0]
        if len(non_zero_cols) == 0:
            continue
        left, right = non_zero_cols[0], non_zero_cols[-1]
        
        final_block = block[:, left:right]
        cropped_blocks.append(final_block)
    
    return cropped_blocks

# 调用示例
blocks = crop_text_blocks("input.png")
for idx, block in enumerate(blocks):
    cv.imwrite(f"block_{idx+1}.png", block)

关键注意事项

  • 阈值调整:blank_threshold和空白区间过滤阈值(如s - prev_end > 10)需要根据图像实际情况微调,避免误分割或漏分割
  • 形态学操作:文本断裂严重时,可调整膨胀核的大小与迭代次数,确保文本区域完整
  • 边界优化:每个子区域二次投影裁剪是必要的,能有效去除文本块边缘的冗余空白

内容的提问来源于stack exchange,提问作者test_zuck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 00:42:55