OpenCV'de bir görüntüyü nasıl netleştirebilirim?


122

OpenCV kullanarak bir görüntüyü nasıl netleştirebilirim ?

Düzgünleştirmenin veya bulanıklaştırmanın birçok yolu var, ancak hiçbiri netleştirmeyi göremedim.

Yanıtlar:


160

Wikipedia makalesinde keskin olmayan maskeleme ile ilgili genel bir prosedür ortaya konmuştur :

Bir Gauss yumuşatma filtresi kullanırsınız ve düzleştirilmiş versiyonu orijinal görüntüden çıkarırsınız (ağırlıklı bir şekilde, böylece sabit bir alanın değerleri sabit kalır).

İçeriğin keskinleştirilmiş bir versiyonunu elde frameetmek için image: (her ikisi cv::Mat)

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

Buradaki parametreler, kendiniz için ayarlamanız gereken bir şey var.

Bir de Laplacian bileme var, google'da bir şeyler bulmalısın.


1
Photoshop'un Keskinliği Azaltma Maskesi sonucunu kopyalamanın bir yolu var mı?
Royi

@Drazick Kopyalanamadığı için mi soruyorsunuz? wikipedia bağlantısı yukarıda verilmiştir. digital_unsharp_masking özgü olmak
tilaprimera

@tilaprimera, soruyorum çünkü Photoshop'un USM'si "Klasik" USM'den farklı.
Royi

50

Basit bir çekirdek ve filter2D işlevini deneyebilirsiniz , örneğin Python'da:

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

Wikipedia burada birkaç örnekle birlikte çekirdeklere iyi bir genel bakış sunar - https://en.wikipedia.org/wiki/Kernel_(image_processing)

Görüntü işlemede çekirdek, evrişim matrisi veya maske küçük bir matristir. Bulanıklaştırma, keskinleştirme, kabartma, kenar algılama ve daha fazlası için kullanılır. Bu, bir çekirdek ve bir görüntü arasında bir evrişim yaparak gerçekleştirilir.


14

Yaklaşık bir örnek kod bulabilirsiniz "keskinlik giderme maskesi" algoritması kullanarak görüntüyü keskinleştirme de OpenCV Belgeler .

Değerleri değiştirme sigma, threshold, amountfarklı sonuçlar verecektir.

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

Bu güzel!
roosevelt

12

Keskin olmayan bir maske kullanarak bir görüntüyü keskinleştirebilirsiniz . Keskin olmayan maskeleme hakkında daha fazla bilgiyi burada bulabilirsiniz . Ve işte OpenCV kullanan bir Python uygulaması:

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)

bu oldukça kullanışlı bir versiyon gibi görünüyor. parametreler hakkında biraz daha bilgi ekleyebilir misiniz? çekirdek boyutu ve sigma açık olarak bakılabilir, peki ya miktar ve eşik? Teşekkürler!
seçimi

2
@choise amount, sadece netleştirme miktarıdır. Örneğin, amount2,0 varsayılan değer olan 1,0 ile karşılaştırıldığında daha net bir görüntü verir. thresholddüşük kontrastlı maske için eşiktir. Diğer bir deyişle, girdi ve bulanık görüntüler arasındaki farkın daha az olduğu pikseller thresholddeğişmeden kalacaktır.
Soroush

11

Herhangi Bir Görüntü, çeşitli frekanslardaki sinyallerin bir koleksiyonudur. Daha yüksek frekanslar kenarları kontrol eder ve daha düşük frekanslar görüntü içeriğini kontrol eder. Bitişik hücrede 0 ve 255 gibi bir piksel değerinden diğer piksel değerine keskin bir geçiş olduğunda kenarlar oluşur. Açıkçası keskin bir değişim ve dolayısıyla kenar ve yüksek frekans var. Bir görüntüyü keskinleştirmek için bu geçişler daha da geliştirilebilir.

Bunun bir yolu, kendi kendine yapılan bir filtre çekirdeğini görüntü ile birleştirmektir.

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

Görüntünün bulanık bir halini parlak halinden çıkarmanın başka bir yöntemi daha var. Bu, görüntünün keskinleştirilmesine yardımcı olur. Ancak, sadece piksel değerlerini artırdığımız için dikkatli yapılmalıdır. Gri tonlamalı bir piksel değeri 190 düşünün; bu, 2 ağırlığıyla çarpıldığında 380 yapar, ancak izin verilen maksimum piksel aralığı nedeniyle 255'te kırpılır. Bu bilgi kaybıdır ve silik görüntünün kaybolmasına neden olur.

    addWeighted(frame, 1.5, image, -0.5, 0, image);

5

Bu konuya açıklık getirmek için gerçekten birkaç noktaya değinmek gerekiyor:

  1. Görüntüleri keskinleştirmek kötü niyetli bir sorundur. Başka bir deyişle, bulanıklaştırma kayıplı bir işlemdir ve bundan geri dönmek genellikle mümkün değildir.

  2. Tekli görüntüleri keskinleştirmek için, ne tür bir görüntü istediğinize ve nasıl bulanıklaştığına bir şekilde kısıtlamalar (varsayımlar) eklemeniz gerekir. Bu, doğal görüntü istatistikleri alanıdır. Keskinleştirme yaklaşımları, bu istatistikleri açıkça veya örtük olarak kendi algoritmalarında tutar (derin öğrenme, en örtük olarak kodlanmış olanlardır). Brian Burns cevabının genelleştirmesi olan bir DOG veya Laplacian piramit ayrışmasının bazı seviyelerinin ağırlıklandırılmasına yönelik ortak yaklaşım, Gauss'un bulanıklaşmasının görüntüyü bozduğunu ve ağırlıklandırmanın nasıl yapıldığına dair varsayımlarla bağlantılı olduğunu varsayar. ile başlamak için resimde.

  3. Diğer bilgi kaynakları, sorunun netleşmesine neden olabilir. Bu tür yaygın bilgi kaynakları, hareketli bir nesnenin videosu veya çoklu görüntü ayarıdır. Bu ortamda keskinleştirme genellikle süper çözünürlük olarak adlandırılır (bu onun için çok kötü bir isimdir, ancak akademik çevrelerde sıkışmıştır). Olmuştur OpenCV süper çözünürlüklü yöntemleri gerçek sorunlar son kuyu için onları teslim olduğunu genellikle do not eser olmasına rağmen .... uzun zamandır. Derin öğrenmenin burada da harika sonuçlar vermesini bekliyorum. Belki birileri orada neyin değerli olduğuna dair açıklamalarda bulunur.


3

Bir görüntüyü keskinleştirmek için filtreyi kullanabiliriz (önceki birçok cevapta olduğu gibi)

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

kernel /= denominator * kernel

Payda 1 olduğunda en fazla olur ve arttıkça azalır (2.3 ..)

En çok kullanılan, payda 3 olduğunda.

Uygulama aşağıdadır.

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

kernel = 1/3 * kernel

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

"En çok olacak" yakınında bir şeyler eksik görünüyor .
Peter Mortensen

Evet Peter, teşekkürler!
kaustubhd9

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.