用 OpenCV 去除图片中的水印,骚操作!

点击上方“小白学视觉”,选择加"星标"或“置顶

重磅干货,第一时间送达

本文转自|AI算法与图像处理

这两天在 Stackoverflow 上面看到了一个有趣的案例,是关于OpenCV 的一个讨论,讨论的主题就是如何用 OpenCV 来去除下面图片中的水印,原图如下;

题主想把纸张中的 黑色圆环去掉只留下背景,因此一些感兴趣的 CV 爱好者在下面写上自己的想法、并贴上自己的解决代码,看到关于这个主题的答案后,只能感叹真正的大佬,都是从实践场景出发来解决问题,因为篇幅有限,在文章中只贴上得票最高的两个问答思路及代码, 让我们感受下他们思路的巧妙之处!

作者:Joel G

这老哥的思路,总体为五部分

  • 1,首先将图像转化为灰度图记为 A;

  • 2,利用霍夫圆在 A 中检测最大的椭圆,然后在新的图像中创建相同半径的圆得到 B;

  • 3,对灰度图和绘制圆的图像,应用OpenCV 的 bitwise_and 与运算,在原灰度图像 A 中提取只包含椭圆图像区域记为 C;

  • 4,对图像 C 设置合适的阈值进行文字提取最终得到 D;

  • 5, 对 图像 A 和 D 做bitwise_or 操作,即能够得到最终图像 E;

以下是在自己机子上跑出来的结果,从左到右依次对应上面的 A,C,D,E;效果如下

这个方法整体大概思想,先提取图像中圆环部分区域,对圆环内的文字做阈值分割进行提取,最后将提取到的图像区域在初始图像中进行替换,这里答主主要用到了三种重要算法:图像位运算(和、或)阈值分割霍夫圆检测,下面就是这个思路的代码部分,原答主用的是 C++ ,因为我做的是 Python 教程,就用 Python 转换了一下

import cv2
import numpy as npif __name__ =='__main__':img_path = "F:/Data/Ceshi1/shuiyin.jpg"img1 = cv2.imread(img_path)cv2.namedWindow('img1',cv2.WINDOW_FREERATIO)cv2.imshow('img1',img1)# 转化为 灰度图gray = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)# 创建一个白画布ellipse_img = np.full((img1.shape[0],img1.shape[1],3),0,dtype = np.uint8)print(ellipse_img.shape,ellipse_img[0][0])gray = cv2.GaussianBlur(gray,(5,5),0) # 高斯处理# 应用霍夫圆检测,检测出所有圆circles = cv2.HoughCircles(gray,cv2.HOUGH_GRADIENT,1,gray.shape[0]/8,100,100,100,0)# 找到最大的圆measure = 0.0x = 0.0y = 0.0for circle in (circles[0]):if circle[2] > measure:measure = circle[2]x = circle[0]y = circle[1]# 绘制圆cv2.circle(img1,(x,y),3,(0,255,0),-1,8,0)cv2.circle(img1,(x,y),int(measure),(0,255,0),2,8,0)# 绘制相同大小的圆ellipse_img =  cv2.ellipse(ellipse_img,(x,y),(int(measure),int(measure)),0,0,360,(255,255,255),-1,8)print(f'center x is {x} ,y is {y}, radius is {measure}')ellipse_img = cv2.cvtColor(ellipse_img,cv2.COLOR_BGR2GRAY)result = cv2.bitwise_and(gray,ellipse_img)cv2.namedWindow('bitwise and',cv2.WINDOW_FREERATIO)cv2.imshow('bitwise and',result)# 估计圆图像像素强度x = result[int(x+30)][int(y)]print(f'intensity is  {x}')# 阈值分割_,ellipse_img = cv2.threshold(result,int(x) - 10,250,cv2.THRESH_BINARY)# print('ellipse_img shape is {}'.format(ellipse_img.shape))cv2.namedWindow('threshold',cv2.WINDOW_FREERATIO)cv2.imshow('threshold',ellipse_img)# 使用 bitwise_or 方法print('shape ------------\n')print(ellipse_img.shape,gray.shape)res = cv2.bitwise_or(gray,ellipse_img)cv2.namedWindow('bitwise_or',cv2.WINDOW_FREERATIO)cv2.imshow('bitwise_or',res)cv2.waitKey(0)

