当前位置: 首页 > news >正文

OpenCV-Python图形图像处理:利用黑帽去除图像浅色水印

☞ ░ 前往老猿Python博客 https://blog.csdn.net/LaoYuanPython ░

一、黑帽简介

黑帽(Black Hat),又称“底帽”运算,其结果图像为闭运算图与原图像的差,即:
dest=close(src,kernal)-src

由于闭运算是先膨胀和腐蚀,因此闭运算会去除图像中的小黑点,同时也会扩大图像前景轮廓的范围,实际上也就是放大了图像前景色区域,因此从闭运算图减去原图的运算结果突出了比原图轮廓周围的区域更暗的区域,此外黑帽还能得到图像内部的小孔,或者前景色中的小黑点。因此黑帽运算可以用于提取亮背景中的细小暗物体。

黑帽在OpenCV-Python的调用语法如下:
morphologyEx(src, CV2.MORPH_BLACKHAT, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)

关于morphologyEx的介绍请参考《OpenCV-Python图像形态变换概述及morphologyEx函数介绍: https://blog.csdn.net/LaoYuanPython/article/details/109556425》。

二、利用黑帽去除暗水印

2.1、案例1:从地图中去除水印

2.1.1、案例原图

在如下图像(文件名:带水印中国地图.jpg):
在这里插入图片描述
在上述地图中存在两行比较淡的水印:“老猿Python”、“https://blog.csdn.net/LaoYuanPython”。

2.1.2、图像黑帽运算代码

import cv2
import numpy as np

from opencvPublic import print2DMatrix,preparePreviewImg,previewImgList,previewImg

def morphologyExTest(imgObj,imgTitle=''):
    if isinstance(imgObj, str):
        img = cv2.imread(imgObj)#, cv2.IMREAD_GRAYSCALE)
        if img is None:
            img = cv2.imdecode(np.fromfile(imgObj, dtype=np.uint8), -1)
        imgTitle = imgTitle+imgObj+': '
    else:
        imgTitle = imgTitle + ': '
    if len(img.shape)==2: channel = 1
    else: channel = img.shape[2]
    if channel==3:
        img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    elif channel==4:
        img = cv2.cvtColor(img,cv2.COLOR_BGRA2GRAY)
    ksize = (3,3)
    kernal = cv2.getStructuringElement(cv2.MORPH_RECT,ksize )
    #preparePreviewImg(img,  imgTitle + '原图')
    preparePreviewImg(cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernal),imgTitle+f'黑帽,矩形核大小{ksize}')

def morphologyTest():
    morphologyExTest(r'f:\pic\带水印中国地图.jpg')
    previewImgList()

morphologyTest()

上面代码中使用的图像预览的函数请见《OpenCV-Python图像运算变换处理:开运算和闭运算以及不同核矩阵的影响分析: https://blog.csdn.net/LaoYuanPython/article/details/109984045》的介绍。

2.1.3、结果图像

经上述代码处理后,该原图黑帽运算的结果图像如下:
在这里插入图片描述
可以看到黑帽运算后提取到了一副去除水印的完整地图图片。

2.2、案例2:处理彩色图像

将上述代码中处理的原图替换为如下图像(文件名:白底蓝线浅水印.jpg),并将核大小调整为7*7:
在这里插入图片描述

得到如下黑帽结果图像:
在这里插入图片描述
可以看到水印文字被去除,但留下了部分缝隙。
对上述图像进行一次闭运算,得到如下图像:
在这里插入图片描述
可以看到黑帽运算中的部分缝隙得到了部分填充。上述处理过程如果使用(3,3)大小的核,则无法达到上述的效果,相关线段无法提取出来。

以上述图像对应的灰度图像作为mask再将原图像进行自与运算,就可以得到原图像中除去水印的效果图如下:
在这里插入图片描述
通过调整核大小以为9*9时,上述线段交叉处的黑色部分可以填充为蓝色,效果会更好一些。

2.3、案例3:一个黑白图的处理

2.3.1、源图像(文件名:hill.JPG)

在这里插入图片描述

2.3.2、黑帽图

