Respuestas:
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 frame
en 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.
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.
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
, amount
dará 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);
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)
amount
es simplemente la cantidad de afilado. Por ejemplo, un amount
2,0 da una imagen más nítida en comparación con el valor predeterminado de 1,0. threshold
es 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 threshold
permanecerán sin cambios.
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);
Para mayor claridad en este tema, se deben hacer algunos puntos:
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.
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.
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.
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)