低通滤波去除噪声,高通滤波提取边缘。
直方图均衡化
直方图均衡化是通过调整图像的灰阶分布,使得在0~255灰阶上的分布更加均衡,提高了图像的对比度,达到改善图像主观视觉效果的目的。对比度较低的图像适合使用直方图均衡化方法来增强图像细节。
laplacian
使用中心为5的8邻域拉普拉斯算子与图像卷积可以达到锐化增强图像的目的,增强局部图像的对比度,拉普拉斯算子如下图所示:
log
对数变换可以将图像的低灰度值部分扩展,显示出低灰度部分更多的细节,将其高灰度值部分压缩,减少高灰度值部分的细节,从而达到强调图像低灰度部分的目的。
gamma
伽马变换主要用于图像的校正,将灰度过高或者灰度过低的图片进行修正,增强对比度。
图像的彩色信息在进行边缘检测时通常是多余的,因此可以在进行边缘检测前先把彩色图像转换成灰度图像。
Opencv提供5种插值方法有5种:最近邻、双线性、双立方、面积关联、兰佐斯。
最邻近插值,是指将目标图像中的点,对应到源图像中后,找到最相邻的整数点,作为插值后的输出。
双线性插值,使用周围4个点插值得到输出,是指在xy方法上,都是基于线性距离来插值的。
双立方插值,数f 在点 (x, y) 的值可以通过矩形网格中最近的十六个采样点的加权平均得到,在这里需要使用两个多项式插值三次函数,每个方向使用一个。
相关的应用场景:几何变换、透视变换、插值计算新像素
resize,如果size有值,使用size做放缩插值,否则根据fx与fy卷积
方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子。它通过计算和统计图像局部区域的梯度方向直方图来构成特征。它的基本思想是利用梯度信息能很好的反映图像目标的边缘信息并通过局部梯度的大小将图像局部的外观和形状特征化。
首先将图像分成小的连通区域,我们把它叫细胞单元。然后采集细胞单元中各像素点的梯度的或边缘的方向直方图。最后把这些直方图组合起来就可以构成特征描述器。
import cv2
##马赛克
def do_mosaic(frame, x, y, w, h, neighbor=9):
"""
马赛克的实现原理是把图像上某个像素点一定范围邻域内的所有点用邻域内左上像素点的颜色代替,这样可以模糊细节,但是可以保留大体的轮廓。
:param frame: opencv frame
:param int x : 马赛克左顶点
:param int y: 马赛克右顶点
:param int w: 马赛克宽
:param int h: 马赛克高
:param int neighbor: 马赛克每一块的宽
"""
fh, fw = frame.shape[0], frame.shape[1]
if (y + h > fh) or (x + w > fw):
return
for i in range(0, h - neighbor, neighbor): # 关键点0 减去neightbour 防止溢出
for j in range(0, w - neighbor, neighbor):
rect = [j + x, i + y, neighbor, neighbor]
color = frame[i + y][j + x].tolist() # 关键点1 tolist
left_up = (rect[0], rect[1])
right_down = (rect[0] + neighbor - 1, rect[1] + neighbor - 1) # 关键点2 减去一个像素
cv2.rectangle(frame, left_up, right_down, color, -1)
im = cv2.imread('test.jpg', 1)
do_mosaic(im, 219, 61, 460 - 219, 412 - 61)
while 1:
k = cv2.waitKey(10)
if k == 27:
break
cv2.imshow('mosaic', im)
算法流程:①对图像进行zero padding ②根据高斯滤波器的核大小和标准差大小实现高斯滤波器 ③使用高斯滤波器对图像进行滤波(相乘再相加)④输出高斯滤波后的图像
import cv2
import numpy as np
# Gaussian filter
def gaussian_filter(img, K_size=3, sigma=1.3):
if len(img.shape) == 3:
H, W, C = img.shape
else:
img = np.expand_dims(img, axis=-1)
H, W, C = img.shape
## Zero padding
pad = K_size // 2
out = np.zeros((H + pad * 2, W + pad * 2, C), dtype=np.float)
out[pad: pad + H, pad: pad + W] = img.copy().astype(np.float)
## prepare Kernel
K = np.zeros((K_size, K_size), dtype=np.float)
for x in range(-pad, -pad + K_size):
for y in range(-pad, -pad + K_size):
K[y + pad, x + pad] = np.exp( -(x ** 2 + y ** 2) / (2 * (sigma ** 2)))
K /= (2 * np.pi * sigma * sigma)
K /= K.sum()
tmp = out.copy()
# filtering
for y in range(H):
for x in range(W):
for c in range(C):
out[pad + y, pad + x, c] = np.sum(K * tmp[y: y + K_size, x: x + K_size, c])
out = np.clip(out, 0, 255)
out = out[pad: pad + H, pad: pad + W].astype(np.uint8)
return out
# Read image
img = cv2.imread("../paojie.jpg")
# Gaussian Filter
out = gaussian_filter(img, K_size=3, sigma=1.3)
# Save result
cv2.imwrite("out.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()
import numpy as np
def means_filter(input_image, filter_size):
'''
均值滤波器
:param input_image: 输入图像
:param filter_size: 滤波器大小
:return: 输出图像
注:此实现滤波器大小必须为奇数且 >= 3
'''
input_image_cp = np.copy(input_image) # 输入图像的副本
filter_template = np.ones((filter_size, filter_size)) # 空间滤波器模板
pad_num = int((filter_size - 1) / 2) # 输入图像需要填充的尺寸
input_image_cp = np.pad(input_image_cp, (pad_num, pad_num), mode="constant", constant_values=0) # 填充输入图像
m, n = input_image_cp.shape # 获取填充后的输入图像的大小
output_image = np.copy(input_image_cp) # 输出图像
# 空间滤波
for i in range(pad_num, m - pad_num):
for j in range(pad_num, n - pad_num):
output_image[i, j] = np.sum(filter_template * input_image_cp[i - pad_num:i + pad_num + 1, j - pad_num:j + pad_num + 1]) / (filter_size ** 2)
output_image = output_image[pad_num:m - pad_num, pad_num:n - pad_num] # 裁剪
return output_image
使用中值滤波对图像进行处理是选定一部分区域(一般3X3,5X5)像素灰度值求取其中值,用求得的中值代替区域内的像素灰度值,以此来达到平滑滤波的效果,因为我们要求中值,所以在选定区域范围是需要注意选择奇数大小范围进行中值计算。
# 中值滤波#
import cv2
import numpy as np
def MedianFilter(img,k=3,padding=None):
imarray=img
height = imarray.shape[0]
width = imarray.shape[1]
if not padding:
edge = int((k - 1) / 2)
if height - 1 - edge <= edge or width - 1 - edge <= edge:
print("The parameter k is to large.")
return None
new_arr = np.zeros((height, width), dtype="uint8")
for i in range(edge,height-edge):
for j in range(edge,width-edge):
new_arr[i, j] = np.median(imarray[i - edge:i + edge + 1, j - edge:j + edge + 1])# 调用np.median求取中值
return new_arr