最终结果预览比对

上面是第一种实现方法,这种方法思路主要用到阈值分割,从最终结果来看确实去掉了水印,但还是有一定的瑕疵:

  • 比如圆内文字背景与圆外背景是不一样的,存在很大色差,并且圆内的文字提取结果来看是不完整的;

  • 此方法不具有普遍性,因为这类方法只能针对于圆形水印,假设水印是不规则多边形此方法可能就会失效

下面介绍第二种思路,与第一种有相似的地方,也用到了阈值分割、图像像素位运算 相关算法,但同却又有自己的独特地方,从客观角度分析来看,这种方法的最终结果会更好一点

作者: dhanushka

思路主要分为四部分

  • 1,源图像记为 A,用形态学滤波器删除图像中文字区域,得到的图像记为 B;

  • 2,获取A,B 图像的之差,用 A-B ,得到区别后再用阈值分割进行处理,得到 C;

  • 3,阈值分割背景图像,提取水印覆盖的黑色部分记为 D;

  • 4,从 A 中提取在区域 D 中的像素,再用阈值分割方法分割像素,最终将提取到的像素贴到 B 中,得到最终去除水印的图像

代码贴在下方

import cv2
import numpy as npif __name__ =='__main__':img_path = "F:/Data/Ceshi1/shuiyin.jpg"im = cv2.imread(img_path)gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)background = gray.copy()for i in range(1,5):kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(2*i+1,2*i+1))# print('kernel size is ',kernel)background = cv2.morphologyEx(background,cv2.MORPH_CLOSE,kernel)background = cv2.morphologyEx(background,cv2.MORPH_CLOSE,kernel)diff = background - gray # 计算差距cv2.namedWindow('diff',cv2.WINDOW_FREERATIO) # 获取图像中前景背景之差cv2.imshow('diff',background)# 阈值分割获取黑色字体_,bw = cv2.threshold(diff,0,255,cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)# 阈值分割获取黑色区域cv2.namedWindow('bw_before', cv2.WINDOW_FREERATIO)cv2.imshow('bw_before', bw)_,dark = cv2.threshold(background,0,255,cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU)darkpix = cv2.countNonZero(dark)# 获取 dark非0d图像像素个数darkpix = [0]*darkpixindex = 0cv2.namedWindow('gray', cv2.WINDOW_FREERATIO)cv2.imshow('gray', gray)for r in range(dark.shape[0]):for c in range(dark.shape[1]):if(dark[r][c]):darkpix[index]  = gray[r][c]index = index +1# 阈值分割 dark 区域 因此我们在里面得到更深的像素darkpix = np.array(darkpix)_,darkpix = cv2.threshold(darkpix,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)cv2.namedWindow('darkpix', cv2.WINDOW_FREERATIO)cv2.imshow('darkpix', darkpix)# 把 取到的像素粘贴到 其渠道的 darker pixelscv2.namedWindow('dark',cv2.WINDOW_FREERATIO)cv2.imshow('dark',dark)index = 0for r in range(dark.shape[0]):for c in range(dark.shape[1]):if (dark[r][c]):bw[r][c] =  darkpix[index]index = index +1cv2.namedWindow('bw',cv2.WINDOW_FREERATIO)cv2.imshow('bw',bw)cv2.waitKey(0)

效果预览对比

相对第一种方法,第二种方法实用性更强一点,无论图像前景水印为什么形状的,这种方法都可适用(水印区域与其他背景像素强度差别大,且水印区域是连接在一起的)。

如果考虑到商用途径,只用 OpenCV 来解决复杂场景的图片水印问题,是不现实的,还需人工的干涉;但不现实并不代表它没有用,对于前后像素值较大、简单场景的水印,OpenCV 是完全可行的,若是再加上一个批量操作,变得更可了,大大解放我们的双手!

