繁体   English   中英

如何使用 python opencv 从图像中删除隐藏标记?

[英]How to remove hidden marks from images using python opencv?

我想从事一个小项目来挑战我的计算机视觉和图像处理技能。 我遇到了一个项目,我想从图像中删除隐藏的标记。 此处隐藏是指在 rgb 空间中不易看到的水印,但当您转换为 hsv 或其他一些空间时,标记变得可见。

这是一个例子:

BGR 空间:

在此处输入图像描述

HSV空间:

在此处输入图像描述

我尝试了不同的方法,但能够实现从图像中删除这些水印的解决方案。 我在这里发布这个问题以获得不同的想法来解决这个问题。

我试过的:

我尝试了各种方法,但都没有奏效,共享代码可能无济于事。 没有必要为其提供代码,将不胜感激伪代码、想法或任何线索。

  1. 我注意到隐藏的标记都是类似于 RGB(90,94,105) 的 colors。 当我分别展示 R、G 和 B 时,我注意到水印仅在 B 通道中可见。 我认为如果调整/删除 B 通道中的标记并再次合并图像,可能会得到更好的结果。

代码

b,g,r = cv2.split(img)
b = b//2;
r = cv2.merge((r,g,b))
cv2.imshow("image",r)

问题:这并不能解决问题,它确实使 colors 变暗,但图像 colors 也受到干扰。

  1. 我试着玩 B 频道,看看能不能完成一些事情。

  2. 我还注意到,如果我们将图像转换为 LUV 空间,那么标记在 V 空间中是可见的。

这可能是一种可能的方法。 基本思想是在 HSV 通道中存在可见的边缘,这些边缘在原始图像中不存在。 以下是并排的 H、S 和 V 通道:

在此处输入图像描述

因此,如果我们找到原始图像中的边缘和 HSV 图像中的边缘并区分它们,水印应该会出现。 然后可以将其用作掩码,使用OpenCV inpaint在原始图像中进行修复。

我只是在终端中使用ImageMagick ,但它都可以用OpenCVPILscikit-image来完成:

# Detect edges visible in original image and auto-level
convert watermarked.png -colorspace gray -auto-level -canny 0x1+1%+3% -auto-level  RGB-edges.png

在此处输入图像描述

# Find visible edges in H, S and V colourspace, generate mean across all three and auto-level
convert watermarked.png -colorspace hsv -separate -canny 0x1+1%+3% -evaluate-sequence mean -auto-level HSV-edges.png

在此处输入图像描述

# Find changemask between the two sets of edges
convert RGB-edges.png HSV-edges.png -compose changemask -composite result.png

在此处输入图像描述

这个想法是水印现在被识别为黑色,所以使用黑色区域(可能在形态上是封闭的)作为OpenCV中的掩码来修复 - 参见上面的链接。

我没有找到任何完全解决问题的答案。 不过,我感谢大家的努力(谢谢)。 我自己做了一些事情,并想分享。 它几乎没有质量损失(有点蓝色模糊),但成功地去除了水印。 解决方案非常简单,但需要时间来分析图像。

如果有人可以扩展这种方法并提出更好的方法,我会非常高兴

我观察到水印仅在 B 空间可见(RGB 之外),在 R 和 G 空间中没有水印的痕迹。

B空间:

在此处输入图像描述

我还在某处发红,与 R 和 G 通道相比,蓝光对整体图像的贡献很小,所以这就是我决定做的事情。

充分模糊 B 通道以去除这些图案的痕迹。 以下是 B 通道之后的显示方式:

在此处输入图像描述

最后,将图像与新的 B 通道、之前的 R 和之前的 G 通道合并。 以下是 RGB 通道之后的显示方式:

在此处输入图像描述

使用方法的优点是痕迹消失了。

唯一的缺点是蓝色和紫色的colors出现在黑边,图像总体上有点偏蓝。

我的代码:

import cv2
from matplotlib import pyplot as plt
import numpy as np
img = cv2.imread("img.png")
b, g, r = cv2.split(img) # split into B,G,R spaces 
b = cv2.GaussianBlur(b, None, 8)
plt.imshow(cv2.merge((r,g,b)), cmap='gray')

这是您在 Python/OpenCV 中处理的轻微变化和扩展。

主要区别在于我使用中位数而不是模糊,并且我尝试提取黑线并将它们强加在中位数上,然后再重新组合。

输入:

在此处输入图像描述

import cv2
import numpy as np

# read image
img = cv2.imread("cartoon_hidden_marks.png")

# separate channels
b,g,r = cv2.split(img)

# median filter blue
median = cv2.medianBlur(b, 21)

# threshold blue image to extract black lines
thresh = cv2.threshold(b, 20, 255, cv2.THRESH_BINARY)[1]

# apply thresh to median
b_new = cv2.bitwise_and(median, thresh)

# combine b_new, g, b
img_new = cv2.merge([b_new,g,r])

# write results to disk
cv2.imwrite("cartoon_hidden_marks_median.jpg", median)
cv2.imwrite("cartoon_hidden_marks_thresh.jpg", thresh)
cv2.imwrite("cartoon_hidden_marks_new_blue.jpg", b_new)
cv2.imwrite("cartoon_hidden_marks_result.png", img_new)

# display it
cv2.imshow("median", median)
cv2.imshow("thresh", thresh)
cv2.imshow("b_new", b_new)
cv2.imshow("img_new", img_new)
cv2.waitKey(0)

蓝色通道中位数:

在此处输入图像描述

蓝色通道阈值(用于黑线):

在此处输入图像描述

新的蓝色通道:

在此处输入图像描述

结果:

在此处输入图像描述


许多错误的蓝线现在是黑色的,但不是全部。 增加阈值会得到更多的黑线,但隐藏的标记会再次出现部分。

Python/OpenCV 中另一个简单的解决方案是简单地将绿色通道替换为蓝色通道,因为大多数绿色通道的强度分布与蓝色通道的强度分布大致相同。

输入:

在此处输入图像描述

import cv2
import numpy as np

# read image
img = cv2.imread("cartoon_hidden_marks.png")

# separate channels
b,g,r = cv2.split(img)

# combine replacing b with g
img_new = cv2.merge([g,g,r])

# write results to disk
cv2.imwrite("cartoon_hidden_marks_result2.png", img_new)

# display it
cv2.imshow("result", img_new)
cv2.waitKey(0)

结果:

在此处输入图像描述

问题是外套和绿树的颜色和质地略有不同。

可以尝试修改绿色通道图像的副本,以将平均值和标准差作为蓝色通道来解决涂层问题。 对于绿色树,它位于水印区域之外,因此可以使用 inRange 来掩盖绿色树的颜色,然后在绿色通道的副本中替换蓝色通道图像的树。 然后重新组合修改后的绿色通道代替蓝色通道。

如果您设法隔离了任何通道中的水印,您应该能够对其进行阈值化并创建二进制掩码。 然后你可以使用修复来填补空白,例如:

    clean_image = cv2.inpaint(marked_image, mask_of_marks, 3, cv2.INPAINT_TELEA)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM