图像处理:二值掩膜影像去噪与边缘强化

news2024/11/13 3:31:11

前言

这篇博客主要解决的一个问题是掩膜图像的噪声去除和边缘强化,如下图1所示。可以看到掩膜图像上有很多的斑点噪声,而且掩膜的轮廓也不够清晰。所以我们的目标就是一方面尽可能把这些斑点噪声去除,另一方面尽量突出掩膜边界。另外处理后的掩膜可以比真值大一些,但最好不能小。

图1 原始二值化影像

一、方法

因为之前有做过相关的工作,所以对于保留边界的斑点噪声消除第一反应是使用中值滤波。但很显然对于我们这个应用,单纯中值滤波是不够的。所以就想着那就采用多步处理,融合形态学操作。因此设计了一种如下图所示的方法。

图2 二值掩膜影像去噪与边缘强化技术路线图

中值滤波比较好理解,就是为了消除斑点噪声。而腐蚀操作这是为了处理一些稍大的面状的噪声,通过多次的腐蚀,尽可能消除它们。而后续的3次膨胀操作则是对应3次腐蚀,恢复成“原样”。然后是一个二值化,目的在于进一步去除一些噪声并且强调轮廓。因为有一些较暗的像素经过3次膨胀就会形成很大一块区域。因此,通过二值化可以过滤掉。最后膨胀一方面是为了满足要求“比真值大一些”,另一方面是填充由于腐蚀或者二值化带来的一些空洞。

二、代码

Python版本代码实现如下,非常简单。

import cv2
import numpy as np
import os


def findFiles(root_dir, filter_type, reverse=False):
    print("Finding files ends with \'" + filter_type + "\' ...")
    separator = os.path.sep
    paths = []
    names = []
    files = []
    for parent, dirname, filenames in os.walk(root_dir):
        for filename in filenames:
            if filename.endswith(filter_type):
                paths.append(parent + separator)
                names.append(filename)
    for i in range(paths.__len__()):
        files.append(paths[i] + names[i])
    print(names.__len__().__str__() + " files have been found.")
    paths.sort()
    names.sort()
    files.sort()
    if reverse:
        paths.reverse()
        names.reverse()
        files.reverse()
    return paths, names, files


