Как повысить резкость изображения в OpenCV?

122

Как повысить резкость изображения с помощью OpenCV ?

Есть много способов сглаживания или размытия, но я не видел ни одного повышения резкости.

AruniRC
источник

Ответы:

160

Одна общая процедура изложена в статье Википедии о нерезком маскировании :

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

Чтобы получить заостренную версию frameв image: (оба cv::Mat)

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

В параметрах есть кое-что, что нужно настроить под себя.

Также есть лапласовская резкость, вы должны найти что-нибудь об этом, когда будете гуглить.

etarion
источник
1
Есть ли способ воспроизвести результат Photoshop Unsharp Mask?
Royi
@Drazick Вы спрашиваете, потому что это невозможно воспроизвести? ссылка на википедию была дана выше. digital_unsharp_masking, а именно
tilaprimera
@tilaprimera, спрашиваю, потому что USM Photoshop отличается от USM "Classic".
Royi
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);
sturkmen
источник
Это прекрасно!
Рузвельт
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)
Soroush
источник
это кажется довольно удобной версией. не могли бы вы добавить немного больше информации о параметрах. Размер ядра и сигму можно посмотреть в opencv, но как насчет количества и порога? Спасибо!
выбор
2
@choise amount- это просто количество заточки. Например, значение amount2,0 дает более четкое изображение по сравнению со значением по умолчанию 1,0. threshold- порог для низкоконтрастной маски. Другими словами, пиксели, для которых разница между входным и размытым изображениями меньше чем threshold, останутся неизменными.
Соруш
11

Any Image - это набор сигналов разной частоты. Более высокие частоты контролируют края, а более низкие частоты контролируют содержание изображения. Края формируются, когда есть резкий переход от одного значения пикселя к другому значению пикселя, например 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
источник
Кажется, чего-то не хватает рядом с надписью «Будет больше всего» .
Питер Мортенсен,
Ага, Питер, спасибо!
kaustubhd9,
-4

Попробуйте с этим:

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

Вы можете найти больше информации здесь .

МЧ
источник
9
Речь идет о повышении резкости изображения, а не о сглаживании с сохранением краев.
Михаил Бурдинов 02