¿Cómo puedo enfocar una imagen en OpenCV?

122

¿Cómo puedo enfocar una imagen usando OpenCV ?

Hay muchas formas de suavizar o difuminar, pero no pude ver ninguna de nitidez.

AruniRC
fuente

Respuestas:

160

En el artículo de Wikipedia sobre el enmascaramiento de enfoque se describe un procedimiento general :

Utiliza un filtro de suavizado gaussiano y resta la versión suavizada de la imagen original (de forma ponderada para que los valores de un área constante permanezcan constantes).

Para obtener una versión mejorada de frameen image: (ambos cv::Mat)

cv::GaussianBlur(frame, image, cv::Size(0, 0), 3);
cv::addWeighted(frame, 1.5, image, -0.5, 0, image);

Los parámetros hay algo que debe ajustar usted mismo.

También está el afilado laplaciano, deberías encontrar algo en eso cuando busques en Google.

etarion
fuente
1
¿Hay alguna forma de replicar el resultado de Photoshop de Unsharp Mask?
Royi
@Drazick ¿Lo preguntas porque no se puede replicar? enlace a la wikipedia se ha dado anteriormente. digital_unsharp_masking para ser específico
tilaprimera
@tilaprimera, pregunto porque el USM de Photoshop es diferente del USM "clásico".
Royi
50

Puede probar un núcleo simple y la función filter2D , por ejemplo, en Python:

kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
im = cv2.filter2D(im, -1, kernel)

Wikipedia tiene una buena descripción general de los núcleos con algunos ejemplos más aquí: https://en.wikipedia.org/wiki/Kernel_(image_processing)

En el procesamiento de imágenes, un núcleo, matriz de convolución o máscara es una matriz pequeña. Se utiliza para desenfocar, afilar, grabar en relieve, detectar bordes y más. Esto se logra haciendo una convolución entre un núcleo y una imagen.

Brian Burns
fuente
14

Puede encontrar un código de muestra sobre cómo enfocar la imagen usando el algoritmo de "máscara de enfoque" en Documentación de OpenCV .

Cambiar los valores de sigma, threshold, amountdará resultados diferentes.

// sharpen image using "unsharp mask" algorithm
Mat blurred; double sigma = 1, threshold = 5, amount = 1;
GaussianBlur(img, blurred, Size(), sigma, sigma);
Mat lowContrastMask = abs(img - blurred) < threshold;
Mat sharpened = img*(1+amount) + blurred*(-amount);
img.copyTo(sharpened, lowContrastMask);
sturkmen
fuente
¡Esto es hermoso!
roosevelt
12

Puede enfocar una imagen usando una máscara de enfoque . Puede encontrar más información sobre el enmascaramiento de enfoque aquí . Y aquí hay una implementación de Python usando OpenCV:

import cv2 as cv
import numpy as np

def unsharp_mask(image, kernel_size=(5, 5), sigma=1.0, amount=1.0, threshold=0):
    """Return a sharpened version of the image, using an unsharp mask."""
    blurred = cv.GaussianBlur(image, kernel_size, sigma)
    sharpened = float(amount + 1) * image - float(amount) * blurred
    sharpened = np.maximum(sharpened, np.zeros(sharpened.shape))
    sharpened = np.minimum(sharpened, 255 * np.ones(sharpened.shape))
    sharpened = sharpened.round().astype(np.uint8)
    if threshold > 0:
        low_contrast_mask = np.absolute(image - blurred) < threshold
        np.copyto(sharpened, image, where=low_contrast_mask)
    return sharpened

def example():
    image = cv.imread('my-image.jpg')
    sharpened_image = unsharp_mask(image)
    cv.imwrite('my-sharpened-image.jpg', sharpened_image)
Soroush
fuente
esta parece ser una versión bastante útil. ¿Podría agregar un poco más de información sobre los parámetros? el tamaño del kernel y sigma se pueden buscar en opencv, pero ¿qué pasa con la cantidad y el umbral? ¡Gracias!
elegir
2
@choise amountes simplemente la cantidad de afilado. Por ejemplo, un amount2,0 da una imagen más nítida en comparación con el valor predeterminado de 1,0. thresholdes el umbral de la máscara de bajo contraste. En otras palabras, los píxeles para los que la diferencia entre la entrada y las imágenes borrosas es menor thresholdpermanecerán sin cambios.
Soroush
10

