16. Prewitt 滤波器
Previtt滤波器是一种一阶微分滤波器,它和Sobel滤波器的区别是,Sobel滤波器主轴方向上的系数是2和-2,而Prewitt滤波器所有的系数都是-1和1,不管是纵向(Y轴方向)还是横向(X轴方向)
纵向(Y轴方向):
还有一点区别是Sobel算子是前面的像素值减去后面的,而Prewitt滤波器是后面的像素值减去前面的
横向(X轴方向):
代码实现:
# @Time : 2022/6/10 15:40
# @Author : Fioman
# @Phone : 13149920693
# @Tips : Talk is Cheap,Show me the code! ^_^^_^
from settings import *
def BGR_to_GRAY(image):
b = image[..., 0].copy()
g = image[..., 1].copy()
r = image[..., 2].copy()
out = 0.2126 * r + 0.7152 * g + 0.0722 * b
out = np.clip(out, 0, 255)
return out
def prewitt_filter(image):
kSize = 3
if len(image.shape) == 3:
image = BGR_to_GRAY(image)
# zero Padding
H, W = image.shape
pad = kSize // 2
out = np.zeros((H + pad * 2, W + pad * 2), dtype=np.float32)
out[pad:pad + H, pad:pad + W] = image.copy().astype(np.float32)
temp = out.copy()
outX = out.copy()
outY = out.copy()
kernelX = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]])
kernelY = np.array([[-1, -1, -1], [0, 0, 0], [1, 1, 1]])
for y in range(H):
for x in range(W):
outY[pad + y, pad + x] = np.sum(kernelY * (temp[y:y + kSize, x:x + kSize]))
outX[pad + y, pad + x] = np.sum(kernelX * (temp[y:y + kSize, x:x + kSize]))
outX = np.clip(outX, 0, 255)
outY = np.clip(outY, 0, 255)
outX = outX[pad:pad + H, pad:pad + W].astype(np.uint8)
outY = outY[pad:pad + H, pad:pad + W].astype(np.uint8)
return outX, outY
if __name__ == '__main__':
imagePath = os.path.join(OPENCV_100_Q_PATH,"gray_01.bmp")
imageOriginal = cv.imread(imagePath,cv.IMREAD_GRAYSCALE)
prewittX,prewittY = prewitt_filter(imageOriginal)
cv.imshow("Origial",imageOriginal)
cv.imshow("PrewittX",prewittX)
cv.imshow("PrevittY",prewittY)
cv.waitKey(0)
17. Laplacian 滤波器
拉普拉斯滤波器也叫调和滤波器,是对图像亮度进行二次微分从而检测边缘的滤波器,由于数字图像是离散的,x方向和y方向的一次微分分别按照以下的式子进行计算:
因此二次微分按照以下的式子进行计算:
特此,Laplician表达式如下:
把这个式子表示为卷积核是这样的:
感觉拉普拉斯算子可以这么理解,使用它的四邻域的像素和中心点像素做差值,最后得到的结果就是拉普拉斯滤波得到的效果.不同于Sobel算子,他们是分纵向和横向的,拉普拉斯算子不分方向,直接得到结果.
代码实现:
# @Time : 2022/6/10 16:02
# @Author : Fioman
# @Phone : 13149920693
# @Tips : Talk is Cheap,Show me the code! ^_^^_^
from settings import *
def BGR_to_GRAY(image):
b = image[..., 0].copy()
g = image[..., 1].copy()
r = image[..., 2].copy()
out = r * 0.2126 + g * 0.7152 + b * 0.0722
out = np.clip(out, 0, 255)
return out
def laplacian_filter(image):
kSize = 3
if len(image.shape) == 3:
image = BGR_to_GRAY(image)
H, W = image.shape
# zero padding
pad = int(kSize / 2)
out = np.zeros((H + pad * 2, W + pad * 2), dtype=np.float32)
out[pad:pad + H, pad:pad + W] = image.copy().astype(np.float32)
laplacianKernel = np.array([[0, 1, 0], [1, -4, 1], [0, 1, 0]])
temp = out.copy()
for y in range(H):
for x in range(W):
out[pad + y, pad + x] = np.sum(laplacianKernel * temp[y:y + kSize, x:x + kSize])
out = np.clip(out, 0, 255)
out = out[pad:pad + H, pad:pad + W].astype(np.uint8)
return out
if __name__ == '__main__':
imagePath = os.path.join(OPENCV_100_Q_PATH, "gray_01.bmp")
imageOriginal = cv.imread(imagePath, cv.IMREAD_GRAYSCALE)
laplacianFilter = laplacian_filter(imageOriginal)
cv.imshow("Original", imageOriginal)
cv.imshow("LaplacianFilter", laplacianFilter)
cv.waitKey(0)
18. Emboss 滤波器
使用Emboss滤波器来进行滤波的时候可以使得物体的轮廓更加的清晰;
Emboss滤波核为:
这个滤波器如何去理解呢?其实就是右下角和左上角的差值,然后再和原来的像素值相加.
其中最远角的系数是2,其他都是1.
这种滤波的意义是什么呢? 如果这个中心的位置是边缘,那么这个差值肯定是存在的,就可以让整个边缘增强了.
# @Time : 2022/6/10 16:17
# @Author : Fioman
# @Phone : 13149920693
# @Tips : Talk is Cheap,Show me the code! ^_^^_^
from settings import *
def BGR_to_GRAY(image):
b = image[..., 0]
g = image[..., 1]
r = image[..., 2]
out = 0.2126 * r + 0.7152 * g + 0.0722 * b
out = np.clip(out, 0, 255)
return out
def emboss_filter(image):
if len(image.shape) == 3:
image = BGR_to_GRAY(image)
H, W = image.shape[:2]
embossKernel = np.array([[-2, -1, 0], [-1, 1, 1], [0, 1, 2]])
# zero padding
kSize = 3
pad = int(kSize / 2)
out = np.zeros((H + 2 * pad, W + 2 * pad), dtype=np.float32)
out[pad:pad + H, pad:pad + W] = image.copy().astype(np.float32)
temp = out.copy()
for y in range(H):
for x in range(W):
out[y + pad, x + pad] = np.sum(temp[y:(y + kSize), x:(x + kSize)] * embossKernel)
out = np.clip(out, 0, 255)
out = out[pad:pad + H, pad:pad + W].astype(np.uint8)
return out
if __name__ == '__main__':
imagePath = os.path.join(OPENCV_100_Q_PATH, "gray_01.bmp")
imageOriginal = cv.imread(imagePath, cv.IMREAD_GRAYSCALE)
embossFilter = emboss_filter(imageOriginal)
cv.imshow("Original", imageOriginal)
cv.imshow("EmbossFilter", embossFilter)
cv.waitKey(0)
19. LoG 滤波器
LoG
即高斯-拉普拉斯(Laplacian of Gaussian)的缩写,使用高斯滤波器使图像平滑之后再使用拉普拉斯滤波器使得图像的轮廓更加清晰.为了防止拉普拉斯滤波器计算二次微分会使得图像噪声更加明显,所以我们首先使用高斯滤波器来抑制噪声.
定义的公式如下:
实现代码:
# @Time : 2022/6/10 17:01
# @Author : Fioman
# @Phone : 13149920693
# @Tips : Talk is Cheap,Show me the code! ^_^^_^
from settings import *
def BGR_to_GRAY(image):
b = image[..., 0]
g = image[..., 1]
r = image[..., 2]
out = r * 0.2126 + g * 0.7152 + b * 0.0722
out = out.astype(np.uint8)
return out
def LoG_filter(image, kSize=5, sigma=3.0):
if len(image.shape) == 3:
image = BGR_to_GRAY(image)
H, W = image.shape
# zero padding
pad = int(kSize / 2)
out = np.zeros((H + 2 * pad, W + 2 * pad), dtype=np.float32)
out[pad:pad + H, pad:pad + W] = image.copy().astype(np.float32)
# LoG Kernel
K = np.zeros((kSize, kSize), dtype=np.float32)
for x in range(-pad, -pad + kSize):
for y in range(-pad, -pad + kSize):
K[y + pad, x + pad] = (x ** 2 + y ** 2 - sigma ** 2) * np.exp(-(x ** 2 + y ** 2) / (2 * (sigma ** 2)))
K /= (2 * np.pi * (sigma * 6))
K /= K.sum()
temp = out.copy()
# filtering
for y in range(H):
for x in range(W):
out[pad + y, pad + x] = np.sum(K * temp[y:y + kSize, x:x + kSize])
out = np.clip(out, 0, 255)
out = out[pad:pad + H, pad:pad + W].astype(np.uint8)
return out
if __name__ == '__main__':
imagePath = os.path.join(OPENCV_100_Q_PATH,"gray_01.bmp")
imageOriginal = cv.imread(imagePath,cv.IMREAD_GRAYSCALE)
LoGFilter = LoG_filter(imageOriginal,5,1.5)
cv.imshow("Original",imageOriginal)
cv.imshow("LoGFilter",LoGFilter)
cv.waitKey(0)
20. 直方图
通俗的来讲直方图要表达的是,横向要表现的是某个状态,而纵向要表现的是这个状态出现的次数.
直方图会将要展示的数据按照数值的范围切割为多个组/间隔,这些组/间隔在英文中称作bin,然后会统计出处在各个数据段中的数据个数并且以不同长度的长条展示出来.所以直方图本身也是一种条形图
plt.hist()函数绘制直方图
hist(x, bins=None, range=None, density=None, weights=None,
cumulative=False, bottom=None, histtype='bar', align='mid',
orientation='vertical', rwidth=None, log=False,
color=None, label=None, stacked=False, normed=None,
**kwargs):
参数解释:
x:
(n,) array or sequence of (n,) arrays. 这个参数是指定每个bin(箱子)分布的数据,对应x轴.bins:
这个参数执行bin(箱子)的个数,也就是总共有几条条状图normed:
这个参数已经丢弃,使用density
参数来代替了.range:
元祖或者None. bin的上下限.如果没有提供,默认使用(x.min(),x.max())density:
是否以密度的方式显示,默认是None,密度形式其实就是归一化.align:
对齐方式 “left”:左,“mid”:中间,"right:"右bottom:
y轴的起始位置,数值类型orientation:
方向, horizontal: 水平, vertical:垂直
# @Time : 2022/6/10 17:27
# @Author : Fioman
# @Phone : 13149920693
# @Tips : Talk is Cheap,Show me the code! ^_^^_^
from settings import *
import matplotlib.pyplot as plt
if __name__ == '__main__':
imagePath = os.path.join(OPENCV_100_Q_PATH,"gray_01.bmp")
imageOriginal = cv.imread(imagePath,cv.IMREAD_GRAYSCALE)
plt.hist(imageOriginal.ravel(),bins=256,rwidth=0.8,range = (0,255))
plt.show()