Saltar al contenido

Eliminar marca de agua de una imagen usando OpenCV

Nuestros desarrolladores estrellas agotaron sus provisiones de café, en su búsqueda noche y día por la respuesta, hasta que Virginia encontró el arreglo en GitHub y en este momento la compartimos con nosotros.

Solución:

No estoy seguro de si la siguiente solución es aceptable en su caso. Pero creo que funciona un poco mejor y no le importa la forma de la marca de agua.

  • Elimina los trazos usando el filtrado morfológico. Esto debería darle una imagen de fondo.
    antecedentes

  • Calcule la imagen de diferencia: diferencia = fondo – inicial, y el umbral: binario = umbral (diferencia)

binario1

  • Umbral de la imagen de fondo y extraer la región oscura cubierta por la marca de agua

oscuro

  • De la imagen inicial, extraiga los píxeles dentro de la región de la marca de agua y establezca el umbral de estos píxeles, luego péguelos en la imagen binaria anterior

binario2

Arriba hay una descripción aproximada. El siguiente código debería explicarlo mejor.

Mat im = [load the color image here];

Mat gr, bg, bw, dark;

cvtColor(im, gr, CV_BGR2GRAY);

// approximate the background
bg = gr.clone();
for (int r = 1; r < 5; r++)

    Mat kernel2 = getStructuringElement(MORPH_ELLIPSE, Size(2*r+1, 2*r+1));
    morphologyEx(bg, bg, CV_MOP_CLOSE, kernel2);
    morphologyEx(bg, bg, CV_MOP_OPEN, kernel2);


// difference = background - initial
Mat dif = bg - gr;
// threshold the difference image so we get dark letters
threshold(dif, bw, 0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);
// threshold the background image so we get dark region
threshold(bg, dark, 0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);

// extract pixels in the dark region
vector darkpix(countNonZero(dark));
int index = 0;
for (int r = 0; r < dark.rows; r++)

    for (int c = 0; c < dark.cols; c++)
    
        if (dark.at(r, c))
        
            darkpix[index++] = gr.at(r, c);
        
    

// threshold the dark region so we get the darker pixels inside it
threshold(darkpix, darkpix, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);

// paste the extracted darker pixels
index = 0;
for (int r = 0; r < dark.rows; r++)

    for (int c = 0; c < dark.cols; c++)
    
        if (dark.at(r, c))
        
            bw.at(r, c) = darkpix[index++];
        
    

Una versión Python de la respuesta de dhanushka

# Import the necessary packages
import cv2
import numpy as np


def back_rm(filename):
    # Load the image
    img = cv2.imread(filename)

    # Convert the image to grayscale
    gr = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # Make a copy of the grayscale image
    bg = gr.copy()

    # Apply morphological transformations
    for i in range(5):
        kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,
                                            (2 * i + 1, 2 * i + 1))
        bg = cv2.morphologyEx(bg, cv2.MORPH_CLOSE, kernel2)
        bg = cv2.morphologyEx(bg, cv2.MORPH_OPEN, kernel2)

    # Subtract the grayscale image from its processed copy
    dif = cv2.subtract(bg, gr)

    # Apply thresholding
    bw = cv2.threshold(dif, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
    dark = cv2.threshold(bg, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]

    # Extract pixels in the dark region
    darkpix = gr[np.where(dark > 0)]

    # Threshold the dark region to get the darker pixels inside it
    darkpix = cv2.threshold(darkpix, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]

    # Paste the extracted darker pixels in the watermark region
    bw[np.where(dark > 0)] = darkpix.T

    cv2.imwrite('final.jpg', bw)


back_rm('watermark.jpg')

Aquí esta el resultado final:
El tiempo de procesamiento es muy corto usando numpy

time python back_rm.py 

real    0m0.391s
user    0m0.518s
sys     0m0.185s

ingrese la descripción de la imagen aquí

Calificaciones y comentarios

No se te olvide difundir este ensayo si te ayudó.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *