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

基于OpenCV的带蓝色边框文档图像裁剪技术问题求助

问题描述

示例图像:
示例文档图像1
示例文档图像2

各位好,我是一名学生,正在开展项目开发,任务是编写函数读取大量此类文档图像中的文本。我原本计划裁剪掉图像的蓝色边框,将其转换为矩形图像,但尝试后失败。由于拍摄光照角度不同,多数图像的蓝色边框呈现不同色调,难以找到最优参数设置;尝试检测蓝色轮廓也因色调差异无法成功,恳请各位提供解决方案。

我的尝试代码:

import cv2
import numpy as np

def find_blue_contour(image):
    # Convert the image to HSV color space
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    
    # Define the blue color range in HSV
    lower_blue = np.array([110, 50, 50])
    upper_blue = np.array([130, 255, 255])
    
    # Create a mask for the blue color
    mask = cv2.inRange(hsv, lower_blue, upper_blue)
    cv2.imshow("mask",mask)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    # Find contours in the mask
    contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    # If no contours are found, return None
    if not contours:
        return None
    
    # Find the largest contour
    largest_contour = max(contours, key=cv2.contourArea)
    
    return largest_contour

def crop_image_around_contour(image, contour):
    # Get the bounding rectangle of the contour
    x, y, w, h = cv2.boundingRect(contour)
    
    # Crop the image around the bounding rectangle
    cropped_image = image[y:y+h, x:x+w]
    
    return cropped_image

# Image path
image_path = 'dene1.JPeG'

# Load the image
image = cv2.imread(image_path)

if image is None:
    print(f"Error: Could not load image {image_path}.")
    exit()

# Find the blue contour
blue_contour = find_blue_contour(image)

if blue_contour is None:
    print("Error: Could not find blue contour.")
    exit()

# Crop the image around the blue contour
cropped_image = crop_image_around_contour(image, blue_contour)

# Display the original and cropped images
cv2.imshow("Original Image", image)
cv2.imshow("Cropped Image", cropped_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
解决方案

针对光照导致蓝色色调变化的问题,可尝试以下几种优化方案:

1. 扩展HSV蓝色范围并结合形态学操作

放宽HSV的蓝色阈值范围,同时用形态学操作消除mask噪点、强化边框轮廓:

def find_blue_contour(image):
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    # 扩展蓝色范围,覆盖不同光照下的色调
    lower_blue = np.array([90, 30, 30])
    upper_blue = np.array([140, 255, 255])
    mask = cv2.inRange(hsv, lower_blue, upper_blue)
    
    # 形态学操作:先膨胀再腐蚀,填充mask漏洞
    kernel = np.ones((5,5), np.uint8)
    mask = cv2.dilate(mask, kernel, iterations=2)
    mask = cv2.erode(mask, kernel, iterations=1)
    
    contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    if not contours:
        return None
    largest_contour = max(contours, key=cv2.contourArea)
    return largest_contour

2. 使用Lab颜色空间检测蓝色

Lab颜色空间的b通道对蓝色/黄色敏感,蓝色在b通道中为高值,不受光照亮度影响,稳定性更强:

def find_blue_contour_lab(image):
    lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)
    # 提取b通道
    b_channel = lab[:,:,2]
    # 对b通道做阈值处理,提取蓝色区域
    _, mask = cv2.threshold(b_channel, 150, 255, cv2.THRESH_BINARY)
    
    kernel = np.ones((7,7), np.uint8)
    mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
    
    contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    if not contours:
        return None
    largest_contour = max(contours, key=cv2.contourArea)
    return largest_contour

3. 边缘检测+轮廓近似(不依赖颜色)

如果颜色检测始终不稳定,可跳过颜色识别,直接通过边缘检测寻找文档的四边形轮廓,再做透视变换纠正为矩形:

def find_document_contour(image):
    # 灰度化+模糊去噪
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray, (5,5), 0)
    # 边缘检测
    edges = cv2.Canny(blur, 50, 150)
    
    # 形态学操作强化边缘
    kernel = np.ones((5,5), np.uint8)
    edges = cv2.dilate(edges, kernel, iterations=1)
    
    contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    if not contours:
        return None
    
    # 筛选面积最大的轮廓,并近似为四边形
    largest_contour = max(contours, key=cv2.contourArea)
    perimeter = cv2.arcLength(largest_contour, True)
    approx = cv2.approxPolyDP(largest_contour, 0.02*perimeter, True)
    
    # 确保是四边形
    if len(approx) == 4:
        return approx
    else:
        return None

# 透视变换纠正为矩形(适配梯形边框)
def warp_perspective(image, contour):
    # 整理四个顶点顺序(左上、右上、右下、左下)
    pts = contour.reshape(4,2)
    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)]
    
    # 计算目标矩形的尺寸
    width1 = np.linalg.norm(rect[1] - rect[0])
    width2 = np.linalg.norm(rect[2] - rect[3])
    max_width = max(int(width1), int(width2))
    
    height1 = np.linalg.norm(rect[3] - rect[0])
    height2 = np.linalg.norm(rect[2] - rect[1])
    max_height = max(int(height1), int(height2))
    
    # 目标顶点
    dst = np.array([
        [0,0],
        [max_width-1,0],
        [max_width-1, max_height-1],
        [0, max_height-1]
    ], dtype="float32")
    
    # 计算透视变换矩阵并应用
    M = cv2.getPerspectiveTransform(rect, dst)
    warped = cv2.warpPerspective(image, M, (max_width, max_height))
    return warped

使用时替换原函数即可,示例:

document_contour = find_document_contour(image)
if document_contour is None:
    print("Error: Could not find document contour.")
    exit()
cropped_image = warp_perspective(image, document_contour)

4. 自适应阈值优化

如果文档内容与边框对比度明显,可尝试对灰度图做自适应阈值分割,再提取轮廓,进一步提升鲁棒性。

内容的提问来源于stack exchange,提问作者ali rıza kurt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 02:14:58