OpenCV реализует карикатуру изображения, шедевр анимации своими руками

искусственный интеллект компьютерное зрение
OpenCV реализует карикатуру изображения, шедевр анимации своими руками

«Это 25-й день моего участия в ноябрьском испытании обновлений. Ознакомьтесь с подробностями события:Вызов последнего обновления 2021 г."

предисловие

существуетOpenCV, может быть примененоcv2.bilateralFilter()для уменьшения шума при сохранении острых краев. Однако этот фильтр создает эффект лестницы и ложные края отфильтрованного изображения. Хотя этот дефект можно уменьшить, улучшив двустороннюю фильтрацию, этот эффект можно использовать для создания крутых мультяшных изображений. В этой статье мы рассмотрим, какOpenCVДавайте мультяшно изобразим.

карикатура изображения

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

Постройте эскиз изображения, используяsketch_image()функция, сначала преобразуйте цветное изображение в изображение в градациях серого, а затем передайтеcv2.medianBlur()Медианный фильтр сглаживает изображение, чтобы уменьшить шум:

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_gray = cv2.medianBlur(img_gray, 5)

Далее используем оператор Лапласаcv2.Laplacian()В качестве детектора границ:

edges = cv2.Laplacian(img_gray, cv2.CV_8U, ksize=5)

Затем используйте края изображения, чтобы создать набросок изображения, применяяcv2.threshold()Пороговое значение результирующего изображения (методы порогового значения будут представлены позже, здесь нам просто нужно знать, что эта функция дает нам бинарное изображение из заданного изображения в градациях серого, какsketch_image()вывод функции). Различные пороговые значения могут использоваться для управления количеством черных пикселей (т.е. обнаруженных краев), которые появляются в результирующем изображении, если порог мал (например, 10), появится много черных пикселей, в противном случае, если значение велико (например, 200)) , то вы получите очень мало черных пикселей, вы можете использовать это значение для получения удовлетворительного результата:

ret, threshold = cv2.threshold(edges, 145, 255, cv2.THRESH_BINARY_INV)

Далее мы можем написатьcartonize_image()Функция для реализации функции мультипликации изображения.

Чтобы получить мультяшный эффект, сначала вызовите большее значение.cv2.bilateralFilter()функции, такие как:

cv2.bilateralFilter(img, 10, 250, 250) 

Второй и последний шаг, используяcv2.bitwise_and()Функция (побитовая операция) объединяет изображение эскиза и вывод двусторонней фильтрации с изображением эскиза в качестве маски для обеспечения вывода этих значений. При желании вывод также можно преобразовать в изображение в градациях серого:

cartoonized = cv2.bitwise_and(filtered, filtered, mask=threshold)

if gray_mode:
    return cv2.cvtColor(cartoonized, cv2.COLOR_BGR2GRAY)

В дополнение к вышеперечисленным пользовательским функциям для мультипликации изображения,OpenCVАналогичные функции также предоставляются встроенными, и для достижения той же функциональности можно использовать следующие фильтры:

  1. cv2.pencilSketch(): Этот фильтр создает рисунки линий карандашного наброска (аналогично пользовательскому рисунку).sketch_image()функция)
  2. cv2.stylization(): этот фильтр можно использовать для создания различных нефотореалистичных эффектов, которые можно применятьcv2.stylization()Получите мультяшный эффект (похожий на пользовательскийcartonize_image()функция)

Результат выполнения кода показан на следующем рисунке:

卡通化效果

полный код

Полный код выглядит так:

import cv2
import matplotlib.pyplot as plt

def show_with_matplotlib(color_img, title, pos):
    img_RGB = color_img[:, :, ::-1]

    ax = plt.subplot(2, 4, pos)
    plt.imshow(img_RGB)
    plt.title(title, fontsize=10)
    plt.axis('off')

def sketch_image(img):
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img_gray = cv2.medianBlur(img_gray, 5)
    edges = cv2.Laplacian(img_gray, cv2.CV_8U, ksize=5)
    ret, threshold = cv2.threshold(edges, 145, 255, cv2.THRESH_BINARY_INV)
    return threshold

# 自定义函数实现卡通化
def cartonize_image(img, gray_mode=False):
    # 提取图像的中的边
    threshold = sketch_image(img)
    # 双边滤波
    filtered = cv2.bilateralFilter(img, 10, 250, 250)
    # 卡通化
    cartoonized = cv2.bitwise_and(filtered, filtered, mask=threshold)

    if gray_mode:
        return cv2.cvtColor(cartoonized, cv2.COLOR_BGR2GRAY)
    return cartoonized

plt.figure(figsize=(14, 6))
plt.suptitle("Cartoonizing images", fontsize=14, fontweight='bold')

image = cv2.imread('sigonghuiye.jpeg')

custom_sketch_image = sketch_image(image)
custom_cartonized_image = cartonize_image(image)
custom_cartonized_image_gray = cartonize_image(image, True)

# 使用OpenCV函数实现卡通化
sketch_gray, sketch_color = cv2.pencilSketch(image, sigma_s=20, sigma_r=0.1, shade_factor=0.1)
stylizated_image = cv2.stylization(image, sigma_s=60, sigma_r=0.07)

show_with_matplotlib(image, "image", 1)
show_with_matplotlib(cv2.cvtColor(custom_sketch_image, cv2.COLOR_GRAY2BGR), 'custom sketch', 2)
show_with_matplotlib(cv2.cvtColor(sketch_gray, cv2.COLOR_GRAY2BGR), 'sketch gray cv2.pencilSketch()', 3)
show_with_matplotlib(sketch_color, 'sketch color cv2.pencilSketch()', 4)
show_with_matplotlib(stylizated_image, 'cartoonized cv2.stylization()', 5)
show_with_matplotlib(custom_cartonized_image, 'custom cartoonized', 6)
show_with_matplotlib(cv2.cvtColor(custom_cartonized_image_gray, cv2.COLOR_GRAY2BGR), 'custom cartoonized gray', 7)

plt.show()

Больше мультяшных эффектов

Мы можем добиться удовлетворительной карикатуры, изменив исходное изображение или параметры функции:

卡通化效果

卡通化效果

Давайте начнем.