Wie kann ich ein Bild in OpenCV schärfen?

122

Wie kann ich ein Bild mit OpenCV schärfen ?

Es gibt viele Möglichkeiten zum Glätten oder Verwischen, aber keine, die ich beim Schärfen sehen könnte.

AruniRC
quelle

Antworten:

160

Ein allgemeines Verfahren ist im Wikipedia-Artikel zur unscharfen Maskierung beschrieben :

Sie verwenden einen Gaußschen Glättungsfilter und subtrahieren die geglättete Version vom Originalbild (gewichtet, damit die Werte eines konstanten Bereichs konstant bleiben).

So erhalten Sie eine geschärfte Version von framein image: (beide cv::Mat)

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

Die Parameter dort müssen Sie selbst anpassen.

Es gibt auch Laplace-Schärfen, Sie sollten etwas darauf finden, wenn Sie googeln.

etarion
quelle
1
Gibt es eine Möglichkeit, das Photoshop-Ergebnis von Unsharp Mask zu replizieren?
Royi
@Drazick Fragen Sie, weil es nicht repliziert werden kann? Der Link zur Wikipedia wurde oben angegeben. digital_unsharp_masking um genau zu sein
Tilaprimera
@tilaprimera, ich frage, weil sich die USM von Photoshop von der USM "Classic" unterscheidet.
Royi
50

Sie können einen einfachen Kernel und die Funktion filter2D ausprobieren , z. B. in Python:

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

Wikipedia hat einen guten Überblick über Kernel mit einigen weiteren Beispielen hier - https://en.wikipedia.org/wiki/Kernel_(image_processing)

Bei der Bildverarbeitung ist ein Kernel, eine Faltungsmatrix oder eine Maske eine kleine Matrix. Es wird zum Verwischen, Schärfen, Prägen, Kantenerkennen und mehr verwendet. Dies wird erreicht, indem eine Faltung zwischen einem Kernel und einem Image durchgeführt wird.

Brian Burns
quelle
14

Einen Beispielcode zum Schärfen von Bildern mit dem Algorithmus "Unscharfe Maske" finden Sie in der OpenCV-Dokumentation .

Ändern von Werten von sigma, threshold, amountwerden unterschiedliche Ergebnisse.

// 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);
Störer
quelle
Das ist schön!
Roosevelt
12

Sie können ein Bild mit einer unscharfen Maske schärfen . Weitere Informationen zur unscharfen Maskierung finden Sie hier . Und hier ist eine Python-Implementierung mit 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
quelle
Dies scheint eine ziemlich praktische Version zu sein. Könnten Sie bitte ein bisschen mehr Informationen über die Parameter hinzufügen. Kernelgröße und Sigma können in opencv nachgeschlagen werden, aber was ist mit Menge und Schwelle? Vielen Dank!
Wählen Sie
2
@choise amountist einfach das Ausmaß des Schärfens. Beispielsweise amountergibt ein Wert von 2,0 ein schärferes Bild im Vergleich zum Standardwert von 1,0. thresholdist der Schwellenwert für die kontrastarme Maske. Mit anderen Worten, die Pixel, bei denen der Unterschied zwischen den eingegebenen und den unscharfen Bildern geringer ist als threshold, bleiben unverändert.
Soroush
10

Jedes Bild ist eine Sammlung von Signalen mit verschiedenen Frequenzen. Die höheren Frequenzen steuern die Kanten und die niedrigeren Frequenzen steuern den Bildinhalt. Kanten werden gebildet, wenn es einen scharfen Übergang von einem Pixelwert zu dem anderen Pixelwert wie 0 und 255 in der benachbarten Zelle gibt. Offensichtlich gibt es eine scharfe Änderung und damit die Kante und die Hochfrequenz. Zum Schärfen eines Bildes können diese Übergänge weiter verbessert werden.

Eine Möglichkeit besteht darin, einen selbst erstellten Filterkern mit dem Bild zu falten.

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

Es gibt eine andere Methode, um eine unscharfe Version des Bildes von der hellen Version zu subtrahieren. Dies hilft beim Schärfen des Bildes. Dies sollte jedoch mit Vorsicht erfolgen, da wir nur die Pixelwerte erhöhen. Stellen Sie sich einen Graustufenpixelwert 190 vor, der, wenn er mit einem Gewicht von 2 multipliziert wird, 380 ergibt, aber aufgrund des maximal zulässigen Pixelbereichs auf 255 gekürzt wird. Dies ist ein Informationsverlust und führt zu einem verwaschenen Bild.

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

Aus Gründen der Klarheit in diesem Thema sollten einige Punkte hervorgehoben werden:

  1. Das Schärfen von Bildern ist ein schlechtes Problem. Mit anderen Worten, Unschärfe ist eine verlustbehaftete Operation, und ein Zurückkehren ist im Allgemeinen nicht möglich.

  2. Um einzelne Bilder zu schärfen, müssen Sie Einschränkungen (Annahmen) hinzufügen, welche Art von Bild Sie möchten und wie es unscharf geworden ist. Dies ist der Bereich der natürlichen Bildstatistik. Ansätze zum Schärfen halten diese Statistiken explizit oder implizit in ihren Algorithmen (Deep Learning ist das implizit codierteste). Der übliche Ansatz, einige Ebenen einer DOG- oder Laplace-Pyramiden-Zerlegung hochzuwichten , der die Verallgemeinerung der Antwort von Brian Burns darstellt, geht davon aus, dass eine Gaußsche Unschärfe das Bild verfälscht und wie die Gewichtung erfolgt, hängt mit Annahmen darüber zusammen, was war im Bild zu Beginn.

  3. Andere Informationsquellen können das Problem beim Schärfen gut aufwerfen. Häufig sind solche Informationsquellen Videos eines sich bewegenden Objekts oder Einstellungen mit mehreren Ansichten. Das Schärfen in dieser Einstellung wird normalerweise als Superauflösung bezeichnet (was ein sehr schlechter Name dafür ist, aber in akademischen Kreisen stecken geblieben ist). Es hat in OpenCV Super-Resolution - Verfahren seit langer Zeit .... obwohl sie in der Regel arbeiten nicht so gut für reale Probleme dauern ich sie ausgecheckt. Ich gehe davon aus, dass Deep Learning auch hier einige wundervolle Ergebnisse hervorgebracht hat. Vielleicht schreibt jemand eine Bemerkung darüber, was sich da draußen lohnt.

Stefan Karlsson
quelle
3

Um ein Bild zu schärfen, können wir den Filter verwenden (wie in vielen vorherigen Antworten).

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

kernel /= denominator * kernel

Es wird am meisten sein, wenn der Nenner 1 ist und mit zunehmendem Wert abnimmt (2.3 ..)

Am häufigsten wird verwendet, wenn der Nenner 3 ist.

Unten ist die Implementierung.

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
quelle
In der Nähe von "Es wird am meisten" scheint etwas zu fehlen .
Peter Mortensen
Ja Peter, danke!
kaustubhd9
-4

Versuchen Sie es damit:

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

Weitere Informationen finden Sie hier .

mch
quelle
9
Die Frage betrifft das Schärfen von Bildern und nicht das Glätten von Kanten.
Michael Burdinov