目录
一、前言
二、实验目的
三、实验内容
四、实验过程
一、前言
编程语言:Python,编程软件:vscode或pycharm,必备的第三方库:OpenCV,numpy,matplotlib,os等等。
关于OpenCV,numpy,matplotlib,os等第三方库的下载方式如下:
第一步,按住【Windows】和【R】调出运行界面,输入【cmd】,回车打开命令行。
第二步,输入以下安装命令(可以先升级一下pip指令)。
pip升级指令:
python -m pip install --upgrade pip
opencv库的清华源下载:
pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple
numpy库的清华源下载:
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
matplotlib库的清华源下载:
pip install matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple
os库的清华源下载:
pip install os -i https://pypi.tuna.tsinghua.edu.cn/simple
二、实验目的
1.了解不同图像亮度变换算法;
2.基于演算法原理,以函数形式实现图像亮度变换;
3.根据实验内容2-4要求,调试出所提供图片对应的参数;
三、实验内容
1.任选一张彩色图完成课堂教授内容,并以函数形式封装功能,包含:
- Image Negatives
- Log Transformations
- Power-Law Transformations
- Piecewise-Linear Transformations
- Contrast Stretching
- Gray-Level Slicing
- Bit-Plane Slicing
2.透过gramma correction,尝试不同参数,将下图還原成原亮度。
3.透过gramma correction,尝试不同参数,将下图還原成原亮度。
4.透过Bit-Plane Slicing,尝试获得下图结果。
Hint:考虑移除细节部分
四、实验过程
根据原理写成一个代码文件,命名为【Methods】,具体代码如下:
import cv2
import numpy as npdef Image_Negatives(img):# 将输入图像转换为灰度图像和反转图像的函数gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)dst = 255 - grayreturn dstdef Log(img, c):# 对输入图像进行对数运算并缩放output = c * np.log(1.0 + img)output = np.uint8(output + 0.5)return outputdef Gamma(img, k):# 对图像进行伽马校正img_gamma = np.power(img, k) # 将图像的每个像素值的幂次方为knormImg = 255. * (img_gamma - img_gamma.min()) / (img_gamma.max() - img_gamma.min() + 1e-6) # 对归一化后的图像进行重新线性化img_Gamma = np.uint8(normImg) # 将归一化后的图像转换为0到255之间的无符号整型return img_Gamma # 返回伽马校正后的图像def Contrast_Stretching(img, height, width):rMin = img.min() # 查找图像最低像素值rMax = img.max() # 查找图像最高像素值r1, s1 = rMin, 0 # 初始化r1和s1为最低像素值和0r2, s2 = rMax, 255 # 初始化r2和s2为最高像素值和255img_Stretch = np.empty((width, height), np.uint8) # 创建一个与输入图像相同大小的空矩阵,用于存储扩展对比度后的图像k1 = s1 / r1 # 计算k1,用于将低于最低像素值的像素值映射到0k2 = (s2 - s1) / (r2 - r1) # 计算k2,用于将介于最低像素值和最高像素值之间的像素值映射到0到255的范围k3 = (255 - s2) / (255 - r2) # 计算k3,用于将高于最高像素值的像素值映射到0到255的范围for h in range(height): # 遍历图像的每一行for w in range(width): # 遍历图像的每一列if img[h, w] < r1: # 如果像素值低于最低像素值img_Stretch[h, w] = k1 * img[h, w] # 将像素值映射到0elif r1 <= img[h, w] <= r2: # 如果像素值介于最低像素值和最高像素值之间img_Stretch[h, w] = k2 * (img[h, w] - r1) + s1 # 将像素值映射到0到255的范围elif img[h, w] > r2: # 如果像素值高于最高像素值img_Stretch[h, w] = k3 * (img[h, w] - r2) + s2 # 将像素值映射到0到255的范围return img_Stretch # 返回扩展对比度后的图像def Gray_Level_Slicing(img, a, b, form):img1 = img.copy() # 复制图像矩阵if form == "binary": # 如果形式为二值化img1[(img1[:, :] < a) | (img1[:, :] > b)] = 0 # 将灰度值小于a或大于b的像素点设置为0img1[(img1[:, :] >= a) & (img1[:, :] <= b)] = 255 # 将灰度值大于等于a且小于等于b的像素点设置为255elif form == "grayscale": # 如果形式为灰度化img1[(img1[:, :] >= a) & (img1[:, :] <= b)] = 255 # 将灰度值大于等于a且小于等于b的像素点设置为255return img1 # 返回处理后的图像矩阵def Bit_Plane_Slicing(img, height, width, i):# 将图像的每个像素点转换为8位二进制表示,然后提取第i个比特位,生成一个新的图像。imgBit = np.empty((height, width), dtype = np.uint8)for h in range(height):for w in range(width):x = np.binary_repr(img[h, w], width = 8)x = x[::-1]a = x[i - 1]imgBit[h, w] = int(a)return imgBit
利用上述原理代码实现各种图片变化,执行代码如下:
import cv2
import numpy as np
import matplotlib.pyplot as plt
from Methods import *def image_negatives():# 读取图像并转换为灰度图像img = cv2.imread(r"D:\Image\img1.jpg")img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 调用Image_Negatives函数对图像进行反转处理img_negative = Image_Negatives(img)# 绘制原始图像、灰度图像、反转图像plt.subplot(1, 3, 1), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title('Original img'), plt.axis('off')plt.subplot(1, 3, 2), plt.imshow(img_gray, cmap = 'gray'), plt.title('gray img'), plt.axis('off')plt.subplot(1, 3, 3), plt.imshow(img_negative, cmap = 'gray'), plt.title('dst img'), plt.axis('off')# 调整图像布局并显示图像plt.tight_layout()plt.show()def log():# 读取图像并转换为灰度图像img = cv2.imread(r"D:\Image\img1.jpg", 0)# 调用Log函数对图像进行对数变换output = Log(img, 40)# 绘制原始图像、对数变换图像plt.subplot(1, 2, 1), plt.imshow(img, cmap = 'gray', vmin = 0, vmax = 225), plt.title('Original img'), plt.axis('off')plt.subplot(1, 2, 2), plt.imshow(output,cmap = 'gray', vmin = 0, vmax = 225), plt.title('output img'), plt.axis('off')# 调整图像布局并显示图像plt.tight_layout()plt.show()def gamma():# 读取图像并转换为灰度图像img = cv2.imread(r"D:\Image\img1.jpg", 0)# 定义Gamma值列表gammaList = [0.125, 0.25, 0.5, 1.0, 2.0, 4.0]for k in range(len(gammaList)):# 调用Gamma函数对图像进行Gamma校正imgGamma = Gamma(img, gammaList[k])# 设置子图参数,关闭坐标轴plt.subplot(2, 3, k + 1), plt.axis('off')# 显示图像,设置灰度映射范围plt.imshow(imgGamma, cmap = 'gray', vmin = 0, vmax = 255)# 设置子图标题,插入Gamma值plt.title(f"$\gamma = {gammaList[k]}$")# 调整图像布局并显示图像plt.tight_layout()plt.show()def contrast_stretching():# 读取图像并转换为灰度图像img = cv2.imread(r"D:\Image\img1.jpg", 0)# 获取图像的高度和宽度height, width = img.shape[:2]# 进行对比度拉伸img_stretch = Contrast_Stretching(img, height, width)# 显示原始图像、拉伸图像plt.subplot(1, 2, 1), plt.imshow(img, cmap = 'gray', vmin = 0, vmax = 255), plt.title('Original img'), plt.axis("off")plt.subplot(1, 2, 2), plt.imshow(img_stretch, cmap = 'gray', vmin = 0, vmax = 255), plt.title('Stretch img'), plt.axis("off")# 调整图像布局并显示图像plt.tight_layout()plt.show()def gray_level():# 读取图像并转换为灰度图像img = cv2.imread(r"D:\Image\img1.jpg", 0)# 设置阈值范围a, b = 155, 245# 生成二值图像form = "binary"# 使用灰度切割法生成二值图像img_binary = Gray_Level_Slicing(img, a, b, form)# 生成灰度图像form = "grayscale"# 使用灰度切割法生成灰度图像img_grayscale = Gray_Level_Slicing(img, a, b, form)# 显示原始图像、二值图像和灰度图像plt.subplot(1, 3, 1), plt.imshow(img, cmap = 'gray'), plt.title('Original img'), plt.axis('off')plt.subplot(1, 3, 2), plt.imshow(img_binary, cmap = 'gray'), plt.title('Binary img'), plt.axis('off')plt.subplot(1, 3, 3), plt.imshow(img_grayscale, cmap = 'gray'), plt.title('Grayscale img'), plt.axis('off')# 调整图像布局并显示图像plt.tight_layout()plt.show()def bit_plane():# 读取图像并转换为灰度图像img = cv2.imread(r"D:\Image\img1.jpg", 0)height, width = img.shape[:2]for i in range(9, 0, -1):# 创建子图并设置子图位置和刻度plt.subplot(3, 3, (9 - i) + 1, xticks = [], yticks = [])if i == 9:# 显示原始图像并添加标题plt.imshow(img, cmap = 'gray'), plt.title('Original img')else:# 进行位平面切割并显示切割后的图像,添加标题img_bit = Bit_Plane_Slicing(img, height, width, i)plt.imshow(img_bit, cmap = 'gray'), plt.title(f"{bin((i - 1))}")# 调整图像布局并显示图像plt.tight_layout()plt.show()# 执行相应函数
image_negatives()
log()
gamma()
contrast_stretching()
gray_level()
bit_plane()
接下来是每种方法对图像的变化情况,具体演示如下:
1.(1)图像反转:
(2)对数变换:
(3)伽马变换:
(4)对比度拉伸:
(5)灰度级分层:
(6)比特平面分层:
2.问题二到四的还原亮度代码如下:
import cv2
import numpy as np
import matplotlib.pyplot as plt
from Methods import *def question1():# 读取图像并转换为灰度图像img = cv2.imread(r"D:\Image\HW3-2.jpg", 0)# 定义Gamma值列表gammaList = [0.025, 0.05, 0.075, 0.1, 0.125, 0.15, 0.175, 0.2, 0.225, 0.25, 0.275, 0.3, 0.325, 0.35, 0.375, 0.4]for k in range(len(gammaList)):# 调用Gamma函数对图像进行Gamma校正imgGamma = Gamma(img, gammaList[k])# 设置子图参数,关闭坐标轴plt.subplot(4, 4, k + 1), plt.axis('off')# 显示图像,设置灰度映射范围plt.imshow(imgGamma, cmap = 'gray', vmin = 0, vmax = 255)# 设置子图标题,插入Gamma值plt.title(f"$\gamma = {gammaList[k]}$")# 调整图像布局并显示图像plt.tight_layout()plt.show()def question2():# 读取图像并转换为灰度图像img = cv2.imread(r"D:\Image\HW3-3.jpg", 0)# 定义Gamma值列表gammaList = [1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5]for k in range(len(gammaList)):# 调用Gamma函数对图像进行Gamma校正imgGamma = Gamma(img, gammaList[k])# 设置子图参数,关闭坐标轴plt.subplot(4, 4, k + 1), plt.axis('off')# 显示图像,设置灰度映射范围plt.imshow(imgGamma, cmap = 'gray', vmin = 0, vmax = 255)# 设置子图标题,插入Gamma值plt.title(f"$\gamma = {gammaList[k]}$")# 调整图像布局并显示图像plt.tight_layout()plt.show()def question3():# 读取图像并转换为灰度图像img = cv2.imread(r"D:\Image\HW3-4.jpg", 0)height, width = img.shape[:2]for i in range(9, 0, -1):# 创建子图并设置子图位置和刻度plt.subplot(3, 3, (9 - i) + 1, xticks = [], yticks = [])if i == 9:# 显示原始图像并添加标题plt.imshow(img, cmap = 'gray'), plt.title('Original img')else:# 进行位平面切割并显示切割后的图像,添加标题img_bit = Bit_Plane_Slicing(img, height, width, i)plt.imshow(img_bit, cmap = 'gray'), plt.title(f"{bin((i - 1))}")# 调整图像布局并显示图像plt.tight_layout()plt.show()# 执行相应函数解决相应问题
question1()
question2()
question3()
对于问题二,代码运行效果如下:
伽马变换的伽马值为0.1到0.3之间较为合适,与题目要求图像最为接近。
3.问题三的代码运行效果如下:
伽马变换的伽马值为1.0到2.0之间较为合适,与题目要求图像最为接近。
4.问题四的代码运行效果如下:
从实验结果来看,比特平面分层中的第八层和第七层较为符合题目图像。
都看到最后了,不点个赞吗?