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

如何用OpenCV去除图像框线并保留文本?

去除图像框线同时保留文本的解决方案

问题背景

需要移除图像中的黑色框线、保留内部黑色文本,但当前使用drawContours的方案因框线与文本共享像素,导致部分字符被误删除。原图为白底黑框黑文本的图像,框线围绕多个文本区域;现有代码运行后,部分框线被标记,但文本边缘也被错误处理。

原实现代码

import cv2

def contour_height(contour):
    (x, y, w, h) = cv2.boundingRect(contour)
    return h

image = cv2.imread("sample.png")

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (9, 9), 0)

# Applying threshold
threshold = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
edges = cv2.Canny(threshold, 50, 200)

# Finding and sorting contours based on the contour area
contours, hierarchy  = cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key=contour_height, reverse = True)

# Display
cv2_imshow(cv2.drawContours(image, contours[:35], -1, (0, 255, 0), 2))

解决方案

方法一:形态学操作(针对规则框线)

利用形态学开运算,结合自定义横竖结构元素,针对性去除水平/垂直框线,避免误触文本:

import cv2
import numpy as np

image = cv2.imread("sample.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 二值化得到黑底白字,方便后续处理
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)

# 构造水平结构元素,去除水平框线
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (40, 1))
remove_horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
cnts = cv2.findContours(remove_horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(thresh, [c], -1, (0,0,0), 2)

# 构造垂直结构元素,去除垂直框线
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 40))
remove_vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
cnts = cv2.findContours(remove_vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(thresh, [c], -1, (0,0,0), 2)

# 反转回白底黑字
result = cv2.bitwise_not(thresh)

# 显示结果
cv2.imshow("Result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

方法二:精准轮廓筛选(区分框线与文本轮廓)

框线轮廓多为近似矩形的大轮廓,文本则是小而不规则的轮廓,通过轮廓面积、多边形边数筛选区分:

import cv2
import numpy as np

image = cv2.imread("sample.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (3, 3), 0)

# 二值化
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)

# 只提取最外层轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 创建掩码,标记要去除的框线区域
mask = np.zeros_like(gray)

for cnt in contours:
    area = cv2.contourArea(cnt)
    # 过滤过小的文本轮廓,只处理大轮廓
    if area > 1000:
        # 轮廓近似为多边形
        peri = cv2.arcLength(cnt, True)
        approx = cv2.approxPolyDP(cnt, 0.02 * peri, True)
        # 框线通常为4边形(矩形)
        if len(approx) == 4:
            cv2.drawContours(mask, [cnt], -1, 255, -1)

# 从二值图中移除框线区域
result = cv2.bitwise_and(thresh, thresh, mask=cv2.bitwise_not(mask))
# 反转回白底黑字
result = cv2.bitwise_not(result)

# 显示结果
cv2.imshow("Result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

说明

  • 形态学操作适合规则水平/垂直框线,可调整结构元素的尺寸(如(40,1)中的40)适配不同粗细的框线;
  • 轮廓筛选适合框线为矩形的场景,通过面积阈值和多边形边数可精准区分框线与文本;
  • 若框线与文本粘连严重,可先执行一次小幅度膨胀操作,再分离轮廓后处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 20:05:10