web-dev-qa-db-fra.com

Comment rendre une image plus nette dans OpenCV?

Comment rendre une image plus nette avec OpenCV? Il y a beaucoup de manières de lisser ou de flou mais aucune que j'ai pu voir d'aiguiser.

108
AruniRC

Une procédure générale est décrite dans l'article de Wikipédia sur le masquage flo : Vous utilisez un filtre de lissage gaussien et soustrayez la version lissée de l'image d'origine (de manière pondérée, de sorte que les valeurs d'une surface constante restent constantes) ).

Pour obtenir une version affinée de frame dans image: (both cv::Mat)

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

Les paramètres il y a quelque chose que vous devez ajuster vous-même.

Il y a aussi l'affûtage laplacien, vous devriez trouver quelque chose à ce sujet lorsque vous recherchez sur Google.

149
etarion

Vous pouvez essayer un noyau simple et le filter2D fonction, par exemple en Python:

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

Wikipedia a un bon aperçu des noyaux avec quelques exemples supplémentaires ici - https://en.wikipedia.org/wiki/Kernel_ (traitement_image)

En traitement d'image, un noyau, une matrice de convolution ou un masque est une petite matrice. Il est utilisé pour le flou, la netteté, le gaufrage, la détection des contours, etc. Ceci est accompli en faisant une convolution entre un noyau et une image.

32
Brian Burns

Vous pouvez trouver un exemple de code sur la netteté de l'image à l'aide de l'algorithme "masque flou" à l'adresse OpenCV Documentation .

Changer les valeurs de sigma, threshold, amount donnera des résultats différents.

// 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);
13
sturkmen

Toute image est une collection de signaux de différentes fréquences. Les hautes fréquences contrôlent les contours et les basses fréquences contrôlent le contenu de l'image. Les bords sont formés lorsqu’il y a une transition nette d’une valeur de pixel à une autre valeur de pixel telle que 0 et 255 dans une cellule adjacente. De toute évidence, il y a un changement brusque et par conséquent le bord et la haute fréquence Pour accentuer une image, ces transitions peuvent être encore améliorées.

Une solution consiste à convertir un noyau de filtre fabriqué avec l'image.

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()

Il existe une autre méthode pour soustraire une version floue de l’image de la version en clair. Cela aide à rendre l’image plus nette. Mais cela doit être fait avec prudence car nous augmentons simplement les valeurs de pixels. Imaginez une valeur de pixel en niveaux de gris 190, qui, si elle est multipliée par un poids de 2, donne 380, mais est réduite à 255 en raison de la plage de pixels maximale autorisée. Ceci est une perte d'information et conduit à une image délavée.

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

Vous pouvez rendre une image plus nette avec un masque flo . Vous pouvez trouver plus d’informations sur le masquage flou ici . Et voici une implémentation de Python utilisant 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)
3
Soroush

Pour clarifier ce sujet, quelques points méritent d’être soulignés:

  1. La netteté des images est un problème mal posé. En d'autres termes, le flou est une opération avec perte, et il est généralement impossible de revenir en arrière.

  2. Pour accentuer des images individuelles, vous devez en quelque sorte ajouter des contraintes (hypothèses) sur le type d'image souhaité et sur la manière dont elle est devenue floue. C'est le domaine des statistiques d'images naturelles. Les approches visant à affiner ces statistiques tiennent explicitement ou implicitement dans leurs algorithmes (l’apprentissage en profondeur étant celui qui est le plus implicitement codé). L'approche courante consistant à sur-pondérer certains des niveaux d'un décomposition de DOG ou de pyramide laplacienne , qui est la généralisation de la réponse de Brian Burns, suppose qu'un flou gaussien a corrompu l'image et comment la pondération est effectuée. est liée à des hypothèses sur ce qui était dans l'image pour commencer.

  3. D'autres sources d'informations peuvent rendre le problème plus aiguisé. De telles sources d’information communes sont la vidéo d’un objet en mouvement ou un paramètre à vues multiples. Netteté dans ce contexte est généralement appelée super-résolution (ce qui est un très mauvais nom, mais il est resté bloqué dans les cercles universitaires). Il y a eu méthodes de super-résolution dans OpenCV depuis longtemps .... bien qu'elles ne fonctionnent généralement pas très bien pour les vrais problèmes, je les ai vérifiées. Je m'attends à ce que l'apprentissage en profondeur ait produit de merveilleux résultats ici aussi. Peut-être que quelqu'un affichera des remarques sur ce qui en vaut la peine.

2
Stefan Karlsson

Pour accentuer une image, nous pouvons utiliser le filtre (comme dans beaucoup de réponses ci-dessus)

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

kernel/=denominator*kernel

it will the most when the denominator is 1 and will decrease as increased(2.3..)

the most used one is when the denominator is 3.

ci-dessous est la mise en œuvre.

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

noyau = 1/3 * noyau

dst = cv2.filter2D (image, -1, noyau)

0
Kaustubh Deokar