6. 减色处理
减色处理就是将图片的256 ^ 3个色调变成 4 ^ 3个色调,也就是将原来每个通道256个颜色级分成四个区间压缩到4个颜色级,这四个灰度级是给出的.分别是32, 96, 160,224.
pix = 32 (0 <= pix < 64)
pix = 96 (64 <= pix < 128)
pix = 160 (128 <= pix < 192)
pix = 224 (192 <= pix < 256)
可以得到一个公式就是
pix = (int)(pix/64)*64 + 32
代码部分:
# @Time : 2022/6/9 13:46
# @Author : Fioman
# @Phone : 13149920693
# @Tips : Talk is Cheap,Show me the code! ^_^^_^
from settings import *
# Dicrease color
def dicrease_color(image):
"""
对图像进行减色处理
:param image:
:return:
"""
out = image.copy()
out = out // 64 * 64 + 32
return out
if __name__ == '__main__':
imagePath = os.path.join(OPENCV_100_Q_PATH,"gray_01.bmp")
imageOriginal = cv.imread(imagePath,cv.IMREAD_COLOR)
imageDicrease = dicrease_color(imageOriginal)
cv.imshow("ImageOriginal",imageOriginal)
cv.imshow("ImageDicrease",imageDicrease)
cv.waitKey(0)
7. 平均池化(Average Pool)
将图片按照固定大小网格分割,网格内的像素值取网格内所有像素的平均值.
我们将这种把图片使用均等大小网格分割,并求网格内代表值的操作叫做池化(Pooling).
池化操作是卷积神经网络(Convolutional Neural Network)
中重要的图像处理方式.平均池化按照下式定义:
请把大小为128 * 128 的图片使用 8 * 8 的网格做平均池化,平均池化是把该区域内所有的像素值全部改为平局值
# @Time : 2022/6/9 14:10
# @Author : Fioman
# @Phone : 13149920693
# @Tips : Talk is Cheap,Show me the code! ^_^^_^
from settings import *
def average_pooling(image, G=8):
out = image.copy()
if len(image.shape) == 3:
H, W, C = image.shape
else:
H, W = image.shape[:2]
C = []
newW = int(W / G)
newH = int(H / G)
for y in range(newH):
for x in range(newW):
if C != []:
for c in range(C):
out[G * y:G * (y + 1), G * x:G * (x + 1), c] =
np.mean(out[G * y, G * (y + 1), G * x:G * (x + 1), c]).astype(np.uint8)
else:
out[G * y:G * (y + 1), G * x:G * (x + 1)] =
np.mean(out[G * y:G * (y + 1), G * x:G * (x + 1)]).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)
averPoolImage = average_pooling(imageOriginal, 8)
cv.imshow("Original", imageOriginal)
cv.imshow("AverPoolImage", averPoolImage)
cv.waitKey(0)
8. 最大池化(Max Pooling)
网格内的值不取平均值,而是取网格内的最大值进行池化操作
# @Time : 2022/6/9 15:56
# @Author : Fioman
# @Phone : 13149920693
# @Tips : Talk is Cheap,Show me the code! ^_^^_^
from settings import *
def max_pooling(image, G=8):
# Max Pooling
out = image.copy()
if len(image.shape) == 3:
H, W, C = image.shape
else:
H, W = image.shape[:2]
C = None
hNums = int(H / G)
wNums = int(W / G)
for y in range(hNums):
for x in range(wNums):
if C is not None:
for c in range(C):
out[G * y:G * (y + 1), G * x:G * (x + 1), c] =
np.max(out[G * y:G * (y + 1), G * x:G * (x + 1)], c)
else:
out[G * y:G * (y + 1), G * x:G * (x + 1)] =
np.max(out[G * y:G * (y + 1), G * x:G * (x + 1)])
return out
if __name__ == '__main__':
imagePath = os.path.join(OPENCV_100_Q_PATH, "gray_01.bmp")
imageOrginal = cv.imread(imagePath, cv.IMREAD_GRAYSCALE)
maxPool = max_pooling(imageOrginal, 8)
cv.imshow("Orginal", imageOrginal)
cv.imshow("MaxPool", maxPool)
cv.waitKey(0)
9. 高斯滤波(Gaussian Filter)
高斯滤波(Gaussian Filter)是线性滤波中的一种.高斯滤波主要用来平滑(模糊)图像,高斯滤波也是一种低通滤波器.
高斯滤波器的思想:
图像上的每个像素点的值,由其本身和邻域内的其他的像素点的值经过加权平均后得到.只是这个用来加权的核,是根据高斯分布求的.其中中心点是这个像素点本身,整个核服从高斯分布.
高斯函数:
一维高斯函数:
G(x)
跟sigma
的取值有极大的关系,sigma
取值越大,图像越平滑,sigma
取值越小,图像越尖锐.
要理解高斯模糊,首先要明白一点,高斯公式是用来计算核权重的值的,并且这个中心点凸起的部分就是要计算的像素点.现在假定一组像素点,另sigma=1.5:
将像素坐标带入到高斯公式中,得到占用的权重为:
这里计算出来的结果为该相对位置的权重,而这个权重和像素值的值无关,是根据相对位置套用高斯公式去计算的.这个值计算之后,要根据归一化处理,就是使得权重的和是1,方法就是让上面的值除以它们的和,最终使得它们的和为1.
这里就得到了高斯卷积核,然后再跟像素值做卷积即可:
扩展到二维
高斯滤波模板的生成:
通过二维高斯函数进行计算,假如我们一个高斯模板的长宽均为5,方差为0.5,那么首先,我们是在卷积核模板上建立一个坐标系,其原点就是高斯模板的中心点,如下图:
高斯滤波器的模板: 两种形式,一个是小数形式,一个是整数形式
小数形式的模板:
就是直接计算得到的值,然后将值除以它们之和.整数形式的模板:
需要进行归一化处理,将模板的左上角的值归一化为1.整数模板需要加一个系数,系数为模板系数和的倒数.
sigma的意义和选取:
高斯分布中的sigma代表的是标准差.标准差代表着离散程度,也表示高斯分布那个钟摆图像的宽度. sigma越小,表示离散程度越大,分布比较集中,中间部分所占用的比重远远高于其他的部分. 而sigma越大,表示离散程度越小,分布比较分散,中间部分占用比重和其他的部分占用的比重差不多.
高斯滤波代码实现:
# @Time : 2022/6/10 10:35
# @Author : Fioman
# @Phone : 13149920693
# @Tips : Talk is Cheap,Show me the code! ^_^^_^
from settings import *
def gaussian_filter(image, kSize=3, sigma=1.3):
"""
高斯滤波实现
:param image:
:param kSize:
:param sigma:
:return:
"""
if len(image.shape) == 3:
H, W, C = image.shape
else:
image = np.expand_dims(image, axis=-1)
H, W, C = image.shape
## Zero Padding
pad = kSize // 2
out = np.zeros((H + pad * 2, W + pad * 2, C), dtype=np.float32)
out[pad:pad + H, pad:pad + W] = image.copy().astype(np.float32)
## preprare 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] = np.exp(-(x ** 2 + y ** 2) / (2 * (sigma ** 2)))
K /= (2 * np.pi * sigma * sigma)
K /= K.sum()
temp = out.copy()
# filter
for y in range(H):
for x in range(W):
for c in range(C):
out[pad + y, pad + x, c] = np.sum(K * temp[y:y + kSize, x:x + kSize, c])
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)
gaussianFilter = gaussian_filter(imageOriginal, 3, 1.2)
cv.imshow("Original", imageOriginal)
cv.imshow("GaussianFilter",gaussianFilter)
cv.waitKey(0)
10. 中值滤波
中值滤波也是一种可以使得图像平滑的滤波器.采用滤波核范围内的像素的中值进行滤波.边缘填充使用Zero Padding
代码实现:
# @Time : 2022/6/10 10:54
# @Author : Fioman
# @Phone : 13149920693
# @Tips : Talk is Cheap,Show me the code! ^_^^_^
from settings import *
def median_filter(image, kSize=3):
"""
中值滤波
:param image: 滤波的图片
:param kSize: 滤波核大小
:return:
"""
if len(image.shape) == 3:
H, W, C = image.shape
else:
image = np.expand_dims(image, axis=-1)
H, W, C = image.shape
pad = kSize // 2
imagePadding = np.zeros((H + 2 * pad, W + 2 * pad, C), dtype=np.float32)
imagePadding[pad:pad + H, pad:pad + W] = image.copy().astype(np.float32)
temp = imagePadding.copy()
for y in range(H):
for x in range(W):
for c in range(C):
imagePadding[pad + y, pad + x, c] = np.median(temp[y:y + kSize, x:x + kSize, c])
imagePadding = imagePadding[pad:pad + H, pad:pad + W].astype(np.uint8)
return imagePadding
if __name__ == '__main__':
imagePath = os.path.join(OPENCV_100_Q_PATH,"gray_01.bmp")
imageOriginal = cv.imread(imagePath,cv.IMREAD_GRAYSCALE)
medianBlured = median_filter(imageOriginal,3)
cv.imshow("Original",imageOriginal)
cv.imshow("MedianBlured",medianBlured)
cv.waitKey(0)