Odpowiedzi:
Jedna ogólna procedura została opisana w artykule Wikipedii dotyczącym nieostrego maskowania :
Używasz filtru wygładzającego Gaussa i odejmujesz wygładzoną wersję od oryginalnego obrazu (w sposób ważony, aby wartości stałego obszaru pozostały stałe).
Aby uzyskać zaostrzoną wersję frame
w image
: (oba cv::Mat
)
cv::GaussianBlur(frame, image, cv::Size(0, 0), 3);
cv::addWeighted(frame, 1.5, image, -0.5, 0, image);
Parametry są coś, co musisz dostosować dla siebie.
Jest też ostrzenie Laplacian, powinieneś znaleźć coś na ten temat, gdy szukasz Google.
Możesz wypróbować proste jądro i funkcję filter2D , np. W Pythonie:
kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
im = cv2.filter2D(im, -1, kernel)
Wikipedia zawiera dobry przegląd jąder z kilkoma przykładami tutaj - https://en.wikipedia.org/wiki/Kernel_(image_processing)
W przetwarzaniu obrazu jądro, macierz splotu lub maska to mała macierz. Służy do rozmycia, wyostrzania, wytłaczania, wykrywania krawędzi i nie tylko. Osiąga się to poprzez zrobienie splotu między jądrem a obrazem.
Przykładowy kod dotyczący wyostrzania obrazu przy użyciu algorytmu „maski wyostrzającej” można znaleźć w dokumentacji OpenCV .
Zmiana wartości sigma
, threshold
, amount
dadzą różne wyniki.
// 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);
Obraz można wyostrzyć, używając maski wyostrzającej . Więcej informacji na temat nieostrego maskowania można znaleźć tutaj . A oto implementacja Pythona przy użyciu 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
to po prostu stopień wyostrzenia. Na przykład wartość amount
2,0 daje ostrzejszy obraz w porównaniu z domyślną wartością 1,0. threshold
jest progiem dla maski o niskim kontraście. Innymi słowy, piksele, dla których różnica między obrazem wejściowym a rozmazanymi obrazami jest mniejsza niż threshold
pozostaną niezmienione.
Dowolny obraz to zbiór sygnałów o różnych częstotliwościach. Wyższe częstotliwości kontrolują krawędzie, a niższe częstotliwości kontrolują zawartość obrazu. Krawędzie są tworzone, gdy występuje ostre przejście od wartości jednego piksela do wartości drugiego piksela, np. 0 i 255 w sąsiedniej komórce. Oczywiście następuje gwałtowna zmiana, a tym samym krawędź i wysoka częstotliwość. W celu wyostrzenia obrazu przejścia te można dodatkowo wzmocnić.
Jednym ze sposobów jest połączenie z obrazem samodzielnie utworzonego jądra filtru.
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()
Istnieje inna metoda odejmowania zamazanej wersji obrazu od jego jasnej wersji. Pomaga to wyostrzyć obraz. Należy jednak zachować ostrożność, ponieważ po prostu zwiększamy wartości pikseli. Wyobraź sobie wartość 190 pikseli w skali szarości, która pomnożona przez wagę 2 daje 380, ale jest zmniejszona do 255 ze względu na maksymalny dopuszczalny zakres pikseli. To utrata informacji i prowadzi do wyblaknięcia obrazu.
addWeighted(frame, 1.5, image, -0.5, 0, image);
Dla jasności w tym temacie należy zwrócić uwagę na kilka kwestii:
Wyostrzanie obrazów to źle postawiony problem. Innymi słowy, rozmycie jest operacją stratną, a powrót z niej na ogół nie jest możliwy.
Aby wyostrzyć pojedyncze obrazy, musisz w jakiś sposób dodać ograniczenia (założenia) dotyczące tego, jakiego rodzaju obrazu chcesz i jak się rozmyło. To jest obszar statystyki obrazu naturalnego. Podejścia do wyostrzania zawierają te statystyki jawnie lub niejawnie w swoich algorytmach (głębokie uczenie jest najbardziej niejawnie zakodowane). Powszechne podejście polegające na zwiększaniu wagi niektórych poziomów rozkładu piramidy Psa lub Laplaciana , które jest uogólnieniem odpowiedzi Briana Burnsa, zakłada, że rozmycie Gaussa zepsuło obraz, a sposób ważenia jest powiązany z założeniami dotyczącymi tego, co było na obrazku.
Inne źródła informacji mogą sprawić, że problem z ostrzeniem będzie słuszny. Typowymi źródłami informacji są wideo poruszającego się obiektu lub ustawienia wielu widoków. Wyostrzanie w tym ustawieniu jest zwykle nazywane super rozdzielczością (co jest bardzo złym określeniem, ale utknęło w kręgach akademickich). Nastąpił metody super-rozdzielczości w OpenCV od dawna .... choć zwykle nie pracuję, że dobrze na rzeczywiste problemy ostatnio sprawdziłem je. Spodziewam się, że głębokie uczenie się również przyniosło wspaniałe rezultaty. Może ktoś napisze w uwagach o tym, co jest warte zachodu.
Aby wyostrzyć obraz, możemy użyć filtra (jak w wielu poprzednich odpowiedziach)
kernel = np.array([[-1, -1, -1],[-1, 8, -1],[-1, -1, 0]], np.float32)
kernel /= denominator * kernel
Najwięcej będzie, gdy mianownik będzie wynosił 1 i będzie maleć wraz ze wzrostem (2,3 ...)
Najczęściej używany jest, gdy mianownik to 3.
Poniżej znajduje się realizacja.
kernel = np.array([[-1, -1, -1],[-1, 8, -1],[-1, -1, 0]], np.float32)
kernel = 1/3 * kernel
dst = cv2.filter2D(image, -1, kernel)