1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 用 OpenCV 去除图片中的水印 骚操作!

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

时间:2019-03-01 02:37:01

相关推荐

用 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 转换了一下

importcv2importnumpyasnpif__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.0forcirclein(circles[0]):ifcircle[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'centerxis{x},yis{y},radiusis{measure}')ellipse_img=cv2.cvtColor(ellipse_img,cv2.COLOR_BGR2GRAY)result=cv2.bitwise_and(gray,ellipse_img)cv2.namedWindow('bitwiseand',cv2.WINDOW_FREERATIO)cv2.imshow('bitwiseand',result)#估计圆图像像素强度x=result[int(x+30)][int(y)]print(f'intensityis{x}')#阈值分割_,ellipse_img=cv2.threshold(result,int(x)-10,250,cv2.THRESH_BINARY)#print('ellipse_imgshapeis{}'.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 中,得到最终去除水印的图像

代码贴在下方

importcv2importnumpyasnpif__name__=='__main__':img_path="F:/Data/Ceshi1/shuiyin.jpg"im=cv2.imread(img_path)gray=cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)background=gray.copy()foriinrange(1,5):kernel=cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(2*i+1,2*i+1))#print('kernelsizeis',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)forrinrange(dark.shape[0]):forcinrange(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)#把取到的像素粘贴到其渠道的darkerpixelscv2.namedWindow('dark',cv2.WINDOW_FREERATIO)cv2.imshow('dark',dark)index=0forrinrange(dark.shape[0]):forcinrange(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“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。