在这里插入图片描述
上图看起来都是黑色,对该图乘以4倍因子得到如下图:
在这里插入图片描述
可以看到提取的是原图中白色部分的周边边缘,该效果很好地体现了黑帽运算的功能。

三、一个问题的解释

前面介绍了,黑帽运算可以用于提取提取亮背景中的细小暗物体,通过案例3可以看到这点,但为什么反而可以在案例1和2中用于去除图像中的浅色水印呢?我们以第二个例子为例来解释:

  1. 首先我们来看看原图进行闭运算的结果图,如下
    在这里插入图片描述
    可以看到闭运算后,由于整图的亮背景色,导致闭运算后,原图的那些线条和文字几乎接近不可见,但并不是都消失了,都该图乘以0.5降低整体亮度后,得到如下图像:
    在这里插入图片描述
    可以看到文字信息不见了,但线条还在。由此可以说明,作为水印的文字信息在闭运算中被膨胀清除了,而线条在闭运算中虽然提高了亮度但还是存在的,只是与周边的颜色差异很小,无法看清,当乘以0.5后,这个差异就显现出来了,由此可见该线条的颜色灰度值接近255。

  2. 由于黑帽是闭运算结果图减原图像,由于原图像中背景色主色为白色,其像素灰度值值为255,而线条颜色为蓝色,对应灰度值为127.5(计算方法请参见《图像处理术语解释:灰度、色相、饱和度、亮度、明度、阿尔法通道、HSL、HSV、RGBA、ARGB和PRGBA以及Premultiplied Alpha(Alpha预乘)等基础概念详解》),闭运算结果图减原图像后,得到灰度值接近于255-127.5=127.5,因此黑帽运算后线条能比较清晰的显示。

因此通过黑帽运算后,背景色变成了黑色,线条比较清晰的展示,文字消失了,从而实现了水印文字的去除。从上面的介绍可以得出,水印文字之所以能消除,是因为水印文字颜色的灰度值与背景白色的灰度值相差不大。

四、小结

本文简单介绍了黑帽的概念、原理和作用,以及OpenCV-Python的具体实现,并提供了两个利用黑帽去除图像水印的案例和一个提取白色图像周边黑色轮廓的案例,通过黑帽的结果图像,再作为mask去与原图像进行运算,即可以得到原图像中去除水印后的亮色图像部分。黑帽运算和顶帽类似,用一个结构元素(核矩阵)通过闭操作从一副图像中删除前景色中比较暗的部分,留下来前景色中相对比较亮的细小部分,就是从图像的亮背景上提取细小的暗物体,黑帽这个特性也可以用于校正不均匀光照的影响(请参考博文:《光照不均匀图像分割技巧2——顶帽变换和底帽变换》)。

写作不易,敬请支持:

如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!

四、形态变换博文传送门

下面是老猿博文中与形态变换相关的博文列表:

  1. https://blog.csdn.net/LaoYuanPython/article/details/109441709 OpenCV-Python图像处理:腐蚀和膨胀原理及erode、dilate函数介绍
  2. https://blog.csdn.net/LaoYuanPython/article/details/109984045 OpenCV-Python图像运算变换处理:开运算和闭运算以及不同核矩阵的影响分析
  3. https://blog.csdn.net/LaoYuanPython/article/details/109556425 OpenCV-Python图像形态变换概述及morphologyEx函数介绍
  4. https://blog.csdn.net/LaoYuanPython/article/details/109768675 OpenCV-Python图像运算变换处理:形态学梯度运算及分类
  5. https://blog.csdn.net/LaoYuanPython/article/details/110195287 OpenCV-Python中预览超大图的程序实现方法
  6. https://blog.csdn.net/LaoYuanPython/article/details/110223709 OpenCV-Python图形图像处理:利用TopHat顶帽获取背景色中的噪点
  7. https://blog.csdn.net/LaoYuanPython/article/details/110294445 OpenCV-Python图形图像处理:利用黑帽去除图像浅色水印
  8. https://blog.csdn.net/LaoYuanPython/article/details/110676764 OpenCV-Python击中击不中HITMISS形态变换详解

更多OpenCV-Python的介绍请参考专栏《OpenCV-Python图形图像处理 》
专栏网址:https://blog.csdn.net/laoyuanpython/category_9979286.html