Cualquier imagen es una colección de señales de varias frecuencias. Las frecuencias más altas controlan los bordes y las frecuencias más bajas controlan el contenido de la imagen. Los bordes se forman cuando hay una transición brusca de un valor de píxel al otro valor de píxel como 0 y 255 en la celda adyacente. Evidentemente hay un cambio brusco y por tanto el borde y la alta frecuencia. Para mejorar la nitidez de una imagen, estas transiciones se pueden mejorar aún más.

Una forma es convertir un núcleo de filtro hecho a sí mismo con la imagen.

    import cv2
    import numpy as np

    image = cv2.imread('images/input.jpg')
    kernel = np.array([[-1,-1,-1], 
                       [-1, 9,-1],
                       [-1,-1,-1]])
    sharpened = cv2.filter2D(image, -1, kernel) # applying the sharpening kernel to the input image & displaying it.
    cv2.imshow('Image Sharpening', sharpened)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

Existe otro método para restar una versión borrosa de la imagen de una versión brillante. Esto ayuda a mejorar la nitidez de la imagen. Pero debe hacerse con precaución ya que solo estamos aumentando los valores de píxeles. Imagine un valor de píxel en escala de grises 190, que si se multiplica por un peso de 2 da 380, pero se recorta en 255 debido al rango máximo de píxeles permitido. Esto es una pérdida de información y conduce a una imagen borrosa.

    addWeighted(frame, 1.5, image, -0.5, 0, image);
Ujjwal Saxena
fuente
5

Para mayor claridad en este tema, se deben hacer algunos puntos:

  1. La nitidez de las imágenes es un problema poco planteado. En otras palabras, el desenfoque es una operación con pérdidas y, en general, no es posible volver atrás.

  2. Para enfocar imágenes individuales, de alguna manera necesita agregar restricciones (suposiciones) sobre el tipo de imagen que desea y cómo se ha vuelto borrosa. Ésta es el área de las estadísticas de imágenes naturales. Los enfoques para realizar la agudización mantienen estas estadísticas de forma explícita o implícita en sus algoritmos (el aprendizaje profundo es el más codificado implícitamente). El enfoque común de aumentar la ponderación de algunos de los niveles de una descomposición de la pirámide DOG o laplaciana , que es la generalización de la respuesta de Brian Burns, asume que un desenfoque gaussiano corrompió la imagen, y cómo se realiza la ponderación está relacionada con las suposiciones sobre lo que fue en la imagen para empezar.

  3. Otras fuentes de información pueden hacer que el problema se agudice bien. Las fuentes de información más comunes son el video de un objeto en movimiento o el entorno de múltiples vistas. El afilado en ese entorno generalmente se llama superresolución (que es un muy mal nombre para él, pero se ha quedado en los círculos académicos). Ha habido métodos de superresolución en OpenCV desde hace mucho tiempo ... aunque generalmente no funcionan tan bien para problemas reales la última vez que los revisé. Espero que el aprendizaje profundo también haya producido algunos resultados maravillosos aquí. Tal vez alguien publique comentarios sobre lo que vale la pena.

Stefan Karlsson
fuente
3

Para enfocar una imagen podemos usar el filtro (como en muchas respuestas anteriores)

kernel = np.array([[-1, -1, -1],[-1, 8, -1],[-1, -1, 0]], np.float32) 

kernel /= denominator * kernel

Será el máximo cuando el denominador sea 1 y disminuirá a medida que aumenta (2,3 ..)

El más utilizado es cuando el denominador es 3.

A continuación se muestra la implementación.

kernel = np.array([[-1, -1, -1],[-1, 8, -1],[-1, -1, 0]], np.float32) 

kernel = 1/3 * kernel

dst = cv2.filter2D(image, -1, kernel)
kaustubhd9
fuente
Algo parece faltar cerca de "Lo hará más" .
Peter Mortensen
¡Sí Peter, gracias!
kaustubhd9
-4

Prueba con esto:

cv::bilateralFilter(img, 9, 75, 75);

Puede encontrar más información aquí .

mch
fuente
9
La pregunta es acerca de la nitidez de la imagen, no el suavizado de conservación de bordes.
Michael Burdinov