使用python变成实现了六种图像的特殊效果,为:
浮雕、底片、哈哈镜、油画、素描、泛黄
各程序的运行结果均用Lena图像来展示。
一.浮雕特效
大致过程:
使用opencv库的EMBOSS滤波,提取轮廓。
自编写的实现:使用EMBOSS滤波器对应的算子实现。
# 图像特效处理
# 浮雕处理
# 使用opencv函数与自编写函数作效果对比
from PIL import Image
from PIL import ImageFilter
import cv2
import argparse
import numpy as np
from scipy.signal import find_peaks
def image_filters_test():
im = cv2.imread("Lena.jpg")
# 预定义的图像增强滤波器
im_blur = im.filter(ImageFilter.BLUR) # 模糊滤波
im_contour = im.filter(ImageFilter.CONTOUR) # 轮廓滤波
im_emboss = im.filter(ImageFilter.EMBOSS) # 浮雕滤波
im_min = im.filter(ImageFilter.MinFilter(3)) # 最小值滤波器
im.show()
im_blur.show()
im_contour.show()
im_emboss.show()
im_min.show()
if __name__ == "__main__":
# image_filters_test()
# read in the image and convert to HSV to extract value channel
img = cv2.imread("Lena.jpg")
horiz = cv2.flip(img, 1) # pressing through the pattern flips the image horizontally
large = cv2.resize(horiz, (0, 0), fx=2, fy=2, interpolation=cv2.INTER_LANCZOS4)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)
blur = cv2.GaussianBlur(s, (3, 3), 0)
edge = cv2.Canny(blur, 0, 50) # perform edge detection with a low slope threshold to capture all edges
kernel = np.ones((3, 3), np.uint8)
mask = cv2.dilate(edge, kernel, iterations=1)
filt = cv2.bitwise_and(cv2.bitwise_not(mask), s) # filter the noisy edges out by masking off those regions
# get counts of times each value occurs in the filtered parts of the image
G = 3
N = 256 // G + 1
val_count = [0] * N
rows, cols = filt.shape
for i in range(rows):
for j in range(cols):
val_count[filt[i, j] // G] += 1
val_count[0] = 0
# detect peaks in the histogram, indicating discrete layers
val_log = np.array([0 if not vc else np.log(vc) for vc in val_count])
val_norm = [0] * N
k = 2 * G
for i in range(N): # use a windowed z-score to find prominent local maxima
lo = max(0, i - k)
hi = min(N, i + k)
window = val_log[lo:hi]
val_norm[i] = (val_log[i] - np.mean(window)) / np.std(window)
val_norm = np.array(val_norm)
colors, _ = find_peaks(val_norm, height=1, distance=15 // G)
# separate into layers by color and apply an edge gradient
# black -> clear to imitate shadows in regions of neg vertical slope
# white -> clear to imitate highlights in regions of pos vert slope
result = np.full_like(v, 128)
upper = np.zeros_like(v)
for i in range(len(colors) - 1, 0, -1):
lowc = np.array([0, G * colors[i] - 15, 0])
highc = np.array([255, G * colors[i]