В настоящее время я пытаюсь реализовать какой-то результат этой статьи , опубликованной Google, о том, как удалять водяные знаки с изображений. Я создал около 80 изображений со своим собственным водяным знаком (шрифт и линии пересечения над всем изображением), и я могу определять края с помощью фильтра Лапласа.
Моя проблема в том, что краев недостаточно, чтобы удалить водяной знак с изображения. Когда линии шире, чем 1 пиксель, края оставляют промежуток между ними. В документе говорится следующее:
В частности,
для данного изображения с водяным знаком мы получаем подробную карту краев (используя детектор краев Canny) и вычисляем его евклидово преобразование расстояния, которое затем сворачивается с краями водяного знака (отраженными по горизонтали и вертикали), чтобы получить расстояние Chamfer от каждого пикселя до ближайший край. Наконец, позиция водяного знака принимается за пиксель с минимальным расстоянием на карте.
Я могу получить преобразование расстояния с помощью следующего кода:
### Detect water mark edges
imgs = glob.glob("images/*.jpg")
mean = np.zeros((1200, 1600))
for i, filename in enumerate(imgs):
img = cv2.imread(filename,0)
mean += cv2.Laplacian(img,cv2.CV_64F,ksize=3)
mean /= len(imgs)
#### Edge map & distance transform
img = cv2.imread("images/1.jpg", 0)
can = cv2.Canny(img, 100, 200)
dist = cv2.distanceTransform(can, cv2.DIST_L2, 3)
Но как мне теперь сделать свертку? Каким должно быть мое ядро для этого? Линии моего водяного знака пересекают всю картинку, поэтому изображение края водяного знака имеет тот же размер, что и мое исходное изображение.
РЕДАКТИРОВАТЬ на основе @Cris Luengo ответа:
_, mean = cv2.threshold(mean, 64, 255, cv2.THRESH_BINARY)
meanFFT = np.fft.fft2(mean)
distFFT = np.fft.fft2(dist)
conj = np.conjugate(meanFFT)
res = distFFT * meanFFT
cv2.imwrite('watermark.png', np.fft.ifft(res).real)