图像基础、OpenCV入门3——图像灰度化、二值化与图像加噪
一、图像灰度化
1. 图像灰度化概念
图像灰度化是将一幅彩色图像转换为灰度图像的过程。在灰度图像中,每个像素只包含一个灰度值,而不是彩色图像中的红、绿和蓝三个通道。灰度图像通常用于简化图像处理和分析,因为它们只包含亮度信息,而没有颜色信息。
图像灰度化的应用包括图像处理、计算机视觉、模式识别等领域。它有助于减少数据维度,简化图像处理算法,并提供更好的对比度和亮度信息,使图像特征更容易分析和识别。
2. 图像灰度化的一些常用方法
(1)加权平均法
通过使用不同的权重来从彩色通道中提取亮度信息。通常根据人眼对不同颜色敏感程序的不同,绿色通过的权重最高,红色次之,蓝色最低。 公式如下:
Gray = 0.299 * R + 0.587 * G + 0.114 * B
(2)平均值法
计算每个像素颜色通道的平均值,方法简单,但结果可能不太准确。
(3)最大值和最小值法
最大值法选取颜色通道中的最大值作为灰度值,而最小值法选取颜色通道中的最小值。这些方法可以用于特定应用,但通常不太常见。
(4) 分量法
这种方法通常用于处理黑白图像。它只选择一个颜色通道,通常是红色通道,作为灰度图像的唯一通道。
(5)加权平均法的改进
通过对加权平均法的权重进行特定的调整来实现。
3. 典型的实现方式
(1)平均值法
求出每个像素点的RGB三个分量的平均值,然后将这个平均值赋予给这个像素的三个分量。
下面是实现方式:
import cv2
import numpy as np
# 读取彩色图像
input_image = cv2.imread('test.png')
# 确保图像成功加载
if input_image is None:
print("无法加载图像文件")
else:
# 获取图像的高度和宽度
height, width = input_image.shape[:2]
# 创建一个空的灰度图像
gray_image = np.zeros((height, width), dtype=np.uint8)
# 遍历每个像素并计算平均值
for y in range(height):
for x in range(width):
# 获取像素的BGR通道值
b, g, r = input_image[y, x]
# 计算平均值并将其赋给灰度图像
gray_value = int((int(b) + int(g) + int(r)) / 3)
gray_image[y, x] = gray_value
# 显示原始图像和灰度图像
cv2.imshow('原始图像', input_image)
cv2.imshow('灰度图像', gray_image)
# 等待按键按下后关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
(2)加权平均法
求RGB和YUV颜色空间的变化关系,建立亮度Y与RGB三个颜色分量的对应关系:Gray = 0.299 * R + 0.587 * G + 0.114 * B
,以这个亮度值表达图像的灰度值。OpenCV的cvtColor函数,可以直接完成灰度化操作。
上面平均法简单修改一下,即可实现加权平均法:
import cv2
import numpy as np
# 读取彩色图像
input_image = cv2.imread('test.png')
# 确保图像成功加载
if input_image is None:
print("无法加载图像文件")
else:
# 获取图像的高度和宽度
height, width = input_image.shape[:2]
# 创建一个空的灰度图像
gray_image = np.zeros((height, width), dtype=np.uint8)
# 遍历每个像素并计算平均值
for y in range(height):
for x in range(width):
# 获取像素的BGR通道值
b, g, r = input_image[y, x]
# 计算平均值并将其赋给灰度图像
gray_value = 0.114*b + 0.587*g + 0.299*r
gray_image[y, x] = gray_value
# 显示原始图像和灰度图像
cv2.imshow('原始图像', input_image)
cv2.imshow('灰度图像', gray_image)
# 等待按键按下后关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
(3)OpenCV的内置函数
#-*- coding: utf-8 -*-
import cv2
# 读取彩色图像
input_image = cv2.imread('test.png')
# 确保图像成功加载
if input_image is None:
print("无法加载图像文件")
else:
# 调用 OpenCV 灰度函数
gray_image = cv2.cvtColor(input_image, cv2.COLOR_BGR2GRAY)
# 显示原始图像和灰度图像
cv2.imshow('原始图像', input_image)
cv2.imshow('灰度图像', gray_image)
# 等待按键按下后关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
实际上RGB并不能反映图像的形态特征,只是从光学的原理蚝颜色的调配。把图像转换成8位的灰度值图像直接进行处理,可以通过直方图、灰度变化及正交变化之类数学运算对图像做进一步处理,比如说图像识别等。如果有必要,可将图像二值化,这样有利于对图像进一步处理,使图像数据量减小,突显出感兴趣的目标的轮廓。
二、图像二值化
1. 图像二值化的概念
图像二值化(Image Binarization)是一种图像处理技术,它将一幅灰度图像转换为只包含两个像素值的二值图像,通常是黑色(0)和白色(255)或其他两种互斥的颜色。二值化的目标是将图像中的信息从背景中分离出来,以便更容易进行特征提取、分割和分析。
图像二值化的主要思想是根据像素的灰度值将图像分为两个不同的区域:前景和背景。前景通常包含我们感兴趣的目标对象,而背景则是目标对象的周围环境。通过将前景和背景分离成明显不同的像素值,可以更容易地进行目标检测、分割、轮廓提取等图像处理任务。
- 字符识别:在光学字符识别(OCR)和文本分析中,图像二值化用于将文本从图像中提取出来,以便进行字符识别。
- 目标检测:在计算机视觉中,二值化有助于分离目标对象(如人脸、车辆等)和背景,从而更容易进行目标检测和跟踪。
- 图像分割:图像二值化是图像分割的预处理步骤,用于将图像分为多个区域,以便分析各个区域的特征。
- 文档处理:在文档图像处理中,二值化用于将文本、图形和背景分离,以便进行文档分析和处理。
图像二值化可以使用不同的阈值处理方法来实现,包括全局阈值、自适应阈值和局部阈值等。全局阈值将整个图像的灰度范围划分为两个区域,而自适应阈值和局部阈值考虑了像素周围的上下文信息,因此在某些情况下可以更有效地处理不均匀光照或噪声的图像。选择合适的二值化方法取决于具体的应用和图像特性。
2. OpenCV里的二值化函数
cv2.threshold 是OpenCV库中用于图像二值化的函数。它可将灰度图像中的像素值转换为二进制像素值,将图像分成两个部分:前景(白色像素)和背景(黑色像素),以便进行目标检测、分割、特征提取等任务。cv2.threshold 函数的基本语法如下:
retval, threshold = cv2.threshold(src, thresh, maxval, type[, dst])
(1)参数说明:
-
src 输入灰度图像
-
thresh 指定的阈值,大于阈值的像素被分配为maxval,小于阈值的像素被分配为0.
-
maxval 分配给像素值大于阈值像素的值,通常是255表示白色。
-
type 指定二值化的类型,包括 :
- cv2.THRESH_BINARY:二进制阈值化,将像素值大于阈值的设置为 maxval,小于等于阈值的设置为0。
- cv2.THRESH_BINARY_INV:反二进制阈值化,与 cv2.THRESH_BINARY 相反,将像素值大于阈值的设置为0,小于等于阈值的设置为 maxval。
- cv2.THRESH_TRUNC:截断阈值化,将像素值大于阈值的设置为阈值,小于等于阈值的保持不变。
- cv2.THRESH_TOZERO:将像素值大于阈值的保持不变,小于等于阈值的设置为0。
- cv2.THRESH_TOZERO_INV:与 cv2.THRESH_TOZERO 相反,将像素值大于阈值的设置为0,小于等于阈值的保持不变。
-
dst 输出图像,不提供则函数会直接修改输入图像src
(2)返回值
- retval 计算出的阈值,通常用于后续的图像处理
- threshold 二值化二的输出图像。
3. OpenCV二值化示例
#-*- coding: utf-8 -*-
import cv2
# 读取灰度图像
image = cv2.imread('test.png', cv2.IMREAD_GRAYSCALE)
# 设置阈值
threshold_value = 128
# 应用二值化
retval, binary_image = cv2.threshold(image, threshold_value, 255, cv2.THRESH_BINARY)
# 显示原始图像和二值化图像
cv2.imshow('原始图像', image)
cv2.imshow('二值化图像', binary_image)
# 等待按键按下后关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
三、图像加噪
1. 概念
图像加噪是指在一幅图像中引入不希望的、随机或人为制造的像素值的变化,这些变化可能来自于各种源头,包括传感器噪声、环境条件、传输问题、图像采集设备的问题或意图明确的操作。噪声可以干扰或损害图像的质量,使其更难以分析、处理或识别。
噪声可以分为以下几种主要类型:
-
加性噪声(Additive Noise):这种类型的噪声是在图像的像素值上添加的,通常是由于传感器的电子噪声、环境干扰或通信问题。加性噪声会导致图像的像素值变得不稳定和不一致。
-
乘性噪声(Multiplicative Noise):与加性噪声不同,乘性噪声是通过将像素值与随机数相乘来引入的,通常会使图像的亮度发生变化。这种噪声通常出现在低光条件下的图像中。
-
量化噪声(Quantization Noise):量化噪声是由于将连续的图像信号量化为离散像素值而引入的。这种噪声通常在数字图像处理中出现,尤其是在压缩和编码过程中。
-
随机噪声(Random Noise):这是一种随机引入的噪声,通常具有高度不可预测性。它可以采取各种形式,如高斯噪声、脉冲噪声、椒盐噪声等。
-
确定性噪声(Deterministic Noise):这种噪声是由于特定的图像处理操作或设备问题引起的,例如摄像头伪像、坏像素或纹理。
图像加噪的原因和目的各不相同,有时可能是不可避免的,但在大多数情况下,噪声是图像处理的不良影响。因此,图像处理任务通常包括去噪步骤,以减少或消除图像中的噪声,从而提高图像质量和可用性。去噪方法包括使用滤波器、统计方法、深度学习等技术来恢复原始图像中的信息,同时尽量减少噪声的影响。
2. 常见加噪方式
图像加噪的方式有很多,这些方式可以根据噪声的性质和来源进行分类。以下是一些常见的图像加噪方式:
-
高斯噪声(Gaussian Noise):高斯噪声是一种加性噪声,其像素值是根据正态分布随机生成的。它模拟了许多自然现象中的噪声,如电子设备的电子噪声和大气干扰。高斯噪声通常呈均匀分布在图像中的像素上。
-
盐和胡椒噪声(Salt and Pepper Noise):盐和胡椒噪声是一种乘性噪声,其中一些像素被设置为最大或最小像素值,模拟了图像中的噪点。这种噪声可能是由于传感器故障或图像传输中的错误引入的。
-
均匀噪声(Uniform Noise):均匀噪声是一种加性噪声,它的像素值是根据均匀分布在一定范围内的随机值生成的。这种噪声使图像看起来更加均匀,而不是高斯噪声那样集中在中心值附近。
-
泊松噪声(Poisson Noise):泊松噪声是一种统计性噪声,通常与低光条件下的图像有关。它模拟了光子的随机性,因此在光线较暗的情况下更常见。
-
周期性噪声(Periodic Noise):周期性噪声通常由于电源干扰或光源问题引起,它在图像中呈现出明显的周期性纹理或条纹,可以使用滤波器等方法去除。
-
亮度均匀性噪声(Illumination Uniformity Noise):这种噪声通常与光照条件不均匀有关,导致图像中的亮度不均匀分布。
-
压缩噪声(Compression Noise):压缩噪声是在图像压缩和解压缩过程中引入的,尤其在高压缩比下更为明显。
-
运动模糊(Motion Blur):运动模糊是由于相机或物体移动而引入的图像模糊,它不是传统的噪声,但可以降低图像质量。
这些噪声形式各异,可能是自然发生的,也可能是由于传感器、设备或传输问题引起的。对于不同类型的噪声,通常需要采用不同的去噪方法来恢复图像的原始信息。
3. 一些加噪实现方式
(1)盐和胡椒噪声
#-*- coding: utf-8 -*-
import cv2
import numpy as np
img = cv2.imread('test.png')
# 噪声点数量
coutn = 100000
for k in range(0,coutn):
# 获取图像噪声点的随机位置
xi = int(np.random.uniform(0,img.shape[1]))
xj = int(np.random.uniform(0,img.shape[0]))
#加噪
if img.ndim == 2:
# 灰度图像
img[xj,xi] = 255
elif img.ndim == 3:
# 非灰度图像,图像加噪
img[xj,xi,0] = 25
img[xj,xi,1] = 20
img[xj,xi,2] = 20
cv2.namedWindow('img')
cv2.imshow('img',img)
cv2.waitKey()
cv2.destroyAllWindows()
(2)高斯噪声
import cv2
import numpy as np
# 读取图像
image = cv2.imread('test.png')
# 创建一个具有相同维度的随机高斯噪声
row, col, ch = image.shape
mean = 0
sigma = 25 # 标准差,控制噪声的强度
gaussian_noise = np.random.normal(mean, sigma, (row, col, ch)).astype(np.uint8)
# 将高斯噪声添加到图像中
noisy_image = cv2.add(image, gaussian_noise)
# 显示原始图像和带有高斯噪声的图像
cv2.imshow('原始图像', image)
cv2.imshow('带有高斯噪声的图像', noisy_image)
# 等待按键按下后关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
上面代码使用的高斯噪声函数是np.random.normal,
np.random.normal(mean, sigma, (row, col, ch))
。
参数说明:
mean
:正态分布的均值,表示噪声的中心位置。在这里,mean
被设置为 0,表示噪声的中心值为0。sigma
:正态分布的标准差,控制随机数的分布范围。较大的sigma
会产生更强的噪声。在这里,sigma
被设置为 25,表示噪声的标准差为25。(row, col, ch)
:指定了生成随机数数组的形状,其中row
、col
、和ch
分别是图像的行数、列数和通道数。这确保了生成的随机数数组与图像具有相同的维度。
另外: .astype(np.uint8)
说明:
这部分代码将生成的随机数数组转换为 NumPy 数据类型 np.uint8
,即无符号8位整数。这是因为图像的像素值通常使用无符号8位整数来表示,范围在 0 到 255 之间。
(3)泊松噪声
import cv2
import numpy as np
# 读取图像
image = cv2.imread('input.jpg')
# 创建一个具有相同维度的随机泊松噪声
row, col, ch = image.shape
lambda_value = 25 # 泊松分布的参数,控制噪声的强度
poisson_noise = np.random.poisson(lambda_value, (row, col, ch)).astype(np.uint8)
# 将泊松噪声添加到图像中
noisy_image = cv2.add(image, poisson_noise)
# 显示原始图像和带有泊松噪声的图像
cv2.imshow('原始图像', image)
cv2.imshow('带有泊松噪声的图像', noisy_image)
# 等待按键按下后关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
np.random.poisson
是NumPy库中用于生成泊松分布随机数的函数。泊松分布用来描述在一段固定时间或空间内随机事件发生次数的概率分布,通常用于模拟稀有事件的发生情况。这个分布适用于以下情况:
- 事件在连续时间或空间中是离散的。
- 事件发生的平均速率是已知的。
- 事件在不同的时间段或空间区域内是独立的。
np.random.poisson
函数的基本语法如下:
numpy.random.poisson(lam=1.0, size=None)
其中:
lam
:是泊松分布的平均速率(或均值),表示在固定时间或空间内事件发生的平均次数。必须为非负数。如果lam
为1.0,那么它表示单位时间或空间内平均发生1次事件。size
:是生成随机数的数量,可以是整数或表示形状的元组。如果未指定size
,则函数将返回一个单一的随机数。
函数的返回值是一个具有指定大小的NumPy数组,其中包含符合泊松分布的随机数。
(4)实现运动模糊
i. 运动模糊核
运动模糊核是一种用于模拟图像中的运动模糊效果的卷积核或滤波器。
运动模糊效果通常是由于相机或拍摄设备在拍摄图像时或物体在移动时引起的图像模糊。运动模糊核的目标是模拟物体在一段时间内在图像上的运动,从而使图像中的对象看起来模糊或拉伸。
ii. 创建运动模糊核
创建一个运动模糊核,用于模拟图像中的运动模糊效果。核的大小由 kernel_size 控制,模糊的方向由 angle 控制。具体步骤包括:
- 创建一个大小为 kernel_size x kernel_size 的零矩阵,该矩阵将用于存储运动模糊核。
- 计算运动模糊的方向,通过将 angle 转换为弧度,然后使用正弦和余弦函数计算方向上的位移。
- 在运动模糊核中填充权重,以创建指定方向上的模糊效果。
- 最后,对模糊核进行归一化,以确保权重之和为1。
iii. 应用运动模糊
使用OpenCV的cv2.filter2D
函数将运动模糊核应用于原始图像上,从而生成带有运动模糊的图像。
该函数通常用于图像处理中的滤波、特征提取和图像增强等任务。二维卷积是一种将一个核或滤波器应用于输入图像的像素值的操作,以产生输出图像的过程。
#-*- coding: utf-8 -*-
import cv2
import numpy as np
# 读取图像
image = cv2.imread('test.png')
# 创建运动模糊核
kernel_size = 15 # 运动模糊核的大小
angle = 45 # 运动模糊的方向角度
motion_blur_kernel = np.zeros((kernel_size, kernel_size))
center = (kernel_size - 1) / 2
# 计算模糊核的方向
angle_rad = np.deg2rad(angle)
sin_val = np.sin(angle_rad)
cos_val = np.cos(angle_rad)
# 填充模糊核
for i in range(kernel_size):
x = int(center + sin_val * (i - center))
y = int(center + cos_val * (i - center))
motion_blur_kernel[y, x] = 1
motion_blur_kernel /= motion_blur_kernel.sum() # 归一化
# 应用运动模糊
blurred_image = cv2.filter2D(image, -1, motion_blur_kernel)
# 显示原始图像、带有运动模糊的图像和带有运动模糊和噪声的图像
cv2.imshow('原始图像', image)
cv2.imshow('带有运动模糊的图像', blurred_image)
# 等待按键按下后关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()