取mask下边界

图像处理函数:method_ForCols用于边界提取
该函数主要对输入的cv::Mat图像进行处理,通过二值化和从下往上的扫描方式找出mask中最下方的白色像素点作为边界,然后在设定的间隔和填充范围内设置mask的值。参数包括线条宽度、列间隔和是否计算处理时间。返回处理后的mask。
cv::Mat method_ForCols(cv::Mat& img, int padding = 5, int interval = 3, bool timer = true) {
/*
    @brief 选取mask最下方的点作为边界
    @param img      : 模型推理结果的边界mask (drawContours的结果)
    @param padding  : 线条宽度
    @param interval : 列间隔 (interval = 1 效率较低 像素大时没有必要)
    @param timer    : 处理时间
    @return         : 处理后的mask
*/
/*
    可以根据上游处理,减少二值化步骤
*/    
    double st = clock();

    cv::Mat mask(img.rows, img.cols, CV_8UC1, cv::Scalar(0));
    cv::threshold(img, img, 100, 255, cv::THRESH_BINARY);

    for (int col_idx = 0; col_idx < img.cols; col_idx += interval) {
        bool hasWhitePixel = false;
        int upest = img.rows;
        
        // 从下往上
        for (int row = img.rows - 1; row >= 0; --row) {
            uchar pixel = img.at<uchar>(row, col_idx);

            if (pixel == 255) {
                hasWhitePixel = true;
                upest = row;
                break;
            }
        }

        if (hasWhitePixel) {
            mask.rowRange(upest, std::min(upest + padding, img.rows)).colRange(col_idx, std::min(col_idx + interval, img.cols)).setTo(255);
        }
    }

    if (timer)
        std::cout << "[Filter method_ForCols] time cost " << (clock() - st) / CLOCKS_PER_SEC << std::endl;

    return mask;

}

请添加图片描述

帮我修复这个自动去除黑边等杂质的代码还是不对,看起来是马赛克的效果,继续完善,import cv2 import numpy as np from scipy.ndimage import binary_dilation def remove_black_borders_with_smart_fill(image, tolerance=15): """ 去除黑边并使用智能纹理合成填充边缘区域 """ # 转换为灰度图 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) h, w = gray.shape # 创建填充掩码 mask = np.zeros((h + 2, w + 2), dtype=np.uint8) flags = 4 | cv2.FLOODFILL_MASK_ONLY | (255 << 8) seed_points = [(0, 0), (w - 1, 0), (0, h - 1), (w - 1, h - 1)] # 使用副本进行漫水填充 gray_copy = gray.copy() for x, y in seed_points: cv2.floodFill( gray_copy, mask, (x, y), 0, tolerance, tolerance, flags ) fill_mask = mask[1:-1, 1:-1] document_mask = cv2.bitwise_not(fill_mask) # 找到主区域的最小外接矩形 ys, xs = np.where(document_mask > 0) if len(ys) == 0 or len(xs) == 0: return image # 未检测到文档区域,返回原图 top, bottom = ys.min(), ys.max() left, right = xs.min(), xs.max() # 创建结果图像 result = image.copy() # 创建需要填充区域的掩码 fill_region = np.zeros_like(gray, dtype=np.uint8) fill_region[:top, :] = 255 # 上边缘 fill_region[bottom + 1:, :] = 255 # 下边缘 fill_region[:, :left] = 255 # 左边缘 fill_region[:, right + 1:] = 255 # 右边缘 # 创建边界区域(文档边缘附近) border_size = 880 border_region = np.zeros_like(gray, dtype=np.uint8) border_region[top:top + border_size, left:right + 1] = 255 # 上边界 border_region[bottom - border_size + 1:bottom + 1, left:right + 1] = 255 # 下边界 border_region[top:bottom + 1, left:left + border_size] = 255 # 左边界 border_region[top:bottom + 1, right - border_size + 1:right + 1] = 255 # 右边界 # 1. 智能填充算法 # 使用inpaint方法进行纹理合成 filled = cv2.inpaint( result, fill_region, inpaintRadius=3, flags=cv2.INPAINT_TELEA ) # 2. 混合结果 - 保留原始文档区域 # 创建文档区域掩码(扩大一点确保覆盖所有文档内容) document_mask_expanded = binary_dilation(document_mask, structure=np.ones((5, 5)), iterations=3).astype( np.uint8) * 255 document_mask_expanded = cv2.bitwise_and(document_mask_expanded, cv2.bitwise_not(fill_region)) # 组合结果:原始文档区域 + 填充区域 result = np.where( document_mask_expanded[:, :, np.newaxis] > 0, result, filled ) # 3. 使用泊松混合优化边缘 # 创建中心区域掩码(文档区域减去边缘) center_mask = np.zeros_like(gray, dtype=np.uint8) center_mask[top + border_size:bottom - border_size, left + border_size:right - border_size] = 255 center_mask = cv2.bitwise_and(center_mask, document_mask) # 泊松混合 center = result[top:bottom, left:right].copy() blended = cv2.seamlessClone( center, result, center_mask[top:bottom, left:right], ((left + right) // 2, (top + bottom) // 2), cv2.NORMAL_CLONE ) return blended # 使用示例 if __name__ == "__main__": input_image = cv2.imread("zdk/5390004.jpg") if input_image is None: print("无法读输入图像") else: output_image = remove_black_borders_with_smart_fill(input_image, tolerance=39) cv2.imwrite("output/a.jpg", output_image) print("处理完成,结果已保存")
07-07
下面的方法运行太慢,如何用pandas内部方法实现他。做到一样的效果。def fill_65535(data): """处理65535值的核心算法""" # 创建背景标记矩阵 mask = np.zeros_like(data, dtype=np.uint8) rows, cols = data.shape q = deque() # 标记边界上的65535为背景 borders = [ (0, range(cols)), # 上边界 (rows - 1, range(cols)), # 下边界 (range(1, rows - 1), 0), # 左边界 (range(1, rows - 1), cols - 1) # 右边界 ] for border in borders: if isinstance(border[0], int): i = border[0] for j in border[1]: if data[i, j] == 65535: mask[i, j] = 1 q.append((i, j)) else: j = border[1] for i in border[0]: if data[i, j] == 65535: mask[i, j] = 1 q.append((i, j)) # 使用BFS扩展背景标记(4连通) directions = [(0, 1), (1, 0), (0, -1), (-1, 0)] while q: i, j = q.popleft() for dx, dy in directions: ni, nj = i + dx, j + dy if 0 <= ni < rows and 0 <= nj < cols: if data[ni, nj] == 65535 and mask[ni, nj] == 0: mask[ni, nj] = 1 q.append((ni, nj)) # 将背景的65535替换为0 data[mask == 1] = 0 # 填充内部65535(使用8邻域平均) max_iters = 50 # 最大迭代次数防止无限循环 for _ in range(max_iters): changed = False # 创建数据副本用于安全更新 new_data = data.copy() for i in range(rows): for j in range(cols): if data[i, j] == 65535: neighbors = [] # 检查8邻域 for dx in (-1, 0, 1): for dy in (-1, 0, 1): if dx == 0 and dy == 0: continue ni, nj = i + dx, j + dy if 0 <= ni < rows and 0 <= nj < cols: if data[ni, nj] != 65535: # 包括0和有效值 neighbors.append(data[ni, nj]) if neighbors: new_data[i, j] = np.mean(neighbors) changed = True data = new_data if not changed: break # 处理剩余未填充的点(使用全局均值) if np.any(data == 65535): global_mean = np.mean(data[data != 65535]) data[data == 65535] = global_mean if not np.isnan(global_mean) else 0 return data
08-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值