Comment rendre une image plus nette dans OpenCV?

122

Comment rendre une image plus nette avec OpenCV ?

Il existe de nombreuses façons de lisser ou de flouter, mais aucune que je puisse voir de netteté.

AruniRC
la source

Réponses:

160

Une procédure générale est présentée dans l'article de Wikipédia sur le masquage flou :

Vous utilisez un filtre de lissage gaussien et soustrayez la version lissée de l'image d'origine (de manière pondérée afin que les valeurs d'une zone constante restent constantes).

Pour obtenir une version affinée de frameinto image: (les deux cv::Mat)

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

Les paramètres que vous devez ajuster vous-même.

Il y a aussi la netteté laplacienne, vous devriez trouver quelque chose là-dessus lorsque vous google.

étarion
la source
1
Existe-t-il un moyen de reproduire le résultat de Photoshop du masque flou?
Royi
@Drazick Demandez-vous parce qu'il ne peut pas être répliqué? lien vers le wikipedia a été donné ci-dessus. digital_unsharp_masking pour être précis
tilaprimera
@tilaprimera, je demande parce que l'USM de Photoshop est différent de l'USM "classique".
Royi
50

Vous pouvez essayer un noyau simple et la fonction filter2D , 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 autres exemples ici - https://en.wikipedia.org/wiki/Kernel_(image_processing)

Dans le 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 bords, etc. Ceci est accompli en faisant une convolution entre un noyau et une image.

Brian Burns
la source
14

Vous pouvez trouver un exemple de code sur la netteté de l'image à l'aide de l'algorithme «masque flou» dans la documentation OpenCV .

Modification des valeurs de sigma, threshold, amountdonnera 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);
sturkmen
la source
C'est beau!
roosevelt
12

Vous pouvez affiner une image à l'aide d'un masque flou . Vous pouvez trouver plus d'informations sur le masquage flou ici . Et voici une implémentation 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)
Soroush
la source
cela semble être une version assez pratique. pourriez-vous s'il vous plaît ajouter un peu plus d'informations sur les paramètres. la taille du noyau et le sigma peuvent être recherchés dans opencv, mais qu'en est-il du montant et du seuil? Merci!
choisissez le
2
@choise amountest simplement la quantité de netteté. Par exemple, une valeur amountde 2,0 donne une image plus nette que la valeur par défaut de 1,0. thresholdest le seuil du masque à faible contraste. En d'autres termes, les pixels pour lesquels la différence entre les images d'entrée et les images floues est inférieure à thresholdresteront inchangés.
Soroush le
10

Any Image est une collection de signaux de différentes fréquences. Les fréquences plus élevées contrôlent les bords et les fréquences inférieures contrôlent le contenu de l'image. Les bords sont formés lorsqu'il y a une transition nette d'une valeur de pixel à l'autre valeur de pixel comme 0 et 255 dans la cellule adjacente. De toute évidence, il y a un changement brusque et donc le bord et la haute fréquence. Pour affiner une image, ces transitions peuvent être encore améliorées.

Une façon est de convoluer un noyau de filtre auto-créé 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 d'une version lumineuse de celle-ci. Cela permet de rendre l'image plus nette. Mais cela doit être fait avec prudence car nous ne faisons qu'augmenter 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 rognée à 255 en raison de la plage de pixels maximale autorisée. Il s'agit d'une perte d'information et conduit à une image délavée.

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

Pour plus de clarté dans ce sujet, quelques points doivent vraiment ê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 n'est généralement pas possible de revenir en arrière.

  2. Pour affiner des images individuelles, vous devez en quelque sorte ajouter des contraintes (hypothèses) sur le type d'image que vous souhaitez et sur la façon dont elle est devenue floue. C'est le domaine des statistiques d'images naturelles. Les approches de l'affûtage conservent ces statistiques explicitement ou implicitement dans leurs algorithmes (l'apprentissage en profondeur étant les plus codés implicitement). L'approche courante consistant à augmenter la pondération de certains niveaux d'une décomposition de la pyramide DOG ou laplacienne , qui est la généralisation de la réponse de Brian Burns, suppose qu'un flou gaussien a corrompu l'image, et la façon dont la pondération est effectuée est liée aux hypothèses sur ce qui était dans l'image pour commencer.

  3. D'autres sources d'informations peuvent rendre le problème de netteté bien posé. Ces sources d'informations courantes sont la vidéo d'un objet en mouvement ou le réglage à vues multiples. La netteté dans ce contexte est généralement appelée super-résolution (ce qui est un très mauvais nom pour cela, mais elle est restée dans les cercles académiques). Il existe depuis longtemps des méthodes de super-résolution dans OpenCV ... bien qu'elles ne fonctionnent généralement pas très bien pour les problèmes réels, je les ai vérifiées. Je m'attends à ce que le deep learning ait également produit de merveilleux résultats ici. Peut-être que quelqu'un publiera des remarques sur ce qui en vaut la peine.

Stefan Karlsson
la source
3

Pour affiner une image, nous pouvons utiliser le filtre (comme dans de nombreuses réponses précédentes)

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

kernel /= denominator * kernel

Ce sera le plus lorsque le dénominateur est 1 et diminuera au fur et à mesure de l'augmentation (2,3 ..)

Le plus utilisé est lorsque le dénominateur est 3.

Voici la mise en œuvre.

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
la source
Quelque chose semble manquer à côté de "Ce sera le plus" .
Peter Mortensen le
Ouais Peter, merci!
kaustubhd9 le
-4

Essayez avec ceci:

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

Vous trouverez peut-être plus d'informations ici .

mch
la source
9
La question concerne la netteté de l'image et non le lissage préservant les bords.
Michael Burdinov