实验1:图像增强
一 实验目的和要求
掌握Array矩阵和数组的创建及应用方法。
掌握OpenCV-Python中图像的数字表达方法。
掌握图像读写和显示方法。
掌握图像的几何变换方法及图像间运算方法。
二 实验环境
(1)操作系统环境:Windows
(2)开发工具:Pycharm.
(3)其它辅助工具:浏览器
三 实验内容
\1. 题目1内容
(1)分析及设计思路:
该题是进行按照指定的规则创建三维数组,并进行显示他们的维数和内容,可以通过两种方式去实现,第一种是直接通过定义如n1=np.array[[[1,2,3]],
[4,5,6]],第二种则是可以通过函数相互配合方式实现.
(2)解答及源码
import numpy as np
#创建1×2×3的数组
print(“1×2×3的数组:”)
n1=np.array([[[1,2,3],[4,5,6]]])
#n1=np.arange(6).reshape(1,2,3)
print(n1)
print(n1.shape)
print(15*“*”)
print(“2×3×1的数组:”)
n2=np.array([[[1],[2],[3]],[[4],[5],[6]]])
# n2=np.arange(6).reshape(2,3,1)
print(n2)
print(n2.shape)
print(15*“*”)
print(“3×1×2的数组:”)
n3=np.array([[[1,2]],[[3,4]],[[5,6]]])
# n3=np.arange(6).reshape(3,1,2)
print(n3)
print(n3.shape)
print(15*“*”)
print(“1×3×2的数组:”)
n4=np.array([[[1,2],[3,4],[5,6]]])
# n4=np.arange(6).reshape(1,3,2)
print(n4)
print(n4.shape)
print(15*“*”)
print(“3×2×1的数组:”)
n5=np.array([[[1],[2]],[[3],[4]],[[5],[6]]])
# n5=np.arange(6).reshape(3,2,1)
print(n5)
print(n5.shape)
print(15*“*”)
print(“2×1×3的数组:”)
n6=np.array([[[1,2,3,]],[[4,5,6]]])
# n6=np.arange(6).reshape(2,1,3)
print(n6)
print(n6.shape)
(3)实验结果及分析
题目1结果是
1×2×3的数组:
[[[1 2 3]
[4 5 6]]]
(1, 2, 3)
2×3×1的数组:
[[[1]
[2]
[3]]
[[4]
[5]
[6]]]
(2, 3, 1)
3×1×2的数组:
[[[1 2]]
[[3 4]]
[[5 6]]]
(3, 1, 2)
1×3×2的数组:
[[[1 2]
[3 4]
[5 6]]]
(1, 3, 2)
3×2×1的数组:
[[[1]
[2]]
[[3]
[4]]
[[5]
[6]]]
(3, 2, 1)
2×1×3的数组:
[[[1 2 3]]
[[4 5 6]]]
(2, 1, 3)
对其以上题目的结果进行一个分析,三维数组的每个维数是怎么进行代表的,其中就要引出一个关于轴的概念,对其其中的看法首先包含两个括号及以上的话,就是代表的三维数组,(2,1,3)对其进行解释:代表的是两块数据块,一块里面是1行3列,那么如果要从数据括号里面要怎么看.1.首先确定是三维数组之后,数第二个括号有几个,例如上面的蓝色括号即为第二个括号,有两个就代表的是有两块数据块,2.其次确认蓝色里面所包含的第三个括号(黄色),即确认它一块中的几行几列,有一个括号代表的是一行,括号里面包含几个数据代表几列,最简单看的方法,蓝色括号里面所包含的黄色括号有几个代表几行,黄色括号里面几个数据代表几列
例如n4[[[1,3,5]],[[2,4,6]]],第二个括号有两块,第三个括号里面包含的是3个数据,没有多余的括号,则是1行3列
例如n3[[[1,3,5],[2,4,6]]],第二个括号有一块,则看第二个括号里面包含第三个括号的情况,有两个黄色括号,一个黄色括号包含3个数据为2行3列
2.题目2内容
(1)分析及设计思路
该问题主要是创建一个255255的掩膜矩阵,其中在中心处进行创建一个100100的矩形区域值为1,其余为0,那么就可以用numpy数组当中的zeros创建一个255—*255的矩阵,然后再去设计中心矩阵开始的地方,去规定它的范围是多少,然后再把中心矩阵的数值设置为1,然后用Matplotlib显示数组
(2)解答及源码
包括解答阐述、公式运用,编码实现等。…
import numpy as np # 导入NumPy库,用于数组操作
import matplotlib.pyplot as plt # 导入Matplotlib库,用于可视化
# 创建一个全零的255x255数组(掩膜矩阵)
mask = np.zeros((255, 255)) # 创建一个名为 mask 的 255x255 数组,初始值都是0
# 中心矩形的起始和结束坐标
start_x = (255 - 100) // 2 # 计算矩形区域的起始x坐标
end_x = start_x + 100 # 计算矩形区域的结束x坐标
start_y = (255 - 100) // 2 # 计算矩形区域的起始y坐标
end_y = start_y + 100 # 计算矩形区域的结束y坐标
# 在中心矩形区域设置值为1
mask[start_x:end_x, start_y:end_y] = 1 # 将矩形区域的值设为1,其他区域的值保持为0
# 使用Matplotlib显示数组
plt.imshow(mask, cmap=‘gray’) # 使用imshow函数显示数组,cmap参数指定颜色映射(灰度图)
plt.title(‘第二题’, fontproperties=‘SimHei’)
plt.show() # 显示图像
(3)实验结果及分析
题目2结果如下,创建了255255的掩膜矩阵,中心创建的是100100的矩形区域,将其图像通过Matplotlib以gray的颜色映射如图下所示
题目2如图1所示。
图1 题2图
3.题目3内容
(1)分析及设计思路
包括问题分析、设计思路或方案、注意事项等。
要进行创建较大的一维整数组的话,那么就需要用到arange这一个函数去进行依次的创建,让其变为10*10的二维数组的话,可以使用reshape,直接对其数组进行变维。
(2)解答及源码
#题目要求
#创建包含1~100的一维整数数组,然后使用reshape()方法把它变成10×10的二维数组,显示原数组和变维后的数组
import numpy as np
# 创建包含1到100的一维整数数组
ori_array = np.arange(1, 101)
# 使用reshape()方法将其变为10x10的二维数组
res_array = ori_array.reshape(10, 10)
# 显示原数组
print(“原来的数组为:”)
print(ori_array)
print()
# 显示变维后的数组
print(“变维之后的数组为:”)
print(res_array)
(3)实验结果及分析
原来的数组为:
[ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
91 92 93 94 95 96 97 98 99 100]
变维之后的数组为:
[[ 1 2 3 4 5 6 7 8 9 10]
[ 11 12 13 14 15 16 17 18 19 20]
[ 21 22 23 24 25 26 27 28 29 30]
[ 31 32 33 34 35 36 37 38 39 40]
[ 41 42 43 44 45 46 47 48 49 50]
[ 51 52 53 54 55 56 57 58 59 60]
[ 61 62 63 64 65 66 67 68 69 70]
[ 71 72 73 74 75 76 77 78 79 80]
[ 81 82 83 84 85 86 87 88 89 90]
[ 91 92 93 94 95 96 97 98 99 100]]
4.题目4内容
(1)分析及设计思路
对其题目中要进行实现数组的相互拼接的作用,则要用到numpy库中的关于拼接相关方面的函数如hstack,vstack, dstack。
(2)解答及源码
#问题描述
#创建2个1×2的数组,然后分别把他们按水平、垂直和深度方向进行拼接,显示原数组和拼接后的数组
import numpy as np
n1=np.array([[1,2]])
n2=np.array([[3,4]])
#水平拼接
result_1=np.hstack((n1,n2))
#垂直拼接
result_2=np.vstack((n1,n2))
#纵向拼接
result_3=np.dstack((n1,n2))
print(“原数组为:”)
print(n1,n2)
print(“水平拼接后的数组:”)
print(result_1)
print(“垂直拼接后的数组:”)
print(result_2)
print(“纵向拼接后的数组:”)
print(result_3)
(3)实验结果及分析
题目4的结果是:
原数组为:
[[1 2]] [[3 4]]
水平拼接后的数组:
[[1 2 3 4]]
垂直拼接后的数组:
[[1 2]
[3 4]]
纵向拼接后的数组:
[[[1 3]
[2 4]]]
\5. 题目5内容
(1)分析及设计思路
对其题目当中的创建一个三维数组,然后对其按照水平,垂直和深度方向进行等分,那么就可以考虑用到numpy库当中的hsplit,vsplit,dsplit,但当其使用的时候要对其进行判断,它是要被分成几个部分,例如创建了一个234的三维数组,它是一个两个大块的三维数组,一块中包含了三行四列,对其进行水平切割的时候,那么就会切割成3个部分,所以在对其np.hsplit(original_array, 3)的时候,第二个参数就要写对应被分成了多少个部分。
(2)解答及源码
import numpy as np
# 创建一个2x3x4的数组
original_array = np.arange(24).reshape(2, 3, 4)
print(“原始数组:”)
print(original_array)
print(“================================”)
# 使用 hsplit 沿水平方向等分成三部分
horizontal_split = np.hsplit(original_array, 3)#按照水平分割的话会将其进行分为三个部分
print(“\n水平分割后的数组:”)
#将其水平分割的子数组按照索引进行打印出来
for i,sub_array in enumerate(horizontal_split):
print(f"第{i+1}部分的子数组:")
print(sub_array)
print(“================================”)
print(“垂直分割后的数组”)
vertical_split = np.vsplit(original_array,2)
#将其垂直分割的子数组按照索引进行打印出来
for i,sub_array in enumerate(vertical_split):
print(f"第{i+1}部分的子数组:")
print(sub_array)
print(“================================”)
print(“深度方向分割后的数组”)
depth_split = np.dsplit(original_array,4)
#将其纵向分割的子数组按照索引进行打印出来
for i,sub_array in enumerate(depth_split):
print(f"第{i+1}部分的子数组:")
print(sub_array)
print(“================================”)
(3)实验结果及分析
题目5结果是
原始数组:
[[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]]
================================
水平分割后的数组:
第1部分的子数组:
[[[ 0 1 2 3]]
[[12 13 14 15]]]
第2部分的子数组:
[[[ 4 5 6 7]]
[[16 17 18 19]]]
第3部分的子数组:
[[[ 8 9 10 11]]
[[20 21 22 23]]]
================================
垂直分割后的数组
第1部分的子数组:
[[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]]
第2部分的子数组:
[[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]]
================================
深度方向分割后的数组
第1部分的子数组:
[[[ 0]
[ 4]
[ 8]]
[[12]
[16]
[20]]]
第2部分的子数组:
[[[ 1]
[ 5]
[ 9]]
[[13]
[17]
[21]]]
第3部分的子数组:
[[[ 2]
[ 6]
[10]]
[[14]
[18]
[22]]]
第4部分的子数组:
[[[ 3]
[ 7]
[11]]
[[15]
[19]
[23]]]
================================
\6. 题目6内容
(1)分析及设计思路
由题目问题可以得知,这题主要是对其二维数组切片的一个考察,其中还是先按照题2构建出一个掩膜矩阵,然后再对其进行一个切片的操作,其中要注意的点是,确定好所开始和终止的行列。
(2)解答及源码
import numpy as np
import matplotlib.pyplot as plt
# 创建一个全零的255x255矩阵
mask = np.zeros((255, 255))
# 获取中心100x100区域的左上角和右下角坐标
center_x1, center_x2 = 78, 178 # 255-100 = 155,所以左上角从78开始
center_y1, center_y2 = 78, 178 # 255-100 = 155
# 在中心100x100区域设置值为1
#从 center_x1 行到 center_x2 行,
# 从 center_y1 列到 center_y2 列的所有元素的值都设置为1
mask[center_x1:center_x2+1, center_y1:center_y2+1] = 1
# 使用切片获取中心100x100矩阵
center_100x100 =mask[center_x1:center_x2+1, center_y1:center_y2+1]
# 显示图像,确保1代表白色
plt.imshow(center_100x100, cmap=‘gray’, vmin=0, vmax=1)
plt.title(‘第6题’,fontproperties=‘SimHei’)
plt.show()
(3)实验结果及分析
其中打印出来的结果如下都为1
[[1. 1. 1. … 1. 1. 1.]
[1. 1. 1. … 1. 1. 1.]
[1. 1. 1. … 1. 1. 1.]
…
[1. 1. 1. … 1. 1. 1.]
[1. 1. 1. … 1. 1. 1.]
[1. 1. 1. … 1. 1. 1.]]
题目6结果如图2所示。
图2 题6图
\7. 题目7内容
(1)分析及设计思路
对其题中要对其图像进行一个组合逻辑运算,将其基本逻辑运算进行不同的组合,其中主要是对其运用cv2下的bitwise_xor/not/or/and,进行组合成相应的逻辑,并组合成相应的功能;再通过matplotlib.pyplot库下的subplot函数将其组合在一起并进行显示,值得注意的是,还可以通过对其边框进行一个添加的操作。
(2)解答及源码
import cv2
import matplotlib.pyplot as plt
#对其图片进行读入
A=cv2.imread(‘pic020201A.tif’)
B=cv2.imread(‘pic020201B.tif’)
#定义一个图像的显示,当按下任何键的时候图片就自行关闭
def cv_show(name,img):
cv2.imshow(name,img) #第一个参数是指定一个名字,第二个参数是对其指定显示的图像
# 等待时间,毫秒级,0表示任意键终止
cv2.waitKey(0) # 0代表的是任意键就会进行终止,如果里面填入数字的话就会延缓好多秒之后结束
cv2.destroyAllWindows()
not_A=cv2.bitwise_not(A)
not_B=cv2.bitwise_not(B)
A_and_notB=cv2.bitwise_and(A,not_B)
notA_and_B=cv2.bitwise_and(not_A,B)
notA_and_notB=cv2.bitwise_and(not_A,not_B)
A_and_B=cv2.bitwise_and(A,B)
not_A_and_B2=cv2.bitwise_not(A_and_B)
# cv_show(‘1’,A_and_notB)
# cv_show(‘2’,notA_and_B)
# cv_show(‘3’,notA_and_notB)
# cv_show(‘4’,not_A_and_B2)
A_or_notB=cv2.bitwise_or(A,not_B)
notA_or_B=cv2.bitwise_or(not_A,B)
notA_or_notB=cv2.bitwise_or(not_A,not_B)
A_or_B=cv2.bitwise_or(A,B)
not_A_or_B=cv2.bitwise_not(A_or_B)
# cv_show(‘5’,A_or_notB)
# cv_show(‘6’,notA_or_B)
# cv_show(‘7’,notA_or_notB)
# cv_show(‘8’,not_A_or_B)
A_xor_notB=cv2.bitwise_xor(A,not_B)
notA_xor_B=cv2.bitwise_xor(not_A,B)
notA_xor_notB=cv2.bitwise_xor(not_A,not_B)
A_xor_B=cv2.bitwise_xor(A,B)
not_A_xor_B=cv2.bitwise_not(A_xor_B)
# cv_show(‘9’,A_xor_notB)
# cv_show(‘10’,notA_xor_B)
# cv_show(‘11’,notA_xor_notB)
# cv_show(‘12’,not_A_xor_B)
#将其进行合并一下
titles=[‘1’,‘2’,‘3’,‘4’,‘5’,‘6’,‘7’,‘8’,‘9’,‘10’,‘11’,‘12’]
images=[A_or_notB,notA_or_B,notA_or_notB,not_A_or_B,
A_and_notB,notA_and_B,notA_and_notB,not_A_and_B2
,A_xor_notB,notA_xor_B,notA_xor_notB,not_A_xor_B]
# 创建一个4x3的子图布局,将12张图像显示在不同的子图中
#指定了新创建的图像窗口的大小。这里的参数是一个元组,包含两个值,分别表示图像窗口的宽度和高度。
plt.figure(figsize=(12, 9))
# 显示所有图像
for i in range(12):
img = cv2.cvtColor(images[i], cv2.COLOR_BGR2RGB) # 将图像从BGR格式转换为RGB格式
border_color = [0, 0, 0] # 黑色边框的颜色
border_width = 10 # 边框宽度
# 在图像周围添加边框
img_with_border = cv2.copyMakeBorder(img, border_width, border_width, border_width, border_width,
cv2.BORDER_CONSTANT, value=border_color)
plt.subplot(3, 4, i + 1)
plt.imshow(img_with_border)
plt.title(titles[i])
plt.axis(‘off’) # 不显示坐标轴
# 调整子图布局
plt.tight_layout()
plt.show()
(3)实验结果及分析
题目7结果如图3所示。
图3 第7图题
\8. 题目8内容
(1)分析及设计思路
该题目是将其一个彩色图像进行转换为一幅灰度图像并进行显示出结果,而且要按照一个gray的转换公式里面的RGB通道进行展示,所以要将运用一个cv2下的cv2.cvtColor函数去进行一个图像颜色空间的转换,其中它的基本语法是output_image = cv2.cvtColor(input_image, color_conversion_code),对其第二个参数的取值就要取cv2.COLOR_BGR2GRAY:将BGR图像转换为灰度图像。然后将其打印显示出来
(2)解答及源码
包
import cv2
# 打开彩色图像
color_image = cv2.imread(‘cat.jpg’)
# 转换为灰度图像
def rgb_to_gray(pixel):
gray = 0.2125 * pixel[2] + 0.7154 * pixel[1] + 0.0721 * pixel[0]
return int(gray)
# 使用亮度转换公式将彩色图像转换为灰度图像
gray_image = cv2.cvtColor(color_image, cv2.COLOR_BGR2GRAY)
# 保存灰度图像
cv2.imwrite(‘output_gray_image.jpg’, gray_image)
# 显示灰度图像
def cv_show(name,img):
cv2.imshow(‘name’, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv_show(‘灰度图’,gray_image)
(3)实验结果及分析
结果如图4所示:主要是定义了一个函数 rgb_to_gray(pixel),用于将彩色像素值转换为灰度值。这个函数使用了一个常见的灰度转换公式,将红色、绿色和蓝色通道的值加权平均,以计算灰度值。
使用OpenCV的 cv2.cvtColor() 函数将 color_image 转换为灰度图像,并将结果存储在变量 gray_image 中。cv2.COLOR_BGR2GRAY 是转换的标志,它告诉函数将图像从BGR(蓝绿红)彩色模式转换为灰度模式。再而把图片进行保存下来,进行显示。
\9. 题目9内容
(1)分析及设计思路
该题主要是对其通过自己编写一个rgbRotate(f,angle)的函数实现将彩色图像f以图像中心为原点进行一个逆时针的旋转angle角度,其中可以通过先是获取原来图像的高宽的信息,计算到旋转之后图像的大小和中心点的坐标,并进行计算旋转的弧度。然后创建一个新的图像,进行执行逆时针旋转的操作其中是将循环遍历新图像中的每一个像素,计算其在原始图像中对应坐标,并再对点检查是否在原图像范围内,将原图像上的像素赋值给新图像。最后将其显示出来
(2)解答及源码
import numpy as np
import cv2
def rgbRotate(f, angle):#f表示对其接受一个图像,angle表示对其进行旋转的角度
# 获取原图像的高度和宽度
height, width, channels = f.shape
# 计算旋转后图像的大小和中心点坐标
center_x = width // 2
center_y = height // 2
new_width = width
new_height = height
# 计算弧度
radians = np.radians(angle)
# 创建新图像
#np.zeros_like() 函数创建一个与输入图像 f 具有相同维度的全零NumPy数组,用于存储旋转后的图像。
g = np.zeros_like(f)
# 执行逆时针旋转
#这个循环遍历新图像的每个像素,计算其在原始图像中的对应坐标 (x_orig, y_orig)。这里使用了旋转矩阵的变换公式来计算新坐标
for y in range(new_height):
for x in range(new_width):
# 计算原图像上对应位置的坐标
x_orig = int((x - center_x) * np.cos(radians) - (y - center_y) * np.sin(radians) + center_x)
y_orig = int((x - center_x) * np.sin(radians) + (y - center_y) * np.cos(radians) + center_y)
# 检查是否在原图像范围内
if x_orig >= 0 and x_orig < width and y_orig >= 0 and y_orig < height:
# 将原图像上的像素值赋值给新图像
g[y, x] = f[y_orig, x_orig]
return g
# 读取彩色图像
color_image = cv2.imread(‘cat.jpg’)
# 旋转图像
rotated_image = rgbRotate(color_image, 45)
# 显示旋转后的图像
cv2.imshow(‘Rotated Image’, rotated_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
(3)实验结果及分析
题目9结果如图所示:
\10. 题目10内容
(1)分析及设计思路
要对其图片进行分析橙子的运动方向即要的对其进行运动检测:使用两个相邻的图像帧,可以计算它们之间的差异,以检测运动。最常见的方法是使用光流或帧间差分,这里我采用的是处理图像并计算光流,以确定物体在图像中的运动方向。其中主要是在对其计算光流的地方,使cv2.calcOpticalFlowFarneback计算光流,然后再计算其中的平均光流方向,计算运动方向的角度,使用角度来确定运动最终的运动方向,通过遍历avg_flow_x和avg_flow_y的像素值,判断物体的运动方向。
(2)解答及源码
import cv2
import numpy as np
# 读取三张图像,这里假设图像文件分别为 “1_move.jpg”、“2_move.jpg” 和 “3_move.jpg”
fram1 = cv2.imread(“1_move.jpg”)
fram2 = cv2.imread(“2_move.jpg”)
fram3 = cv2.imread(“3_move.jpg”)
# 将图像转换为灰度图像,以便后续的光流计算
gray_1 = cv2.cvtColor(fram1, cv2.COLOR_BGR2GRAY)
gray_2 = cv2.cvtColor(fram2, cv2.COLOR_BGR2GRAY)
gray_3 = cv2.cvtColor(fram3, cv2.COLOR_BGR2GRAY)
# 使用cv2.calcOpticalFlowFarneback计算光流
# flow12表示从第一帧到第二帧的光流
flow12 = cv2.calcOpticalFlowFarneback(gray_1, gray_2, None, 0.8, 10, 200, 5, 7, 10, 0)
# flow23表示从第二帧到第三帧的光流
flow23 = cv2.calcOpticalFlowFarneback(gray_2, gray_3, None, 0.8, 10, 200, 5, 7, 10, 0)
# 计算平均光流方向,将两帧之间的光流取平均
avg_flow = (flow12 + flow23) / 2
avg_flow_x = avg_flow[:, :, 0] # 平均光流的水平分量
avg_flow_y = avg_flow[:, :, 1] # 平均光流的垂直分量
# 计算运动方向的角度,将光流向量的y分量除以x分量,并将弧度转换为角度
angle = np.arctan2(avg_flow_y, avg_flow_x) * 180 / np.pi
# 用于存储每个像素位置的运动方向信息的列表
directions = []
# 遍历图像中的每个像素位置
for y in range(avg_flow_x.shape[0]):
for x in range(avg_flow_x.shape[1]):
if avg_flow_x[y, x] > 0:
# 如果水平分量为正,表示物体向右移动
directions.append(“向右”)
elif avg_flow_x[y, x] < 0:
# 如果水平分量为负,表示物体向左移动
directions.append(“向左”)
else:
# 否则,表示物体在这个位置没有水平移动
directions.append(“静止”)
# 统计每个运动方向的出现次数,以确定最终的整体运动方向
direction_counts = dict(zip(*np.unique(directions, return_counts=True)))
# 找到出现最多次的方向,即整体的运动方向
most_common_direction = max(direction_counts, key=direction_counts.get)
# 打印出物体的最终运动方向
print(f"物体的最终运动方向为:{most_common_direction}")
(3)实验结果及分析
题目10结果是:物体的最终运动方向为:向右
通过用光流对其图像进行一系列的计算可以得出确定物体的最终方向是向右,那么对其提出疑问,当其改变图片的添加顺序,让最终的结果是一个向左的运动是否还可以得出相同的结果呢?答案经过测试,也是可以得出交换图片顺序之后,运动方向向左的结论。
\11. 题目11内容
(1)分析及设计思路
该题目是将光照不均的图像进行正常化的显示出来,其中显示将其光照不均的素材进行读取其中的文档图像和背景图像,再将文档图像除以背景图像,读入的图像需将其像素类型转换为0~1之间的浮点数才能进行除法运算。然后对其进行除法运算,将文档图像除以背景图像对应的像素值,其中可以通过遍历完成,最后可以通过调整一下图片的显示大小,再将图片显示出来即可。
(2)解答及源码
import cv2
import numpy as np
# 读取文档图像和背景图像
document_image = cv2.imread(‘document.jpg’).astype(np.float32) / 255.0
light_image = cv2.imread(‘light.jpg’).astype(np.float32) / 255.0
# 确保图像大小相同
document_image = cv2.resize(document_image, (light_image.shape[1], light_image.shape[0]))
# 处理除以零的情况
light_image[light_image == 0] = 1e-10 # 将零值替换为一个极小的非零数
# 进行图像点除法
result_image = document_image / light_image
# 调整结果图像的大小
scale_factor = 0.2 # 缩小为原来的1/5,让其图像更加显示出来
result_image = cv2.resize(result_image, None, fx=scale_factor, fy=scale_factor)#
# 显示缩小后的结果图像
cv2.imshow(‘Resized Result Image’, result_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
(3)实验结果及分析
题目11结果如图所示:通过对图像的处理可以实现让光照不均的图像进行显示出来。
图6 题11题
四 心得体会
通过本次实验我掌握了其中numpy库中对其矩阵和数组创建以及相关的用法,了解到了numpy库中这么多实用型的知识,学好numpy的知识,为之后的OpenCV理论知识学习打好坚实的基础。另外在其对OpenCV学习的的时候,掌握了对其一定的代码知识,了解到对其图像处理的一些基本操作,例如对其图像的归一化处理,对其图像的显示,对其图像逻辑运算,对图像灰度图像的转换运算等等,掌握了图像读写和显示的方法,并对其图像几何变换及图像见的运算方法有了一个更深的了解,更加激发了我对图像了解的兴趣,让我对其图像处理的奥秘又多了一份思考。