Як я можу відточити зображення у OpenCV?


122

Як я можу вирізати зображення за допомогою OpenCV ?

Існує багато способів згладжування або розмивання, але я не міг бачити різкості.

Відповіді:


160

Один загальний порядок викладений у статті Вікіпедії про нерізке маскування :

Ви використовуєте фільтр згладжування Гаусса і віднімаєте згладжений варіант від вихідного зображення (зваженим способом, щоб значення постійної області залишалися постійними).

Щоб отримати загострену версію frameв image: (обидва cv::Mat)

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

Параметри там є те, що потрібно підкоригувати для себе.

Існує також лаплакійська заточка, ви маєте щось знайти на Google.


1
Чи є спосіб відтворити результат Photoshop Unsharp Mask?
Рой

@Drazick Ви запитуєте, оскільки його неможливо повторити? Посилання на вікіпедію було наведено вище. digital_unsharp_masking щоб бути конкретним
tilaprimera

@tilaprimera, я запитую, тому що USM Photoshop відрізняється від "Classic" USM.
Рой

50

Ви можете спробувати просте ядро та функцію filter2D , наприклад в Python:

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

У Вікіпедії є хороший огляд ядер, ще кілька прикладів тут - https://en.wikipedia.org/wiki/Kernel_(image_processing)

При обробці зображення ядро, матриця згортки або маска - це невелика матриця. Застосовується для розмивання, різкості, тиснення, виявлення країв тощо. Це досягається шляхом згортання між ядром і зображенням.


14

Ви можете знайти зразок коду щодо різкості зображення за допомогою алгоритму "нерізка маска" в документації OpenCV .

Зміна значень sigma, threshold, amountдають різні результати.

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

Це прекрасно!
Roosevelt

12

Ви можете чітко зобразити за допомогою нерізкої маски . Ви можете знайти більше інформації про нерізке маскування тут . А ось реалізація Python за допомогою 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)

це здається досить зручною версією. Ви можете додати трохи більше інформації про параметри. розмір ядра та сигма можна шукати у opencv, але як щодо суми та порогу? Дякую!
вибір

2
@choise amount- це просто кількість різкості. Наприклад, amount2,0 дає чіткіше зображення порівняно зі значенням за замовчуванням 1,0. threshold- поріг для низькоконтрастної маски. Іншими словами, пікселі, для яких різниця між вхідними та розмитими зображеннями менше threshold, залишаться незмінними.
Soroush

10

Будь-яке зображення - це сукупність сигналів різної частоти. Більш високі частоти керують ребрами, а нижчі - керують вмістом зображення. Краї утворюються при різкому переході від одного значення пікселя до іншого значення пікселя, такого як 0 і 255, у сусідній комірці. Очевидно, є різка зміна, а отже, крайка і висока частота. Для різкості зображення ці переходи можна додатково покращити.

Один із способів - це об'єднати власне виготовлене ядро ​​фільтра із зображенням.

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

Існує ще один метод віднімання розмитої версії зображення від яскравої його версії. Це допомагає відточувати зображення. Але робити це слід обережно, оскільки ми лише збільшуємо значення пікселів. Уявіть значення пікселя в градаціях сірого 190, яке, якщо помножити на вагу 2, становить 380, але обрізане на 255 завдяки максимально допустимому діапазону пікселів. Це втрата інформації та призводить до вимитого зображення.

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

5

Для наочності в цій темі слід зробити кілька моментів:

  1. Точність зображень - це неправомірна проблема. Іншими словами, розмивання - це втратна операція, і повернутися назад від неї взагалі неможливо.

  2. Щоб відточувати окремі зображення, потрібно якось додати обмеження (припущення) щодо того, який саме образ ви хочете, і як він розмився. Це область статистики природних зображень. Підходи до різкості чітко або неявно містять цю статистику в своїх алгоритмах (глибоке навчання - це найбільш неявно закодовані). Загальний підхід до збільшення зважування деяких рівнів розпаду піраміди DOG або Лаплакійської піраміди , що є узагальненням відповіді Брайана Бернса, передбачає, що розмиття Гаусса пошкодило зображення, а те, як робиться зважування, пов'язане з припущеннями щодо того, що було в зображенні для початку.

  3. Інші джерела інформації можуть вирішити проблему загострення проблеми. Поширеними такими джерелами інформації є відео рухомого об’єкта або налаштування з кількома переглядами. Загострення в цій обстановці зазвичай називають суперроздільною здатністю (це дуже погана назва, але вона застрягла в академічних колах). Там були методи супер-дозволом в OpenCV , оскільки довгий час .... хоча вони зазвичай не працюють , що добре для реальних проблем останній я перевірив їх. Я думаю, що глибоке навчання також дало чудові результати. Можливо, хтось опублікує зауваження щодо того, що варто там.


3

Для різкості зображення ми можемо використовувати фільтр (як у багатьох попередніх відповідях)

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

kernel /= denominator * kernel

Це буде найбільше, коли знаменник дорівнює 1 і зменшиться зі збільшенням (2,3 ..)

Найбільш використовуваний, коли знаменник дорівнює 3.

Нижче наведено реалізацію.

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

-4

Спробуйте з цим:

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

Ви можете знайти більше інформації тут .


9
Питання в тому, що стосується різкості зображення, а не згладжування країв.
Михайло Бурдінов
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.