简体   繁体   English

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

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

I wanted to work on a small project to challenge my computer vision and image processing skills.我想从事一个小项目来挑战我的计算机视觉和图像处理技能。 I came across a project where I want to remove the hidden marks from the image.我遇到了一个项目,我想从图像中删除隐藏的标记。 Hidden here refers to the watermarks that are not easily visible in rgb space but when you convert into hsv or some other space the marks become visible.此处隐藏是指在 rgb 空间中不易看到的水印,但当您转换为 hsv 或其他一些空间时,标记变得可见。

Here's one example:这是一个例子:

BGR SPACE: BGR 空间:

在此处输入图像描述

HSV SPACE: HSV空间:

在此处输入图像描述

I've tried different ways but was able to implement a solution that would remove those watermarks from the image.我尝试了不同的方法,但能够实现从图像中删除这些水印的解决方案。 I am posting this question here to get different ideas to tackle this problem.我在这里发布这个问题以获得不同的想法来解决这个问题。

What I have tried:我试过的:

I have tried various approaches but none of them worked, sharing the code might not help.我尝试了各种方法,但都没有奏效,共享代码可能无济于事。 It is not necessary to provide code for it, a pseudo code, idea or any lead would be appreciated.没有必要为其提供代码,将不胜感激伪代码、想法或任何线索。

  1. I noticed that the hidden marks are all the colors similar to RGB(90,94,105).我注意到隐藏的标记都是类似于 RGB(90,94,105) 的 colors。 And when I showed R, G, and B separately I noticed that the watermarks were only visible in B channel.当我分别展示 R、G 和 B 时,我注意到水印仅在 B 通道中可见。 I thought that if adjust/remove the marks in B channel and merge the image again, may be I could get better results.我认为如果调整/删除 B 通道中的标记并再次合并图像,可能会得到更好的结果。

Code :代码

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

Problems : This doesn't does solve the problem, it did make the colors little dimmer but the image colors were also disturbed.问题:这并不能解决问题,它确实使 colors 变暗,但图像 colors 也受到干扰。

  1. I tried playing around with B channel to see if could accomplish something.我试着玩 B 频道,看看能不能完成一些事情。

  2. I also noticed that if we convert the image to LUV space then the marks are visible in V space.我还注意到,如果我们将图像转换为 LUV 空间,那么标记在 V 空间中是可见的。

This might be a possible approach.这可能是一种可能的方法。 The underlying idea is that there are edges visible in the HSV channel that are not present in the original image.基本思想是在 HSV 通道中存在可见的边缘,这些边缘在原始图像中不存在。 Here are the H, S and V channels side-by-side:以下是并排的 H、S 和 V 通道:

在此处输入图像描述

So if we find the edges in the original image and the edges in the HSV image and difference them, the watermarking should show up.因此,如果我们找到原始图像中的边缘和 HSV 图像中的边缘并区分它们,水印应该会出现。 That can then be used as a mask to do in-painting in the original image with OpenCV inpaint .然后可以将其用作掩码,使用OpenCV inpaint在原始图像中进行修复。

I am just using ImageMagick here in Terminal, but it could all be done equally with OpenCV , PIL or scikit-image :我只是在终端中使用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

在此处输入图像描述

The idea is that the watermarking is now identified in black, so use the black areas (maybe morphologically closed) as a mask in OpenCV to inpaint - see link above.这个想法是水印现在被识别为黑色,所以使用黑色区域(可能在形态上是封闭的)作为OpenCV中的掩码来修复 - 参见上面的链接。

I didn't find any answer that completely solved the question.我没有找到任何完全解决问题的答案。 I appreciate everyone's effort though (Thank you).不过,我感谢大家的努力(谢谢)。 I did something on my own and would like to share.我自己做了一些事情,并想分享。 It results in little quality loss (a little bluish blurriness) but successfully removes the watermarks.它几乎没有质量损失(有点蓝色模糊),但成功地去除了水印。 The solution is very simple but took time to analyze the image.解决方案非常简单,但需要时间来分析图像。

