一、前言
武汉大学测绘学院数字图像处理课程,要求自己编程实现图像处理。今天的内容主要包括图像的读取与显示,图像融合,图像色调转换。本文采用Python语言实现编译,也可以使用C++的OpenCV,C#或者matlab语言编写。咱们废话不多说,直接开始讲解。
二、图像读取与显示
要求:
- 编写读取图像文件(彩色图像、灰度图像):
- 图像文件的读写;
- 读取图像文件中某位置(例如(100,100))像素的灰度值。
- 图像显示与保存。
为了保证程序的通用性,我选择了把这些功能封装成函数,方便不同脚本相互调用和后续的使用。用python处理图像需要用到一个库叫做pillow,解释器没有安装这个库的话可以通过以下命令安装:
pip install pillow
读取图像的函数
from PIL import Image
#读取图像文件
def read_image(image_path):
return Image.open(image_path)
获取指定位置灰度值的函数
#读取指定位置的像素灰度值
def get_pixel_value(image,position):
if image.mode=='RGB':
#如果是彩色图像,转换为灰度图像
gray_image=image.convert('L')
else:
gray_image=image
return gray_image.getpixel(position)
显示图像和保存图像的函数:
#显示图像
def show_image(image):
image.show()
#保存图像
def save_image(image,save_path):
image.save(save_path)
函数写完之后可以简单写一个主函数来测试
def main():
image_path='编程1扩展-1.jpg'
image=read_image(image_path)
#获取指定位置的灰度值
postion=(100,100)
pixel_value=get_pixel_value(image,postion)
print(f"位置{postion}的灰度值是:{pixel_value}")
#显示图像
show_image(image)
if __name__=="__main__":
main()
注意最后两行,它的作用是当脚本没有被其它脚本引用直接运行时,执行main函数,而当脚本被其它脚步引用时,不执行。
三、图像融合
要求:
- 将两幅RGB图像(编程1扩展-1.jpg、编程1扩展-2.jpg)变换至HSI模型中,用第2幅图像的I分量代替第1幅图像的I分量,得到一幅新的图像;
- 反变换至RGB模型,就得到一幅“清晰度高、细节丰富、噪声表现及颜色还原度好”的彩色图像;
- 显示与保存新图像。
所用到的知识点及公式:
1.RGB模型
RGB模型采用CIE规定的三基色成表色系统。自然界 的任一颜色都可通过这三种基色按不同比例混合而成。 由于RGB模型将三基色同时加入以产生新的颜色,所以, 它是一个加色系统。 设颜色传感器把数字图像上的一个像素编码成(R,G, B),每个分量量化范围为 [0,255]共256级。因此, RGB模型可以表示2 8×2 8×2 8=224=256×256×256=16 777 216≈1670万种颜色。这足以表示自然界的任一颜色,故 又称其为24位真彩色。
R、G、B分别代表红、绿、蓝
2.HSI模型
HSI模型是美国色彩学家孟塞尔(H.A.Munseu)于1915年 提出的,它反映了人的视觉系统感知彩色的方式,在艺术上 经常使用HSI模型。 HSI模型中,H表示色调(Hue),S表示饱和度(Saturation), I表示亮度(Intensity,对应成像亮度和图像灰度)。
色调H(Hue): 与光波的波长有关,它表示人的感官对不同颜色的感受,如红色、绿色、蓝色等,它也可表示一定范 围的颜色,如暖色、冷色等。
饱和度S(Saturation): 表示颜色的纯度,纯光谱色是完全饱和的,加入白光会稀释饱和度。饱和度越大,颜色看起 来就会越鲜艳,反之亦然。
强度I(Intensity): 对应成像亮度和图像灰度,是颜色的明亮程度。
色相由角度表示,它反映了该彩色最接近什么样的光谱波长。 一般假定0°表示的颜色为红色, 120°为绿色, 240°为蓝色。 0°到240°的色相覆盖了所有可见光谱的彩色,在240° 到300°之间为人眼可见的非光谱色(紫色)。
3.RGB模型与HSI模型的相互转换
HSI模型与RGB模型之间可按下述方法相互转换。
(1) RGB转换到HSI
首先,对取值范围为[0,255] 的R、G、B值进行归一化处理,得到3个[0,1]范围内的 r、g、b值:
则对应HSI模型中的H、S、I分量的计算公式为:
(2)HSI转换到RGB
(3)完整代码
import numpy as np
from PIL import Image
def rgb_to_hsi(rgb_image):
epsilon = 1e-10 # 防止除以零的很小值
rgb_array = np.array(rgb_image) / 255.0
# 提取 R、G 和 B 通道
R = rgb_array[:, :, 0]
G = rgb_array[:, :, 1]
B = rgb_array[:, :, 2]
# 初始化 H、S 和 I
H = np.zeros_like(R)
S = np.zeros_like(R)
I = (R + G + B) / 3
# 计算 H、S 和 I 分量
min_of_RGB = np.min(rgb_array, axis=2)
denominator = R + G + B
denominator[denominator < epsilon] = epsilon # 避免除以非常小的值
S[denominator > epsilon] = 1 - 3 * min_of_RGB[denominator > epsilon] / denominator[denominator > epsilon]
return H, S, I
def hsi_to_rgb(H, S, I):
H = H * 2 * np.pi
R, G, B = np.zeros(H.shape), np.zeros(H.shape), np.zeros(H.shape)
for i in range(H.shape[0]):
for j in range(H.shape[1]):
h = H[i, j]
s = S[i, j]
i_val = I[i, j]
if s == 0:
R[i, j] = G[i, j] = B[i, j] = i_val
else:
h = h * 3
h = h - np.floor(h)
x = i_val * (1 - s)
y = i_val * (1 + s * np.cos(h * np.pi / 3) / np.cos((1 - h * np.pi / 3)))
if h < 1:
R[i, j] = i_val + (y - i_val) * h
G[i, j] = x
B[i, j] = i_val + (y - i_val) * (1 - h)
elif h < 2:
R[i, j] = x
G[i, j] = i_val + (y - i_val) * (h - 1)
B[i, j] = i_val + (y - i_val) * (2 - h)
else:
R[i, j] = i_val + (y - i_val) * (3 - h)
G[i, j] = x
B[i, j] = i_val + (y - i_val) * (h - 2)
R = np.clip(R * 255, 0, 255).astype(np.uint8)
G = np.clip(G * 255, 0, 255).astype(np.uint8)
B = np.clip(B * 255, 0, 255).astype(np.uint8)
return np.stack([R, G, B], axis=2)
def process_images(image_path1, image_path2, save_path):
# 读取图像
img1 = Image.open(image_path1).convert('RGB')
img2 = Image.open(image_path2).convert('RGB')
# 转换到 HSI
H1, S1, I1 = rgb_to_hsi(img1)
H2, S2, I2 = rgb_to_hsi(img2)
# 替换 I 分量
new_I = I2
# 转换回 RGB
new_rgb_array = hsi_to_rgb(H1, S1, new_I)
new_img = Image.fromarray(new_rgb_array)
# 显示和保存新图像
new_img.show()
new_img.save(save_path)
print(f"新图像已保存到 {save_path}")
(4)转换效果
原图1
原图2
融合图像:
四、图像色调变换
参考了以下文章:
要改变图片的色调,核心就是改变HSI模型里面的H值,H值为0时,即为红色,H值为120时为绿色,H值为240时为蓝色。实现代码如下,用到了colorsys库,没有安装需要提前安装:
import colorsys
from PIL import Image
def change_h(image_path,target_hue):
# 读入图片,转化为 RGB 色值
image = Image.open(image_path).convert('RGB')
# 将 RGB 色值分离
image.load()
r, g, b = image.split()
result_r, result_g, result_b = [], [], []
# 依次对每个像素点进行处理
for pixel_r, pixel_g, pixel_b in zip(r.getdata(), g.getdata(), b.getdata()):
# 转为 HSV 色值
h, s, v = colorsys.rgb_to_hsv(pixel_r / 255., pixel_b / 255., pixel_g / 255.)
#转回R,G,B
rgb = colorsys.hsv_to_rgb(target_hue, s, v)
pixel_r, pixel_g, pixel_b = [int(x * 255.) for x in rgb]
# 每个像素点结果保存
result_r.append(pixel_r)
result_g.append(pixel_g)
result_b.append(pixel_b)
r.putdata(result_r)
g.putdata(result_g)
b.putdata(result_b)
# 合并图片
image = Image.merge('RGB', (r, g, b))
return image
通过以上算法,可以随意改变图片的色调,挺好玩的,效果如下:
五、总结:
本次的内容就分享到这里了,感兴趣的同学可以点个关注,后续会持续分享更多优质的内容哦。
大家需要完整资源的,可以免费下载哦,内容包括所有源代码和测试所用的图片以及相关知识点的PPT,下载链接如下: