从图像中去除透明水印 - python

如何解决从图像中去除透明水印 - python

我正在尝试从图像中去除透明水印。

这是我的示例图片:

我想从图像中删除文本“水印”。如您所见,文本是透明的。所以我想将该文本替换为原始背景。

这样的东西将是我想要的输出:

我尝试了一些示例(我目前正在使用 cv2,如果其他库可以解决问题也请推荐),但没有一个离成功很近。我知道要走的路是有一个面具(如 this 帖子),但他们都已经有面具的图像,但我没有。

这是我尝试使用蒙版做的事情,我将饱和度调低为黑白,并创建了一个图像“imagemask.jpg”,然后尝试使用 for 循环遍历像素:

mask = cv2.imread('imagemask.jpg')
new = []
rows,cols,_ = mask.shape
for i in range(rows):
    new.append([])
    #print(i)
    for j in range(cols):
        k = img[i,j]
        #print(k)
        if all(x in range(110,130) for x in k):
            new[-1].append((255,255,255))
        else:
            new[-1].append((0,0))

cv2.imwrite('finalmask.jpg',np.array(new))

然后想使用掩码的代码,但我意识到“finalmask.jpg”是一团糟......所以我没有尝试使用掩码的代码。

这真的可能吗?我已经尝试了大约 3 个小时,但没有收到任何运气...

解决方法

这不是小事,我的朋友。雪上加霜的是,您的图像分辨率非常低,被压缩并且具有令人讨厌的眩光 - 这根本无助于处理。请查看您的输入并相应地设置您的期望。话虽如此,让我们尝试用我们所拥有的来获得最佳结果。这些是我建议的步骤:

  1. 尝试分割图像中的水印文本
  2. 过滤分割掩码并尝试获得尽可能干净的二进制掩码
  3. 使用文本遮罩以输入图像作为参考修补违规区域

现在,正如您已经看到的,棘手的部分是分割文本。在尝试了一些技巧和色彩空间之后,我发现 CMYK color space - 特别是 K 通道 - 提供了有希望的结果。文字相当清晰,我们可以尝试使用 Adaptive Thresholding,让我们看看:

# Imports
import cv2
import numpy as np

# Read image
imagePath = "D://opencvImages//"
img = cv2.imread(imagePath+"0f5zZm.jpg")

# Store a deep copy for the inpaint operation:
originalImg = img.copy()

# Convert to float and divide by 255:
imgFloat = img.astype(np.float) / 255.

# Calculate channel K:
kChannel = 1 - np.max(imgFloat,axis=2) 

OpenCV 不直接提供 BGRCMYK 的转换,因此我必须手动使用 conversion formula 获取 K 频道。这是非常简单的。 K(或 Key)通道代表最低强度(黑色)的像素,颜色为白色。这意味着几乎是白色的文本将呈现为黑色...这是输入的 K 通道:

你看到输入上较暗的像素在这里几乎是白色的了吗?这很好,它似乎在文本和其他一切之间得到了清晰的分离。很遗憾,我们的右侧有一些令人讨厌的大眩光。无论如何,转换涉及float操作,所以要小心data types。也许我们可以通过一些亮度/对比度调整来改善这个图像。只是一点点,我只是想将更多的文字与那讨厌的眩光分开:

# Apply a contrast/brightness adjustment on Channel K:
alpha = 0
beta = 1.2
adjustedK = cv2.normalize(kChannel,None,alpha,beta,cv2.NORM_MINMAX,cv2.CV_32F)

# Convert back to uint 8:
adjustedK = (255*adjustedK).astype(np.uint8)

这是调整后的图像:

文字和眩光之间似乎有更多的分离。好的,让我们对这个坏男孩应用 Adaptive Thresholding 以获得初始分割掩码:

# Adaptive Thresholding on adjusted Channel K:
windowSize = 21
windowConstant = 11
binaryImg = cv2.adaptiveThreshold(adjustedK,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY_INV,windowSize,windowConstant)

你看到我在这里使用了一个不太大的 windowSize 来进行阈值设置吗?如果您愿意,可以随意调整这些参数。这是我得到的二进制图像:

是的,噪音很大。以下是我建议获得更干净的掩码的建议: 有一些明显的斑点 比文本。同样,还有其他比文本的 blob。让我们找出大斑点和小斑点并减去它们。如果我们正确设置参数,生成的图像应该包含文本。让我们看看:

# Get the biggest blobs on the image:
minArea = 180
bigBlobs = areaFilter(minArea,binaryImg)

# Filter the smallest blobs on the image:
minArea = 20
smallBlobs = areaFilter(minArea,binaryImg)

# Let's try to isolate the text:
textMask = smallBlobs - bigBlobs
cv2.imshow("Text Mask",textMask)
cv2.waitKey(0)

这里我使用了一个名为 areaFilter 的辅助函数。此函数返回图像中高于最小面积阈值的所有斑点。我将在答案的末尾发布该功能。同时,看看这些很酷的图片:

大斑点:

过滤后的小斑点:

它们之间的区别:

可悲的是,似乎字符的某些部分在过滤操作中没能幸存下来。那是因为眩光和文本的交集太多,算法无法得到清晰的分离。可以使修复结果受益的是此蒙版上的微妙模糊,以消除该压缩别名。让我们应用一些 Gaussian Blur 来平滑蒙版:

# Blur the mask a little bit to get a
# smoother inpanting result:
kernelSize = (3,3)
textMask = cv2.GaussianBlur(textMask,kernelSize,cv2.BORDER_DEFAULT)

内核没有那么大,我只是想要一个微妙的效果。结果如下:

最后,让我们应用内画:

# Apply the inpaint method:
inpaintRadius = 10
inpaintMethod = cv2.INPAINT_TELEA
result = cv2.inpaint(originalImg,textMask,inpaintRadius,inpaintMethod)
cv2.imshow("Inpaint Result",result)
cv2.waitKey(0)

这是最终结果:

嗯,考虑到输入图像,还不错。您可以尝试通过调整一些值来进一步改善结果,但我的老兄,这种生活的现实是输入图像一开始并不是那么好。这是 areaFilter 函数:

def areaFilter(minArea,inputImage):

    # Perform an area filter on the binary blobs:
    componentsNumber,labeledImage,componentStats,componentCentroids = \
    cv2.connectedComponentsWithStats(inputImage,connectivity=4)

    # Get the indices/labels of the remaining components based on the area stat
    # (skip the background component at index 0)
    remainingComponentLabels = [i for i in range(1,componentsNumber) if componentStats[i][4] >= minArea]

    # Filter the labeled pixels based on the remaining labels,# assign pixel intensity to 255 (uint8) for the remaining pixels
    filteredImage = np.where(np.isin(labeledImage,remainingComponentLabels) == True,0).astype('uint8')

    return filteredImage

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res