Bagaimana cara mempertajam gambar di OpenCV?

122

Bagaimana cara mempertajam gambar menggunakan OpenCV ?

Ada banyak cara untuk menghaluskan atau mengaburkan tapi tidak ada yang bisa saya lihat untuk mengasah.

AruniRC
sumber

Jawaban:

160

Salah satu prosedur umum dijelaskan dalam artikel Wikipedia tentang unsharp masking :

Anda menggunakan filter penghalusan Gaussian dan mengurangi versi penghalusan dari gambar asli (dengan cara berbobot sehingga nilai area konstan tetap konstan).

Untuk mendapatkan versi yang dipertajam framemenjadi image: (keduanya cv::Mat)

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

Parameternya ada sesuatu yang perlu Anda sesuaikan sendiri.

Ada juga penajaman Laplacian, Anda harus menemukan sesuatu tentang itu ketika Anda google.

etarion
sumber
1
Apakah ada cara untuk mereplikasi hasil Photoshop dari Unsharp Mask?
Royi
@ Drazick Apakah Anda bertanya karena tidak dapat direplikasi? link ke wikipedia telah diberikan di atas. digital_unsharp_masking untuk lebih spesifik
tilaprimera
@tilaprimera, saya bertanya karena USM Photoshop berbeda dari USM "Klasik".
Royi
50

Anda dapat mencoba kernel sederhana dan fungsi filter2D , misalnya dengan Python:

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

Wikipedia memiliki ikhtisar kernel yang bagus dengan beberapa contoh lainnya di sini - https://en.wikipedia.org/wiki/Kernel_(image_processing)

Dalam pemrosesan gambar, kernel, matriks konvolusi, atau topeng adalah matriks kecil. Ini digunakan untuk mengaburkan, mempertajam, membuat timbul, deteksi tepi, dan banyak lagi. Ini dilakukan dengan melakukan konvolusi antara kernel dan image.

Brian Burns
sumber
14

Anda dapat menemukan contoh kode tentang penajaman gambar menggunakan algoritma "unsharp mask" di OpenCV Documentation .

Mengubah nilai-nilai sigma, threshold, amountakan memberikan hasil yang berbeda.

// 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
sumber
Ini indah!
roosevelt
12

Anda dapat mempertajam gambar menggunakan topeng unsharp . Anda dapat menemukan informasi lebih lanjut tentang unsharp masking di sini . Dan inilah implementasi Python menggunakan 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
sumber
sepertinya ini adalah versi yang sangat berguna. bisakah Anda menambahkan sedikit lebih banyak info tentang parameter. ukuran kernel dan sigma dapat dicari di opencv, tetapi bagaimana dengan jumlah dan ambang? Terima kasih!
pilih
2
@choise amounthanyalah jumlah penajaman. Misalnya, amountdari 2.0 memberikan gambar yang lebih tajam dibandingkan dengan nilai default 1.0. thresholdadalah ambang batas untuk masker kontras rendah. Dengan kata lain, piksel yang perbedaan antara gambar masukan dan buram lebih kecil dari thresholdakan tetap tidak berubah.
Soroush
10

Gambar Apapun adalah kumpulan sinyal dari berbagai frekuensi. Frekuensi yang lebih tinggi mengontrol tepi dan frekuensi yang lebih rendah mengontrol konten gambar. Tepi terbentuk ketika ada transisi tajam dari satu nilai piksel ke nilai piksel lainnya seperti 0 dan 255 di sel yang berdekatan. Jelas ada perubahan tajam dan karenanya tepi dan frekuensi tinggi. Untuk mempertajam gambar, transisi ini dapat ditingkatkan lebih jauh.

Salah satu caranya adalah dengan menggabungkan kernel filter yang dibuat sendiri dengan 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()

Ada metode lain untuk mengurangi versi gambar buram dari versi cerahnya. Ini membantu mempertajam gambar. Tetapi harus dilakukan dengan hati-hati karena kami hanya meningkatkan nilai piksel. Bayangkan nilai piksel skala abu-abu 190, yang jika dikalikan dengan bobot 2 menghasilkan jika 380, tetapi dipangkas menjadi 255 karena kisaran piksel maksimum yang diizinkan. Ini adalah kehilangan informasi dan menyebabkan gambar pudar.

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

Untuk kejelasan tentang topik ini, beberapa poin harus dibuat:

  1. Mempertajam gambar adalah masalah yang mungkin terjadi. Dengan kata lain, pemburaman adalah operasi yang merugikan, dan mundur dari itu secara umum tidak mungkin dilakukan.

  2. Untuk mempertajam gambar tunggal, Anda perlu menambahkan batasan (asumsi) tentang jenis gambar yang Anda inginkan, dan bagaimana gambar tersebut menjadi buram. Ini adalah bidang statistik gambar alami. Pendekatan untuk melakukan penajaman memegang statistik ini secara eksplisit atau implisit dalam algoritme mereka (pembelajaran dalam menjadi kode yang paling implisit). Pendekatan umum untuk menaikkan pembobotan beberapa tingkat dekomposisi DOG atau piramida Laplacian , yang merupakan generalisasi dari jawaban Brian Burns, mengasumsikan bahwa pengaburan Gaussian merusak gambar, dan bagaimana pembobotan dilakukan terhubung dengan asumsi tentang apa yang terjadi. pada gambar untuk memulai.

  3. Sumber informasi lain dapat membuat penajaman masalah menjadi tepat. Sumber informasi yang umum seperti itu adalah video dari objek bergerak, atau pengaturan multi-tampilan. Penajaman dalam pengaturan itu biasanya disebut resolusi-super (yang merupakan nama yang sangat buruk untuk itu, tetapi telah terjebak dalam lingkaran akademis). Ada metode resolusi super di OpenCV sejak lama .... meskipun mereka biasanya tidak bekerja dengan baik untuk masalah nyata terakhir saya memeriksanya. Saya berharap pembelajaran yang mendalam telah menghasilkan beberapa hasil yang luar biasa di sini juga. Mungkin seseorang akan memposting komentar tentang apa yang berharga di luar sana.

Stefan Karlsson
sumber
3

Untuk mempertajam gambar kita bisa menggunakan filter (seperti di banyak jawaban sebelumnya)

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

kernel /= denominator * kernel

Ini akan menjadi yang paling banyak jika penyebutnya adalah 1 dan akan berkurang seiring bertambahnya (2.3 ..)

Yang paling banyak digunakan adalah jika penyebutnya adalah 3.

Berikut implementasinya.

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
sumber
Sesuatu tampaknya hilang di dekat "Paling banyak" .
Peter Mortensen
Ya Peter, terima kasih!
kaustubhd9
-4

Coba dengan ini:

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

Anda dapat menemukan informasi lebih lanjut di sini .

mch
sumber
9
Pertanyaannya adalah tentang penajaman gambar, bukan penghalusan menjaga tepi.
Michael Burdinov