并且这两种思路中用到的的一些方法,是值得我们借鉴的,比如 图像像素或与和操作、形态学过滤、霍夫圆检测等技术,可借助于这些方法应用到其它场景,例如提取图像中圆形区域、行人路上斑马线检测、去除不规则图像连接区域等。

下载1:OpenCV-Contrib扩展模块中文版教程

在「小白学视觉」公众号后台回复:扩展模块中文教程即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。

下载2:Python视觉实战项目52讲

在「小白学视觉」公众号后台回复:Python视觉实战项目即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。

下载3:OpenCV实战项目20讲

在「小白学视觉」公众号后台回复:OpenCV实战项目20讲即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。

交流群

欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么软件可以去除照片水印?这3种方法可以帮你轻松搞定

大家有过这样的烦恼吗?在网上看到一张喜欢的图片,想要将它保存下来做壁纸,但是却发现图片里面有个大大的水印,十分影响效果。或者是在网上看到一张喜欢的头像,里面也有着一个大大的水印,我们该放弃这张图片…

学会这3个小技巧,轻松去图片水印

有些小伙伴在浏览个别平台时,会看到一些心水的图片,就想保存下来,拿来当头像壁纸,或是发朋友圈时用来配图。但是有些图片下载后会发现自带着平台水印,虽然理解它们是为了保护自身权益,但我们并不是进行商用…

脆弱水印 信息隐藏 QR分解

一、算法介绍 1、论文出处 F. Nejati, H. Sajedi and M. Mohammadi, “Fragile Watermarking for Image Authentication Using QR factorization and Fourier Transform,” 2019 5th International Conference on Web Research (ICWR), 2019, pp. 45-49, doi: 10.1109/ICWR.2…

watermark-removal: 一款超赞的开源图片去水印解决方案

公众号关注 「奇妙的 Linux 世界」 设为「星标」,每天带你玩转 Linux ! 今天给大家推荐一个开源项目,这个开源项目的图片去水印效果非常好。 这个开源项目就是:Watermark-Removal,是可基于机器学习的图像修复方法&…

德国商标注册程序

(一)进行商标查询。申请人应调查是否已注册相同或类似商标。可在德专利商标局慕尼黑总部、耶拿办事处和柏林技术信息中心的商标注册大厅以及该局网站免费查询。也可向位於该国24个大中城市的专利信息中心查询,四周可出结果,收费50…

商标注册查询入口官网在国家知识产权局商标局查询

最近程序员想要注册商标,注册之前要进行商标近似查询,提高通过成功率,前期不好好查询的话,要是被商标局驳回,规费可是不退的。所以,商标查询是很重要的环节,商标注册查询入口官网肯定是家知识产…

小度电视伴侣与小米电视音响对比评测

本文来自智能电视网 家里智能电视买了有小一年了,平时工作忙没怎么看,但是过年期间的使用率还挺高。本来对自家的电视还挺满意的,结果走亲戚的时候发现人家整的全套,投影、音响、K歌装备一应俱全,尤其是在亲戚家里看了…

刷爆朋友圈!前百度总裁陆奇最新AI重磅演讲:我的大模型世界观

文 / 高扬(微信公众号:量子论) 陆奇的演讲刷屏了,我认真看了他的演讲稿,收获颇丰。 陆奇提到,人类社会的发展,大致可分为:农业化、工业化和数字化三个阶段。 在三个递进的阶段中&…

陆奇博士最新演讲分享:我的大模型世界观(附PPT下载链接)

省时查报告-专业、及时、全面的行研报告库 省时查方案-专业、及时、全面的营销策划方案库 【免费下载】2023年3月份热门报告合集 【限时免费】ChatGPT4体验,无需翻墙直接用 ChatGPT调研报告(仅供内部参考) ChatGPT的发展历程、原理、技术架构…

2022.10.27每日刷题打卡

