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é.

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.


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.


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

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)

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

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.


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)

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 .


9
La question concerne la netteté de l'image et non le lissage préservant les bords.
Michael Burdinov
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.