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

如何使用形态学操作去除同灰度噪声并保留图像竖线与对角线?

解决思路

1 定向形态学筛选替换通用核

你当前使用的椭圆、大尺寸矩形核适配性太泛,是引入额外噪声的主要原因,可直接针对目标线条方向制作专属结构元:

  • 垂直方向保留:使用Size(1, N)的矩形核做形态学运算,N设置为你需要保留的垂直线条最小长度,只有高度满足要求的垂直线条会被留存,短于该长度的噪声直接被过滤
  • 45°/135°对角线方向:手动构造对应方向的斜线结构元,核内仅沿目标斜线位置赋值为1,其余为0,长度同样匹配目标线条的最小长度,仅会保留和核方向一致、长度达标的对角线条,其余方向杂点直接被滤除

2 几何特征过滤替代灰度阈值筛选

因为噪声和目标灰度一致,仅靠灰度运算无法区分,可直接基于线条的几何特征做筛选:

  • 先调用HoughLinesP霍夫线变换检测出图中所有直线段
  • 按斜率做过滤:斜率绝对值>5的判定为垂直线,斜率落在0.81.2或者-1.2-0.8区间的判定为对角线
  • 把符合条件的线段在空白画布上重新绘制,即可完全避开灰度一致的噪声干扰,直接得到纯净的目标线条结果

3 现有逻辑的后处理优化

如果你不想改动原有运算逻辑,可在当前带噪声的输出结果上追加连通域过滤步骤:

  • 调用connectedComponentsWithStats计算所有连通域的面积、宽高比、最小外接矩形倾斜角
  • 过滤掉面积过小、宽高比不符合细长线条特征、角度不在垂直/对角线范围内的连通域,剩余即为目标线条

优化后参考代码
int main() {
    Mat src = imread("cau3.png", IMREAD_GRAYSCALE);
    Mat dst;
    
    // 自定义方向结构元,长度可根据实际线条长度调整
    Mat kernel_vertical = getStructuringElement(MORPH_RECT, Size(1, 25));
    // 手动构造45度斜线核,长度21
    Mat kernel_45 = Mat::zeros(21, 21, CV_8U);
    for(int i=0; i<21; i++) kernel_45.at<uchar>(i, 20-i) = 1;
    // 手动构造135度斜线核,长度21
    Mat kernel_135 = Mat::zeros(21, 21, CV_8U);
    for(int i=0; i<21; i++) kernel_135.at<uchar>(i, i) = 1;

    Mat res_vertical, res_45, res_135;
    // 对每个目标方向单独做顶帽运算,直接提取对应方向的亮线条
    morphologyEx(src, res_vertical, MORPH_TOPHAT, kernel_vertical);
    morphologyEx(src, res_45, MORPH_TOPHAT, kernel_45);
    morphologyEx(src, res_135, MORPH_TOPHAT, kernel_135);

    // 合并三个方向的结果
    bitwise_or(res_vertical, res_45, dst);
    bitwise_or(dst, res_135, dst);

    // 可选:连通域过滤残留小噪声
    Mat labels, stats, centroids;
    int num_labels = connectedComponentsWithStats(dst, labels, stats, centroids);
    for(int i=1; i<num_labels; i++) {
        // 过滤面积小于30的连通域,阈值可自行调整
        if(stats.at<int>(i, CC_STAT_AREA) < 30) {
            for(int y=stats.at<int>(i, CC_STAT_TOP); y<stats.at<int>(i, CC_STAT_TOP)+stats.at<int>(i, CC_STAT_HEIGHT); y++) {
                for(int x=stats.at<int>(i, CC_STAT_LEFT); x<stats.at<int>(i, CC_STAT_LEFT)+stats.at<int>(i, CC_STAT_WIDTH); x++) {
                    if(labels.at<int>(y,x) == i) dst.at<uchar>(y,x) = 0;
                }
            }
        }
    }

    imshow("result", dst);
    waitKey(0);
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 21:54:01