Phoenix and Beauty 题意:给出一个长度为n的序列a,在其中任意位置插入若干个[1,n]中的数,使得新序列b中的连续k项和都相等。 思路:其实很好想,我们可以把每个元素都处理成k个元素,然后保证这k个元素的和都…

Java面试题(每日总结晨读)

一、Java基础 1.ArrayList底层数据结构是什么?说一下你对它的理解 底层是一个长度可变的数组,当使用new ArrayList()的时候,底层是: public ArrayList() { this.elementData DEFAULTCAPACITY_EMPTY_ELEMENTDATA; //默认 容量&…

2022-05-07每日刷题打卡

2022-05-07每日刷题打卡 代码源——每日一题 题目描述 有一棵 n 个节点的以1为根的有根树。现在可以对这棵树进行若干次操作,每一次操作可以选择树上的一个点然后删掉这个点和它的儿子之间的所有边。 现在想要知道对于每一个 k∈[1,n],最少需要多少次…

《花雕学AI》哪种技能5年10年后还会被市场需要? 该如何提高这些能力?

随着AI人工智能、ChatGPT等新的技术革新的发展,未来职业场景确实会发生变化,一些传统的职业可能会被取代,而一些新的职业可能会出现。根据世界经济论坛所发布的《未来就业报告》,一半的劳动力需要在2025年之前完成技能重塑。那么&…

想清楚这些的程序员,35岁绝不会被毕业

一、成长与能力 1、成长理解 成长是一个过程。在这个过程中,可能会发生各种事件,有些是正向的,有些是负向的。这些事件会影响成长的速度与方向,体现到个人能力上。我是这么看待这个过程的: 【正向事件】&#xff1a…

华为鸿蒙 OS 尝鲜,跑了个 “hello world”!跑通后,我特么开始怀疑人生...

最近华为鸿蒙OS 2.0正式开源!关于鸿蒙的教程其实网上也已经有一些尝鲜的小伙伴分享的相关文章了,编者我按照步骤一步步跑下来,整个流程还是非常简单的,尤其是对Android开发的小伙伴来说,从IDE到项目的创建及项目的编译…

梅科尔工作室-鸿蒙笔记1

梅科尔工作室-于天姿-鸿蒙笔记1 一、主要目录配置文件作用 1、stage模型 其中常用模块为app.json模块,entry模块,module.json模块。 app.json5中,icon是应用图标,可在pages中添加图片,从而改变图标;labe…

华为鸿蒙跑了个“hello world”!跑通后,我特么开始怀疑人生....

点击上方[全栈开发者社区]→右上角[...]→[设为星标⭐] 作者:一个俗人 来源:https://my.oschina.net/u/169565/blog/4557279 最近华为鸿蒙OS 2.0正式开源!关于鸿蒙的教程其实网上也已经有一些尝鲜的小伙伴分享的相关文章了,编者我…

值得一谈的鸿蒙2.0,程序员们拿起你们手中的编译器撸一下hello world

一款“面向未来”、面向全场景(移动办公、运动健康、社交通信、媒体娱乐等)的分布式操作系统 。现已开源,名为OpenHarmony。 2019年8月9日,华为在HDC开发者大会上正式发布鸿蒙系统。 2020年9月10日,华为在HDC开发者大会上如约发布鸿蒙 2.0,并面向应用开发者发布Beta版本…

梅克尔工作室-赵一帆-鸿蒙笔记4

1.页面的跳转和数据传递 Ability是一种包含用户界面的应用组件,主要用于和用户进行交互。Ability也是系统调度的单元,为应用提供窗口在其中绘制界面。 每一个Ability实例,都对应于一个最近任务列表中的任务。 一个应用可以有一个Ability&…

鸿蒙手机Beta版本官宣!我们带着成果和Code来了!!

12月16号,也就是今天,华为鸿蒙OS手机开发者Beta版本来啦! 发布会给出了最新版的开发环境(DevEco Studio 2.0 Beta3),支持手机等多设备模拟器的跨端运行调试,大家已经可以上手体验鸿蒙手机应用开…