I WOULD BE VERY GLAD IF SOMEONE CAN EXTEND THIS APPROACH AND COME UP WITH SOMETHING EVEN BETTER如果有人可以扩展这种方法并提出更好的方法,我会非常高兴

I observed that the watermarks were only visible in B space (out of RGB) and there were no traces of watermarks in R and G space.我观察到水印仅在 B 空间可见(RGB 之外),在 R 和 G 空间中没有水印的痕迹。

B space: B空间:

在此处输入图像描述

I also red somewhere that blue light contributes little to the overall image compared to R and G channel so here's what I decided to do.我还在某处发红,与 R 和 G 通道相比,蓝光对整体图像的贡献很小,所以这就是我决定做的事情。

Blur the B channel by a large enough amount to remove traces of those patterns.充分模糊 B 通道以去除这些图案的痕迹。 Here's how the B channel would appear afterwards:以下是 B 通道之后的显示方式:

在此处输入图像描述

Finally, merge the image with the new B channel, previous R and previous G channel.最后,将图像与新的 B 通道、之前的 R 和之前的 G 通道合并。 Here's how the RGB channel would appear afterwards:以下是 RGB 通道之后的显示方式:

在此处输入图像描述

The advantage of using approach is that the traces are gone.使用方法的优点是痕迹消失了。

The only disadvantage is that the bluish and purplish colors appear at the black edges and the image is a little bluish in general.唯一的缺点是蓝色和紫色的colors出现在黑边,图像总体上有点偏蓝。

My Code:我的代码:

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')

Here is a slight variation and extension of your processing in Python/OpenCV.这是您在 Python/OpenCV 中处理的轻微变化和扩展。

The main difference is that I use the median rather than a blurring and that I try to extract the black lines and impose them on the median before recombining.主要区别在于我使用中位数而不是模糊,并且我尝试提取黑线并将它们强加在中位数上,然后再重新组合。

Input:输入:

在此处输入图像描述

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)

Blue channel median: 蓝色通道中位数:

在此处输入图像描述

Blue channel threshold (for black lines):蓝色通道阈值(用于黑线):

在此处输入图像描述

New blue channel:新的蓝色通道:

在此处输入图像描述

Result:结果:

在此处输入图像描述


Many of the erroneous blue lines are now black, but not all.许多错误的蓝线现在是黑色的,但不是全部。 Increasing the threshold would have gotten more black lines, but then the hidden marks would have appeared again in part.增加阈值会得到更多的黑线,但隐藏的标记会再次出现部分。

Another trivial solution in Python/OpenCV is simply to replace the green channel for the blue channel, since most of the green channel is about the same intensity distribution as that of the blue channel. Python/OpenCV 中另一个简单的解决方案是简单地将绿色通道替换为蓝色通道,因为大多数绿色通道的强度分布与蓝色通道的强度分布大致相同。

Input:输入:

在此处输入图像描述

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)

Result: 结果:

在此处输入图像描述

The issue is that the coat and the green tree are slightly different color and texture.问题是外套和绿树的颜色和质地略有不同。

One might try modifying a copy of the green channel image to have the mean and standard-deviation as the blue channel to fix the coat issue.可以尝试修改绿色通道图像的副本,以将平均值和标准差作为蓝色通道来解决涂层问题。 For the green tree, it is outside the region of the watermark, so one could mask that using inRange for the green tree color and then replace the blue channel image's tree in the copy of the green channel.对于绿色树,它位于水印区域之外,因此可以使用 inRange 来掩盖绿色树的颜色,然后在绿色通道的副本中替换蓝色通道图像的树。 Then recombine the modified green channel in place of the blue channel.然后重新组合修改后的绿色通道代替蓝色通道。

If you have managed to isolate the watermarks in any channel, you should be able to threshold it and create a binary mask.如果您设法隔离了任何通道中的水印,您应该能够对其进行阈值化并创建二进制掩码。 Then you could use inpainting to fill the gaps with something like:然后你可以使用修复来填补空白,例如:

    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