公众号:尤而小屋 编辑:Peter 作者:Peter
大家好,我是Peter~
图像基础处理是计算机视觉
和数字图像处理
的第一步,旨在通过简单而有效的操作改善图像质量或提取关键信息。
常见的处理技术包括:
Sobel、Canny
算子提取轮廓)这些方法通常基于像素级操作或卷积运算,能够快速优化图像数据,为后续高级分析(如目标识别、特征匹配)奠定基础。
例如,直方图均衡化可增强低对比度图像的细节,而形态学操作(如腐蚀、膨胀)能优化二值图像中的连通区域。基础处理技术因其高效性和广泛适用性,在工业检测、医学影像、安防监控等领域发挥着重要作用。
本文给大家介绍10个图像处理的基本操作,所有的操作都是基于Numpy
实现,用个人本地图片代码复制即可运行。
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from 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)
可以看到该创建的是一个三维矩阵,表示图像的高度、宽度和颜色通道数
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))
基本原理:图像亮度调整的原理是通过数学运算改变图像像素的强度值(即亮度),从而整体提亮或压暗图像。
其核心是对每个像素的RGB(或灰度)通道值进行线性或非线性变换,同时确保结果在有效范围内(如0~255)。
np.clip()
是NumPy
中的一个重要函数,用于限制数组值的范围,将超出指定范围的值截断到边界值。它在图像处理中常用于防止像素值溢出或归一化数据。
具体用法为:
np.clip(array, min, max, out=None)
# 增加亮度
# 原数组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))
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()
# 方式2
def 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) 表示沿高度(行)和宽度(列)组成的平面旋转,即顺时针旋转)。# 定义裁剪函数
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_img
display(Image.fromarray(crop_image(M, 3, 5)))
RGB(Red, Green, Blue)
是一种颜色模型,通过 红(R)、绿(G)、蓝(B)
三个颜色通道的组合来表示所有颜色。它是数字图像处理中最常用的色彩模式,适用于显示器、摄像头、照片等。
RGB通道的作用:
通过调整这三个通道的强度(0-255),可以混合出 1677万种(256×256×256) 颜色。
RGB 通道的顺序取决于使用的库或工具:
库/工具 | 通道顺序 | 示例( |
---|---|---|
PIL/Pillow、Matplotlib | RGB |
|
OpenCV | BGR |
|
# 提取 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)
图片灰度化是将彩色图像转换为灰度图像的过程,也就是将包含丰富颜色信息的图像转换为仅包含亮度信息的黑白图像(实际上是不同深浅的灰色)。
基本原理:灰度化通过数学转换将彩色图像(通常由红、绿、蓝三个通道组成)转换为单通道的灰度图像,其中每个像素的值代表该点的亮度。
常用的灰度化方法:
(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)的本质:
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)
图像像素化是一种通过减少图像分辨率或合并相邻像素来创建块状、马赛克效果的图像处理技术。它通过将图像分割为若干个小方块(像素块),并用每个方块内像素的平均颜色值替换该区域的所有像素来实现。
简单来说,就是把矢量图形转换成像素点组成的点阵图形,也叫栅格化。
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)是将灰度图像转换为仅包含黑白两色的图像处理技术,通过设定一个阈值将像素分为前景(通常为白色)和背景(通常为黑色)。
二值化基本原理:
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))
图像融合是指根据两种图片的透明度将二者的像素进行叠加求和的过程。
# 读取第二张图
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)
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。