关于老猿的付费专栏

老猿的付费专栏《使用PyQt开发图形界面Python应用 》(https://blog.csdn.net/laoyuanpython/category_9607725.html)专门介绍基于Python的PyQt图形界面开发基础教程,付费专栏《moviepy音视频开发专栏》 (https://blog.csdn.net/laoyuanpython/category_10232926.html)详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,两个专栏都适合有一定Python基础但无相关知识的小白读者学习。

付费专栏文章目录:《moviepy音视频开发专栏文章目录》(https://blog.csdn.net/LaoYuanPython/article/details/107574583)、《使用PyQt开发图形界面Python应用专栏目录 》(https://blog.csdn.net/LaoYuanPython/article/details/107580932)。

对于缺乏Python基础的同仁,可以通过老猿的免费专栏《专栏:Python基础教程目录》(https://blog.csdn.net/laoyuanpython/category_9831699.html)从零开始学习Python。

如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。

跟老猿学Python、学OpenCV!

☞ ░ 前往老猿Python博文目录 https://blog.csdn.net/LaoYuanPython ░

相关文章:

  • OpenCV击中击不中HITMISS形态变换公开资料汇总
  • OpenCV图形图像击中击不中HITMISS变换处理基础知识
  • OpenCV-Python图像击中击不中变换理解的关键知识点及自定义实现
  • OpenCV-Python击中击不中HITMISS形态变换详解
  • OpenCV-Python击中击不中变换案例:长方形边界提取
  • OpenCV-Python击中击不中变换案例:绿叶轮廓提取
  • OpenCV-Python击中击不中变换案例:真图作核的绳网结匹配
  • 你不一定全知道的四种Python装饰器实现详解
  • 类的类装饰器简单实现思路及案例
  • OpenCV-Python图形图像处理:自用的一些工具函数源代码
  • OpenCV-Python图形图像处理:自用的一些工具函数功能及调用语法介绍
  • OpenCV-Python图形图像处理:split通道拆分和数组矩阵访问通道
  • Python图像处理:OpenCV HSV和标准表示法的区别以及转换
  • OpenCV-Python图像处理:用inRange刷选图像中指定颜色对象案例
  • PyQt事件信号实战:为QTableWidget提供键盘事件
  • 【跃迁之路】【641天】程序员高效学习方法论探索系列(实验阶段398-2018.11.14)...
  • 30天自制操作系统-2
  • Android 控件背景颜色处理
  • C++11: atomic 头文件
  • Computed property XXX was assigned to but it has no setter
  • Java读取Properties文件的六种方法
  • js
  • js ES6 求数组的交集,并集,还有差集
  • JS基础篇--通过JS生成由字母与数字组合的随机字符串
  • SQLServer之索引简介
  • vue脚手架vue-cli
  • 阿里中间件开源组件:Sentinel 0.2.0正式发布
  • 闭包--闭包之tab栏切换(四)
  • 从零搭建Koa2 Server
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • ​2020 年大前端技术趋势解读
  • ###STL(标准模板库)
  • #1015 : KMP算法
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (Demo分享)利用原生JavaScript-随机数-实现做一个烟花案例
  • (附源码)springboot车辆管理系统 毕业设计 031034
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (四) Graphivz 颜色选择
  • (转) RFS+AutoItLibrary测试web对话框
  • (最优化理论与方法)第二章最优化所需基础知识-第三节:重要凸集举例
  • .dwp和.webpart的区别
  • .gitignore文件—git忽略文件
  • .net core 6 集成和使用 mongodb
  • .NET Core WebAPI中封装Swagger配置
  • .NET 将多个程序集合并成单一程序集的 4+3 种方法
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • .NET 实现 NTFS 文件系统的硬链接 mklink /J(Junction)
  • .NET 线程 Thread 进程 Process、线程池 pool、Invoke、begininvoke、异步回调
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)
  • .NET/C# 阻止屏幕关闭,阻止系统进入睡眠状态
  • /etc/shadow字段详解
  • @require_PUTNameError: name ‘require_PUT‘ is not defined 解决方法
  • @ResponseBody