簡體   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