Peter 2025-08-16 15:40 浙江
公众号:尤而小屋编辑:Peter作者:Peter
大家好,我是Peter~
图像基础处理是计算机视觉
和数字图像处理
的第一步,旨在通过简单而有效的操作改善图像质量或提取关键信息。
常见的处理技术包括:
灰度化(将彩色图像转换为单通道灰度图)
二值化(通过阈值分割突出目标区域)
平滑滤波(如高斯模糊去除噪声)
边缘检测(如Sobel、Canny
算子提取轮廓)
几何变换(如旋转、缩放、裁剪)。
这些方法通常基于像素级操作或卷积运算,能够快速优化图像数据,为后续高级分析(如目标识别、特征匹配)奠定基础。
例如,直方图均衡化可增强低对比度图像的细节,而形态学操作(如腐蚀、膨胀)能优化二值图像中的连通区域。基础处理技术因其高效性和广泛适用性,在工业检测、医学影像、安防监控等领域发挥着重要作用。
本文给大家介绍10个图像处理的基本操作,所有的操作都是基于Numpy
实现,用个人本地图片代码复制即可运行。
import numpy as npimport matplotlib.pyplot as plt%matplotlib inlinefrom PIL import Image
图像基础操作
读取图像
首先读取我们需要处理的图像:
img = Image.open("Mona_Lisa.jpg")type(img)PIL.JpegImagePlugin.JpegImageFile
# 创建矩阵M = np.array(img)type(M) # numpy数组
结果显示是:
numpy.ndarray
M[:2]
array([[[ 99, 110, 93], [ 85, 98, 80], [ 80, 95, 76], ..., [ 76, 90, 65], [ 73, 82, 63], [ 92, 96, 82]], [[101, 113, 93], [ 93, 106, 86], [ 78, 93, 72], ..., [ 60, 74, 49], [ 64, 73, 54], [ 58, 62, 48]]], dtype=uint8)
图像基本信息
M.shape
(447, 300, 3)
可以看到该创建的是一个三维矩阵,表示图像的高度、宽度和颜色通道数
height:图像的高度(垂直方向的像素行数)。
width:图像的宽度(水平方向的像素列数)。
channels:颜色通道数(如RGB图像为3,灰度图像为1)。
M.size # 图像大小 447*300*3
402300
显示图像
方式1:通过show函数显示
# img.show() # 方式1:新建窗口打开图片
方式2:通过display函数显示该图像:Image.fromarray()
是图像处理库Pillow (PIL)
中的一个核心方法,其作用是将 NumPy
数组转换为 PIL
的 Image
对象
display(Image.fromarray(M)) # 将numpy数组转成Image对象
或者直接使用img,因为通过读取进行本身就是Image对象中的JpegImageFile类型。
type(img)
PIL.JpegImagePlugin.JpegImageFile
display(img)
缩小图像
def reduce_img_size(img, n): h,w,c = img.shape # h---height w---width c---channel # 将图像缩小n倍;得到缩小后的高度和宽度 new_h = h // n new_w = w // n # 创建一个新矩阵来存储缩小后的图像 new_img = np.zeros((new_h,new_w,c), dtype=img.dtype) # 保持和原图像相同的dtype for i in range(new_h): for j in range(new_w): # 遍历每个像素位置(i,j) new_img[i,j] = img[n*i, n*j] # 新图像的每个像素 (i, j),从原图像中取位置为 (n*i, n*j) 的像素值赋值给它 return new_img
reduced_M = reduce_img_size(M,2) # 缩小为原来一半display(Image.fromarray(reduced_M))
图像亮度调整Image Brightness Adjustment
基本原理
基本原理:图像亮度调整的原理是通过数学运算改变图像像素的强度值(即亮度),从而整体提亮或压暗图像。
其核心是对每个像素的RGB(或灰度)通道值进行线性或非线性变换,同时确保结果在有效范围内(如0~255)。
案例
np.clip()
是NumPy
中的一个重要函数,用于限制数组值的范围,将超出指定范围的值截断到边界值。它在图像处理中常用于防止像素值溢出或归一化数据。
具体用法为:
np.clip(array, min, max, out=None)
array: 输入数组(可以是 NumPy 数组或类似数组的对象)。
min: 最小值,所有比 min 小的值会被替换为 min(可选,默认为 None)。
max: 最大值,所有比 max 大的值会被替换为 max(可选,默认为 None)。
out: 可选参数,指定输出数组(避免创建新数组)。
# 增加亮度# 原数组M 乘以1.5,即扩大50%,然后将值限制在0~255;并转成标准np.uint格式brightened_M = np.clip(M * 1.5, 0, 255).astype(np.uint8)
display(Image.fromarray(brightened_M))
# 降低亮度darkened_M = np.clip(M * 0.5, 0, 255).astype(np.uint8) # 亮度降低50%display(Image.fromarray(darkened_M))
图像翻转Image Flipping
Horizontal水平翻转即沿 垂直轴(Y轴) 翻转图像,相当于对图像的 列(width) 进行逆序排列。
Vertical垂直翻转即沿 水平轴(X轴) 翻转图像,相当于对图像的 行(height) 进行逆序排列
NumPy 的切片操作是 零拷贝(view),速度极快,适合大规模图像处理
# 方式1# 水平翻转(左右镜像)flipped_horizontal = M[:, ::-1, :]# 垂直翻转(上下镜像)flipped_vertical = M[::-1, :, :]# 显示结果plt.figure(figsize=(12, 4))plt.subplot(131), plt.imshow(img), plt.title("Original"), plt.axis('off')plt.subplot(132), plt.imshow(flipped_horizontal), plt.title("Horizontal Flip"), plt.axis('off')plt.subplot(133), plt.imshow(flipped_vertical), plt.title("Vertical Flip"), plt.axis('off')plt.show()
# 方式2def flip_image(image): # 水平翻转函数 flip_image = image[:, ::-1] return flip_image def rotate_image(image): # 垂直翻转函数 rotated_img = Image.fromarray(np.rot90(image, k=n, axes=(1, 0))) return rotated_img
其中np.rot90
为内置的矩阵旋转函数,其中:
k=n
:表示旋转次数(90°*n)
axes=(1, 0)
:指定旋转的轴平面((1, 0) 表示沿高度(行)和宽度(列)组成的平面旋转,即顺时针旋转)。
图像裁剪Image Cropping
# 定义裁剪函数def crop_image(image, crop_ratio, zoom_ratio): """ image:待裁剪的函数,(h,w,c)三个参数 crop_ratio:裁剪比例,控制裁剪范围的中心位置 zoom_ratio:缩放比例,控制裁剪后区域的放大倍数 """ # 获取图像的高度shape[0]、宽度shape[1]和通道数shape[2] # top:从图像顶部向下裁剪 1/crop_ratio 的部分(例如 crop_ratio=4 表示从 25% 高度处开始裁剪) # bottom:在 top 的基础上,放大 zoom_ratio 倍(例如 zoom_ratio=2 表示裁剪区域高度为原图的 2/crop_ratio) top = image.shape[0] // crop_ratio bottom = zoom_ratio * image.shape[0] // crop_ratio left = image.shape[1] // crop_ratio right = zoom_ratio * image.shape[1] // crop_ratio focused_img = image[top:bottom, left:right] return focused_imgdisplay(Image.fromarray(crop_image(M, 3, 5)))
RGB通道
RGB简介
RGB(Red, Green, Blue)
是一种颜色模型,通过 红(R)、绿(G)、蓝(B)
三个颜色通道的组合来表示所有颜色。它是数字图像处理中最常用的色彩模式,适用于显示器、摄像头、照片等。
RGB通道的作用:
红色(R):控制图像中的红色分量。
绿色(G):控制图像中的绿色分量。
蓝色(B):控制图像中的蓝色分量。
通过调整这三个通道的强度(0-255),可以混合出 1677万种(256×256×256) 颜色。
RGB通道的顺序
RGB 通道的顺序取决于使用的库或工具:
库/工具 | 通道顺序 | 示例( |
---|---|---|
PIL/Pillow、Matplotlib | RGB | image[:, :, 0] = 红(R) |
OpenCV | BGR | image[:, :, 0] = 蓝(B) |
提取指定通道
# 提取 R、G、B 通道(注意通道顺序是 R=0, G=1, B=2)# 指定提取单个通道的数据red_channel = M[:, :, 0] # 红色通道(二维数组)green_channel = M[:, :, 1] # 绿色通道blue_channel = M[:, :, 2] # 蓝色通道# 显示单通道(灰度图)plt.figure(figsize=(12, 4))plt.subplot(131), plt.imshow(red_channel, cmap='Reds'), plt.title("Red Channel")plt.subplot(132), plt.imshow(green_channel, cmap='Greens'), plt.title("Green Channel")plt.subplot(133), plt.imshow(blue_channel, cmap='Blues'), plt.title("Blue Channel")plt.show()
另外一种方式:定义提取单个通道的函数
def RGB_image(image,image_color): """ 定义RGB函数:提取图像的红-绿-蓝色的单色通道,并将其他两个通道置为零 通道顺序:R=0, G=1, B=2 """ if image_color == 'R': img_R = image.copy() img_R[:, :, (1, 2)] = 0# 保留 R,G 和 B 置零 return img_R elif image_color == 'G': img_G = image.copy() img_G[:, :, (0, 2)] = 0# 保留 G,R 和 B 置零 return img_G elif image_color == 'B': img_B = image.copy() img_B[:, :, (0, 1)] = 0 # 保留 B,R 和 G 置零 return img_B
M_red = Image.fromarray(RGB_image(M, 'R')) display(M_red)
图片灰度化Image Grayscaling
图片灰度化是将彩色图像转换为灰度图像的过程,也就是将包含丰富颜色信息的图像转换为仅包含亮度信息的黑白图像(实际上是不同深浅的灰色)。
基本原理:灰度化通过数学转换将彩色图像(通常由红、绿、蓝三个通道组成)转换为单通道的灰度图像,其中每个像素的值代表该点的亮度。
常用的灰度化方法:
平均值灰度法:(R+G+B)/3
加权平均灰度法:0.5*R+0.3*G+0.2*B
;OpenCV等库采用
最大值/最小值灰度法:max(R,G,B)
,min(R,G,B)
def grayscale_image(image): """ 定义加权平均灰度函数 输入:图像数组np.array """ grayscale_image = np.dot(image[...,:3], [0.5,0.3,0.2]) # 选取RGB通道,忽略可能的alpha通道;自定义加权系数 grayscale_image = np.clip(grayscale_image,0,255) # 将像素值限制在0-255内,防止计算溢出 grayscale_image = grayscale_image.astype(np.uint8) # # 转换数据类型为np.uint8;标准图像格式 return grayscale_image# 执行灰度转换功能M_gray = grayscale_image(M)display(Image.fromarray(M_gray))
图片添加滤镜Image Filter
图像滤镜(Image Filter)的本质:
给图像添加滤镜,本质上是通过数学运算改变像素的颜色值,从而让图像呈现出特定的视觉效果。
滤镜可以模拟自然现象(如老照片)、艺术风格(如油画),或其他的创意表达。
def apply_sepia(image): """ """ sepia_matrix = np.array([[0.493, 0.769, 0.189], # 红色通道转换系数 [0.349, 0.686, 0.168], # 绿色 [0.282, 0.434, 0.431]]) # 蓝色 sepia_img = image.dot(sepia_matrix.T) # .dot 执行矩阵乘法 sepia_img = np.clip(sepia_img, 0, 255) return sepia_img.astype(np.uint8) M_sepia = Image.fromarray(apply_sepia(M))display(M_sepia)
图片像素化Image Pixelation
图像像素化是一种通过减少图像分辨率或合并相邻像素来创建块状、马赛克效果的图像处理技术。它通过将图像分割为若干个小方块(像素块),并用每个方块内像素的平均颜色值替换该区域的所有像素来实现。
简单来说,就是把矢量图形转换成像素点组成的点阵图形,也叫栅格化。
基本原理
分块处理:将图像划分为N×N的方块网格
颜色平均:计算每个方块内所有像素的颜色平均值
替换像素:用该平均值替换方块内所有像素
效果控制:通过调整方块大小控制像素化程度
案例
def pixelate_image(image,block_size): """ image:待处理图片 block_size:每个像素化方块的大小,比如block_size=10表示10*10的像素 """ # 计算每个维度的所需分块数 num_blocks_x = image.shape[1] // block_size # //表示整除计算 num_blocks_y = image.shape[0] // block_size # 计算每个方块的平均颜色值 block_means = np.zeros((num_blocks_y,num_blocks_x,3), dtype=np.uint8) # 零矩阵用于存储数据 for y in range(num_blocks_y): for x in range(num_blocks_x): # 提取当前方块 block = image[y * block_size:(y+1) * block_size, x * block_size:(x+1) * block_size] # 计算方块内RGB三通道均值 block_mean = np.mean(block, axis=(0,1)) # 将均值从浮点数转为 uint8(0~255的整数) block_means[y,x] = block_mean.astype(np.uint8) # 扩展均值块生成像素化图像:垂直和水平方向使用两次 pixelated_image = np.repeat(np.repeat(block_means, block_size, axis=0), block_size, axis=1) return pixelated_image # 生成的是图像数组M_pixelated = Image.fromarray(pixelate_image(M,block_size=10))display(M_pixelated)
图像二值化Image Binarization
图像二值化(Image Binarization)是将灰度图像转换为仅包含黑白两色的图像处理技术,通过设定一个阈值将像素分为前景(通常为白色)和背景(通常为黑色)。
二值化基本原理:
选择一个灰度值作为分界点(0-255之间)
大于阈值的像素设为白色(255),小于等于阈值的像素设为黑色(0)
def binarize_image(image,threshold): binarize_image = (image > threshold) * 255 binarize_image = binarize_image.astype(np.uint8) # 转成标准格式 return binarize_image # 数组格式M_binarized = Image.fromarray(binarize_image(M,threshold=100)) # 数组---转成display((M_binarized))
图像融合Image Blending
图像融合是指根据两种图片的透明度将二者的像素进行叠加求和的过程。
# 读取第二张图img2 = Image.open("cat.jpg")# 尺寸转换,和第一张图M的相同img2 = img2.resize(M.shape[1::-1])# 创建矩阵M2 = np.array(img2)display(Image.fromarray(M2))
def blend_image(image1,image2,visibility1,visibility2): blend_image = image1 * visibility1 + image2 * visibility2 # 根据两个权重进行叠加 blend_image = blend_image.astype(np.uint8) # 标准格式 return blend_image
blended_image = Image.fromarray(blend_image(M,M2,0.6,0.4))display(blended_image)