一.数字图像基本定义
一幅单通道灰度图像定义为一个二元连续函数f(x,y),其中各分量x和y是对应的平面坐标。对于这样的空间曲面函数,在任意位置(x,y)处的函数值就是单通道数字图像在该点处的灰度值或者强度值。当x,y和f(x,y)都是有限的离散量时,就是数字图像。简单来说,数字图像是由二维离散像素点组成的,每个像素点都具有特定的颜色和亮度值。
数字图像根据颜色信息(通道数)可以分为:
- 灰度数字图像:每个像素点只有一个亮度值(强度值),通常是0到255之间的整数,其中0代表黑色,255代表白色,中间的值则表示不同的灰度级别。
- 彩色数字图像:每个像素点由多个通道(通常为红色、绿色和蓝色,即RGB)组成,每个通道分别存储不同颜色的强度值,通过混合不同的颜色通道来表示各种颜色。
二.数字图像读取操作
1. 读取
cv2.imread是 OpenCV 库中的一个函数,用于从文件中读取图像,并将其加载为一个 NumPy 数组。这个函数能够加载不同格式的图像,如 JPEG、PNG、BMP 等。返回值是一个多维 NumPy 数组,表示读取到的图像。如果加载失败,函数将返回None。
cv2.imread(filename, flags)
"""
filename:字符串类型,表示要读取的图像文件的路径。可以是相对路径或绝对路径
flags:整数类型,可选参数,用于指定图像的读取方式
常用的读取方式:
cv2.IMREAD_COLOR(彩色图像)
cv2.IMREAD_GRAYSCALE(灰度图像)
cv2.IMREAD_UNCHANGED(保持原始通道数)
"""
使用opencv的库函数cv2.imread()进行图像读取
image_grey = cv2.imread(r'D:\pythonwork\imagepro\data\Fig0001.tif', cv2.IMREAD_GRAYSCALE)
读取结果:

2. 可视化(matplotlib+opencv)
cv2.imshow()是 OpenCV 库中用于在交互式窗口中显示图像的库函数。它创建一个窗口并显示指定的图像,可以用于在计算机视觉任务中检查和可视化处理后的图像。
cv2.imshow(winname, mat)
"""
winname:字符串类型,表示窗口的名称。它指定将要显示的窗口的名称,并且此名称也是窗口的标识符。如果多个窗口被创建,每个窗口都需要一个唯一的名称
mat:要显示的图像,即 NumPy 数组。通常由 cv2.imread() 读取的图像或其他处理后的图像。这是一个二维或三维数组,表示要显示的图像。图像可以是彩色图像(RBG)或者灰度图像
"""
使用opencv的库函数cv2.imshow()进行图像可视化
"""
cv2.waitKey(delay)用于暂停程序并等待用户输入的按键,单位为毫秒。如果 delay 为 0,则会无限期等待,直到用户按下键盘上的任意键才会继续
cv2.destroyAllWindows()用于关闭所有通过 cv2.imshow() 打开的窗口。通常在程序结束时调用该函数,以确保释放系统资源并关闭所有窗口。特定的几毫秒之内,如果按下任意键,这个函数会返回按键的 ASCII 码值,程序将会继续运行。如果没有键盘输入,返回值为 -1,如果我们设置这个函数的参数为 0,那它将会无限
期的等待键盘输入。它也可以被用来检测特定键是否被按下。
"""
cv2.imshow('Image show', image_grey)
cv2.waitKey(0)
cv2.destroyAllWindows()
可视化结果:

plt.figure()
plt.title('Grayscale Image') # 添加标题
plt.imshow(image_grey, cmap='gray')
可视化结果:

3. 保存图像
cv2.imwrite()是 OpenCV 中用于将图像保存到文件的函数。它能够将处理后的图像存储为指定的文件格式(如 PNG、JPEG 等),并且可以设置压缩质量等参数。
cv2.imwrite(filename, img, params=None)
"""
filename:字符串类型,表示图像要保存的文件路径和名称。需要包含文件的扩展名,如.jpg, .png等,这决定了图像将以何种格式保存
img:要保存的图像,即 NumPy 数组。通常是由cv2.imread()读取处理后的数组数据
params:保存时的可选参数列表。此参数取决于图像的格式,可以用来指定压缩比或图像质量等
"""
三.数字图像基础操作
1. 读取和修改像素值
在 OpenCV 中,可以通过直接访问图像的 NumPy 数组元素来获取特定像素的值。利用cv2.imread读取的图像数据是numpy数组格式,因此可以通过数组索引获取离散像素点的二维位置坐标。
Numpy 是经过优化了的进行快速矩阵运算的扩展库。所以并不不推荐逐个获取像素值并修改,这样会很慢,能利用矩阵运算就不要用循环。
px=image_grey[1,9]
print(px)
# 160
image_grey[1,9] = 255
print(image_grey[1,9])
# 255
彩色图像每个像素由三个通道(BGR:蓝色、绿色、红色)组成,返回的是一个包含三个元素的数组,分别代表该像素的 B、G、R 值。
2. 获取图像属性
在 OpenCV 中,读取图像后,可以获取多种图像属性。这些属性提供了有关图像的尺寸、颜色通道、数据类型等关键信息,帮助我们更好地理解和处理图像。常见的获取图像属性的方法通常涉及图像的 NumPy 数组。
- 图像的形状属性可以通过shape获取,它返回一个包含图像维度的元组。对于彩色图像,返回(height, width, channels) ;对于灰度图像,返回(height, width);
- size属性返回图像中像素的总数,即height*width*channels。对于灰度图像,它仅为height*width;
- dtype属性返回图像中每个像素的元素类型。通常情况下,OpenCV 读取的图像像素类型是 uint8(无符号8位整数),即每个像素值的范围是0-255;
- 对于彩色图像,可以通过shape[-1]获取通道数,即图像的颜色深度。彩色图像通常有 3 个通道(BGR),而灰度图像只有 1 个通道;
- 可以使用min()和max()函数来获取图像中像素值的最小值和最大值,这个在图像对比度分析中非常重要;
- 对于彩色图像,可以使用cv2.split()将图像的 B、G、R 三个通道拆分为单独的数组;
- 位深度表示每个通道中用多少位来表示像素值;
- 在 OpenCV 中,图像的颜色通道默认顺序是 BGR(蓝、绿、红),而不是 RGB(红、绿、蓝)。因此,当你从 OpenCV 读取图像并使用其他库(如matplotlib)显示时,可能需要转换颜色通道;
- 可以检查图像的类型,例如是否是彩色图像、灰度图像等。
height, width, channels = image_brg.shape # 获取图像尺寸
print(f"高度: {height}, 宽度: {width}, 通道数: {channels}")
total_pixels = image_brg.size # 获取图像像素总数
print(f"像素总数: {total_pixels}")
data_type = image_brg.dtype # 图像的数据类型
print(f"图像的数据类型: {data_type}")
channels = image_brg.shape[-1] # 通道数
print(f"图像的通道数: {channels}")
b, g, r = cv2.split(image_brg) # 拆分颜色通道
print(f"蓝色通道形状: {b.shape}, 绿色通道形状: {g.shape}, 红色通道形状: {r.shape}")
bit_depth = image_brg.dtype.itemsize * 8 # 位深度
print(f"图像的位深度: {bit_depth} 位")
if len(image_brg.shape) == 3: # 判断彩色图像还是灰度图
print("这是一个彩色图像")
else:
print("这是一个灰度图像")
image_brg[:,:,-1] = 0 # 令r通道的像素值都为0
cv2.imshow('Image show', image_brg)
cv2.waitKey(0)
cv2.destroyAllWindows()
运行结果:



获取图像属性是图像处理的基础步骤,帮助我们了解图像的尺寸、数据类型、通道数和像素值等信息,为后期更复杂的图像处理做铺垫。
3. 图像填充
图像填充是指在图像的边缘添加额外的像素,以增加图像的尺寸。填充可以在图像的四个边界上增加像素行或列,并可以填充特定的颜色或根据不同的策略来填充这些新增像素。
- 常数填充(cv2.BORDER_CONSTANT):用固定值填充图像边界;
- 复制边缘(cv2.BORDER_REPLICATE):用图像边缘的像素值填充;
- 反射填充(cv2.BORDER_REFLECT):边界元素的镜像;
- 反射101填充(cv2.BORDER_REFLECT_101):与反射填充类似,但是不包含边界元素;
- 包裹填充(cv2.BORDER_WRAP):像素值从对立边界包裹到填充区域。
这些填充函数可以接受的主要参数有:需填充操作的图片、在图像四个边添加的像素行列数和相对应的填充类型。
cons_image = cv2.copyMakeBorder(image_brg, 30, 30, 30, 30, cv2.BORDER_CONSTANT, value=[0, 0, 0])
rep_image = cv2.copyMakeBorder(image_brg, 30, 30, 30, 30, cv2.BORDER_REPLICATE)
ref_image = cv2.copyMakeBorder(image_brg, 30, 30, 30, 30, cv2.BORDER_REFLECT)
p101_image = cv2.copyMakeBorder(image_brg, 30, 30, 30, 30, cv2.BORDER_REFLECT_101)
wrap_image = cv2.copyMakeBorder(image_brg, 50, 50, 50, 50, cv2.BORDER_WRAP)

4. 对应元素运算
涉及一幅或者多幅图像的对应元素运算是逐个像素进行的,类似于矩阵的哈达玛积。图片的对应元素运算常用的应用就是掩膜(mask)操作。

height, width, channels = image_brg.shape
mask = np.ones((height, width, 3), dtype=np.uint8)
center_x, center_y = width // 2, height // 2
mask[center_y-50:center_y+50, center_x-50:center_x+50, :] = 0 # 定义中心 200x200 的掩膜
# 对掩膜区域进行逐元素乘法计算
masked_image = cv2.multiply(image_brg, mask)
5. 基础矩阵运算
矩阵加法,可以使用numpy直接进行数值矩阵相加,但是要保证两个加数的尺寸(长 宽 通道数)一致。
img = image_grey+image_2

图像混合操作,与图像加法类似,区别在于赋予两幅不同的权重:
mixed_img=cv2.addWeighted(image_grey,0.7,image_2,0.3,0)
plt.imshow(mixed_img)
plt.title('Mixed')
plt.axis('off')


937