if __name__ == '__main__':
    root_dir = "./mask" # 影像的输入路径
    out_dir = "./mask/refine"   # 结果的输出路径
    file_type = ".jpg"  # 文件类型
    median_kernel = 7   # 中值滤波卷积核大小
    morph_kernel1 = 5   # 形态学操作卷积核大小1
    morph_kernel2 = 5   # 形态学操作卷积核大小2
    morph_iter1 = 3 # 形态学操作迭代次数1
    morph_iter2 = 3 # 形态学操作迭代次数2

    paths, names, files = findFiles(root_dir, file_type)
    kernel1 = np.ones((morph_kernel1, morph_kernel1), np.uint8)
    kernel2 = np.ones((morph_kernel2, morph_kernel2), np.uint8)

    for i in range(len(files)):
        img_gray = cv2.imread(files[i], cv2.IMREAD_GRAYSCALE)

        # 主要流程:先做一次中值滤波,去除零碎像素噪声点
        # 然后再做3次腐蚀操作去除一些噪声块,再做3次膨胀操作填充回来
        # 然后,做个Otsu二值化,把一些潜在的噪声去除
        # 最后,为了使掩膜尽可能包含真值,再做一次膨胀操作
        img_median = cv2.medianBlur(img_gray, ksize=median_kernel)
        img_erode = cv2.erode(img_median, kernel1, iterations=morph_iter1)
        img_dilate = cv2.dilate(img_erode, kernel1, iterations=morph_iter1)
        ret, img_threshold = cv2.threshold(img_dilate, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
        img_mask = cv2.dilate(img_threshold, kernel2, iterations=morph_iter2)

        # 绘制轮廓,可视化,以及保存
        _, contours, _ = cv2.findContours(img_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        img_rgb = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2BGR)
        img_contours = cv2.drawContours(img_rgb, contours, -1, (0, 0, 255))
        cv2.imwrite(out_dir + "/" + names[i].split(".")[0] + "_refine.jpg", img_mask)
        cv2.imwrite(out_dir + "/" + names[i].split(".")[0] + "_range.jpg", img_contours)

        # 如果需要查看每一步结果,可以把下面这些注释掉
        # cv2.imwrite(out_dir + "/" + names[i].split(".")[0] + "_median.jpg", img_median)
        # cv2.imwrite(out_dir + "/" + names[i].split(".")[0] + "_erode.jpg", img_erode)
        # cv2.imwrite(out_dir + "/" + names[i].split(".")[0] + "_dilate.jpg", img_dilate)
        # cv2.imwrite(out_dir + "/" + names[i].split(".")[0] + "_threshold.jpg", img_threshold)

        print(i + 1, "/", len(files))

三、效果测试

为了测试效果,输出了中间过程的结果。如下是输入的原始影像。

然后首先进行中值滤波,结果如下。

然后进行3次腐蚀操作,以去除一些噪声,如下。

为了保证掩膜和输入一样,再膨胀3次,结果如下。

由于掩膜是0-1影像,为了过滤掉一些中间值,进行一次二值化,结果如下。

二值化以后难免会有一些空洞,因此使用膨胀操作进行填充,最终生成的掩膜如下。

将生成的掩膜范围绘制到输入影像上(红色框线)如下图所示。

总结

以上就是本文的全部内容,希望对大家的学习有所帮助

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/141732.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c#入门-多播委托,匿名函数

多播委托 委托作为变量,也可以和-。委托可以和方法组相加,但方法组和方法组不能相加。 储存多个函数时,调用委托会按照加的顺序依次执行。但返回值只使用最后绑定的函数。 使用 – 时,如果储存了这个值,那么会移除第一…

深圳电子行业的mes系统的需求分析方法~先达智控

深圳电子行业mes系统的需求分析方法导读:如今,制造业的行业竞争越来越激烈,减少产品成本、提高产品质量,缩短开发周期,已成为当前企业生产与发展中的一个重点方向。而对电子行业而言,厂家着重考虑并解决了产…

我们想要赚钱,就要理解赚钱的本质、要素、公式和障碍

想要赚钱,就要先理解赚钱,只有理解了赚钱,才能够赚到钱。赚钱的本质是商业,而商业的本质是交易,那交易的本质又是什么呢?就是价值交换。价值交换,就是我们怎么能与别人达成合作,并且…

朱江明赋予了零跑新的活力

作为今年风云的智能自主化新能源汽车品牌,零跑汽,一度是人们谈论的热点话题。零跑汽车在今年也取得了非常不错的销量,这么一个响当当的品牌在之前其实发展几度遭遇挫折,而正是创始人朱江明几次将零跑汽车起死回生,赋予…

使用基于python的neurora进行表征相似性分析(RSA)

发现了一款用于表征分析的Python API,还是挺方便的,这里简单介绍一下进行表征相似性分析的使用方法。官方文档见https://neurora.github.io/documentation/index.html下载pip install neurora表征相似性分析的知识可见:https://zhuanlan.zhih…

QSqlDatabase::drivers()输出为空的解决办法

解决问题&#xff1a;今天项目中需要用到QT连接MYSQL数据库进行数据库访问&#xff0c;使用数据库驱动加载代码&#xff1a; qDebug()<<"数据库驱动&#xff1a;"<<QSqlDatabase::drivers();打印出来的结果居然为空“()”。 尝试解决方案&#xff1a; …

逻辑漏洞渗透与攻防(三)之登录前端验证漏洞

目录 前言 登录前端验证漏洞 忘记密码 给邮箱/手机发验证码 前端验证绕过 设置新密码时改他人密码 ​编辑 某网站密码找回功能 链接的形式-链接token参数可逆 服务端验证逻辑缺陷 登录状态下修改密码等验证条件 参数带用户名等多阶段验证 重置密码 重置后的默认密…

软件产品科技成果鉴定需要提供哪些材料?软件测试费用怎么算?

一、软件产品科技成果鉴定是什么? 软件产品科技成果鉴定是有效评价科技成果质量和水平的方法之一&#xff0c;也是鼓励科技成果通过市场竞争等方式得到有效的评价和认可&#xff0c;可以推动科技成果的进步和转化。软件产品科技成果鉴定测试报告是申报国家、省、市科技成果奖…

SQLite Database Introduction

Use SQLite installed on Linux (CentOS7) to introduce.(You can also use python to install SQLite3 for learning.)•SQLite Preface•Introduction to SQLite Features•SQLite Data Type•SQLite Constraint•SQLite Syntax•SQLite Join•SQLite Database & Table•…

第01讲:ElasticSearch安装

一、什么是ElasticSearch 二、ElasticSearch的安装 Elasticsearch 分为 Linux 和 Windows 版本&#xff0c;基于我们主要学习的是 Elasticsearch 的 Java 客户端的使用&#xff0c;所以课程中使用的是安装较为简便的 Windows 版本。 2.1、Windows系统下安装ElasticSearch W…

KubeSphere 使用 OpenLDAP 进行统一认证完全指南

作者&#xff1a;申红磊&#xff0c;青云QingCloud 容器解决方案架构师&#xff0c;开源项目爱好者&#xff0c;KubeSphere Member。 背景 在实际使用中&#xff0c;会有一些用户&#xff0c;在不同场景中经常碰到 OpenLDAP 对接问题&#xff1a; 能否对接 LDAP&#xff1f;对…

go sync.Map源码分析

概述 go 语言中的map并不是并发安全的,在Go 1.6之前,并发读写map会导致读取到脏数据,在1.6之后则程序直接panic. 因此之前的解决方案一般都是通过引入RWMutex(读写锁)进行处理, 关于go为什么不支持map的原子操作,概况来说,对map原子操作一定程度上降低了只有并发读,或不存在并…

多线程看这一篇文章就够了

第一章 多线程概述 1 2 31. 什么是程序? 2. 什么是进程? 3. 什么是线程?程序1是为完成特定任务、用某种语言编写的一组指令的集合(一段静态的代码)进程1是程序的一次执行过程&#xff0c;或是正在运行的一个程序线程1 2 3进程可进一步细化为线程&#xff0c;是一个程序内部的…

软考网络工程师上午常考点

软考网络工程师上午常考点&#xff1a; **计算机硬件基础&#xff1a;**根据考纲分析&#xff0c;本章主要考查三个模块&#xff1a;计算机体系结构、存储系统、I/O输入输出系统&#xff0c;其中每一模块又分若干知识点。“计算机硬件基础”相当于软考中的“公共基础课”&…

12月更新 | Visual Studio Code Python

我们很高兴地宣布&#xff0c;2022年12月发布的适用于 Visual Studio Code Python 和 Jupyter 扩展现已推出&#xff01;此版本包括以下改进&#xff1a;Pylance 自动缩进 预览&#xff1a;浏览器中运行与调试 Python社区提供新扩展&#xff1a;Ruff如果您有兴趣&#xff0c;可…

C51单片机基础之串口编程实战

目录 一、串口编程寄存器分析 1、PCON : 电源控制寄存器 2、SCON&#xff1a;串行控制寄存器 二、自己实现串口初始化编程 三、发送一串字符串给到PC端编程 四、PC发送指令控制LED编程 五、串口中断实时控制LED编程 1、串口中断的中断号&#xff1a;interrupt4 2、串口…

Apache Doris Join 实现与调优实践|未来源码

推荐语&#xff1a; SQL 的支持力度和粒度&#xff0c;已经作为今天所有大数据计算引擎的重要衡量标准之一&#xff0c;而 SQL 的所有操作&#xff0c;可以分为简单操作&#xff08;如 where、limit等 filter 操作&#xff09;和复杂操作&#xff08;groupby、join 等聚合操作&…

SpringCloud微服务项目实战 - 3.App端文章

经历了新冠疫情始末&#xff0c;之后&#xff0c;多出门走走&#xff0c;看看山&#xff0c;看看海&#xff0c;吃好吃的 系列文章目录 项目搭建App登录及网关App文章 文章目录系列文章目录一、文章列表1. 数据库⑴. 导入文章数据库⑵. 表结构分析①. ap_article 文章基本信息…

MySQL慢SQL探究

文章目录前言1、慢SQL捕获慢查询追踪配置方式2、情况分析为什么查询会慢&#xff1f;2.1 SQL执行计划分析explain执行计划分析PROFILE分析OPTIMIZER_TRACE分析3、引擎参数配置分析I/O性能分析MySQL I/O参数其他原因分析网络抖动单表数据量过大总结前言 我们在日常开发中&#…

GeoServer搭建私有地图服务,Cesium引擎加载。

一、安装JDK 1、安装GeoServer是基于Java的环境&#xff0c;所以需要先装Jdk环境。 2、前往官网下载Java SE 3、下载GeoServer 1、前往官网下载最新稳定版 2、安装GeoServer 二、发布地图服务 1、启动geoserver 找到安装目录&#xff0c;bin/下的startup.bat,双击执行…