任务:利用python编写图像读取、显示图像,并基于opencv库函数和自定义函数实现图像灰度化、二值化。
图像定义为二维矩阵 A(u,v),其中,u,v 是像素坐标,a(i,j) 是图像在点(i,j) 的处的强度或灰度的幅值。 彩色图像由三个(如 RGB)二维灰度(或亮度)矩阵 A(x,y)组成。用红、绿、 蓝三元组的二维矩阵来表示。通常,三元组的 每个数值也是在 0 到 255 之间,0 表示相应的基色在该像素中没有,而 255 则代表相应的基色在该像素中取得最大值。
灰度图像是一个二维灰度(或亮度)矩 阵 A(i,j),每个像素的亮度用一个数值 来表示,通常数值范围在 0 到 255 之间,0 表示黑、255 表示白,其它值表示处 于黑白之间的灰度。
二值图像只有白和黑两种颜色,称为二值图像,0 表示黑,1 表示白。
一、使用 OpenCV 库函数实现图像灰度化、二值化
①读取彩色图像:使用函数 cv2.imread(filepath,flags)读入重邮和可莉图片
filepath:要读入图片的完整路径
flags:读入图片的标志
cv2.IMREAD_COLOR:默认参数,读入一副彩色图片,忽略 alpha 通道
cv2.IMREAD_GRAYSCALE:读入灰度图片
cv2.IMREAD_UNCHANGED:读入完整图片,包括 alpha 通道
②灰度化图像:使用 cv2.cvtColor(input_image, flag)函数灰度化图像
>或者在 imread 读取图像时直接读取成灰度图像,用 cv2.IMREAD_GRAYSCALE
③二值化图像:使用 cv2.threshold(src, thresh, maxval, type)函数二值化图像
④编写 python 源码
Picture_trans.py
import cv2
img_path = "C:/Users/Akaxi/Desktop/Akaxi_python/Sensor_learning_Akaxi/Keli.jpg" # 读取图片的路径
img_path2 = "C:/Users/Akaxi/Desktop/Akaxi_python/Sensor_learning_Akaxi/fig1.jpg"
# 使用opencv函数进行灰度化以及二值化
# imread 读取图像
img_cv = cv2.imread(img_path)
img_cv2 = cv2.imread(img_path2)
cv2.imshow("Color_keli", img_cv)
cv2.imshow("Color_CQUPT", img_cv2)
# 使用cvtColor函数灰度化图像
img_cv_gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)
img_cv_gray2 = cv2.cvtColor(img_cv2, cv2.COLOR_BGR2GRAY)
cv2.imshow("Gray_Keli", img_cv_gray)
cv2.imshow("Gray_CQUPT", img_cv_gray2)
# 或者在imread读取图象时直接读取成灰度图像
img_cv_st = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
img_cv_st2 = cv2.imread(img_path2, cv2.IMREAD_GRAYSCALE)
cv2.imshow("Gray_read-Keli", img_cv_st)
cv2.imshow("Gray_read-CQUPT", img_cv_st2)
# 使用threshold函数二值化图像
# ret, img_cv_dua = cv2.threshold(img_cv_gray, 127, 255, cv2.THRESH_BINARY)
# ret2, img_cv_dua2 = cv2.threshold(img_cv_gray2, 127, 255, cv2.THRESH_BINARY)
ret, img_cv_dua = cv2.threshold(img_cv_gray, 200, 255, cv2.THRESH_BINARY)
ret2, img_cv_dua2 = cv2.threshold(img_cv_gray2, 200, 255, cv2.THRESH_BINARY)
cv2.imshow("Dua_Keli", img_cv_dua)
cv2.imshow("Dua_CQUPT", img_cv_dua2)
cv2.waitKey()
二、使用自定义函数实现图像灰度化、二值化
①读取彩色图像:使用函数 plt.imread()读入一副图片
②编写彩图转灰图函数:def rgb_to_gray(image):
功能:将 RGB 图像转换为灰度图像
参数:image:输入的 RGB 图像,类型为 NumPy 数组
灰度化思路:
先获取图片的尺寸,利用 np.shape 获取图片数组的长度和宽度,再创建同 样大小的灰度图片 numpy 数组,使用循环来求取每一个像素灰度值,采用不同的 算法,这里我采用均值法与经验函数法,核心函数为:
for i in range(height):
for j in range(width):
# gray_value = (image[i, j, 0] + image[i, j, 1] + image[i, j, 2]) / 3 # 均值法
gray_value = 0.299 * image[i, j, 0] + 0.587 * image[i, j, 1] + 0.114 * image[i, j, 2] # 加权平均法
gray_img[i, j] = gray_value
还有其他方法,可以参考:
③实例化得灰度图:
自己编写的函数使用不同方法得出的灰度图像效果不同,所以方法的选择还是比较重要。
其中在使用均值法时,会报错 RuntimeWarning: overflow encountered in ubyte_scalars,像素加减运算溢出异常,可能是由于在进行像素的 R、G、B 三通 道值时累加会超出 255,所以报错,但是除以三均值后任然可以正常生成灰图。
④编写灰图转二值图函数:def gray_to_binary(gray_image, threshold):
功能:将灰度图像转换为二值图像
参数:gray_image: 输入的灰度图像,类型为 NumPy 数组
threshold: 二值化阈值,取值范围[0, 255]
二值化思路: 主要是将灰度值与阈值进行比较,0 或者 255 的二值化,核心代码为:
for i in range(height):
for j in range(width):
if gray_image[i, j] > threshold: # 如果像素的灰度值大于阈值,则为白色,否则为黑色
binary_image[i, j] = 255
⑤实例化得二值图:
⑥编写 python 源码
Picture_trans_own.py
import numpy as np
import matplotlib.pyplot as plt
def rgb_to_gray(image):
# 将RGB图像转换为灰度图像
# image: 输入的RGB图像,类型为NumPy数组
# 先获取图片的尺寸
# shape获取图片数组的长度和维度
height, width, channels = image.shape
gray_img = np.zeros((height, width), dtype=np.uint8) # 创建同样大小的灰度图片numpy数组
# 使用循环来求取每一个像素灰度值,采用不同的算法
for i in range(height):
for j in range(width):
# gray_value = (image[i, j, 0] + image[i, j, 1] + image[i, j, 2]) / 3 # 均值法
gray_value = 0.299 * image[i, j, 0] + 0.587 * image[i, j, 1] + 0.114 * image[i, j, 2] # 加权平均法
gray_img[i, j] = gray_value
return gray_img
def gray_to_binary(gray_image, threshold):
# 将灰度图像转换为二值图像
# gray_image: 输入的灰度图像,类型为NumPy数组
# threshold: 二值化阈值,取值范围[0, 255]
# 获取图像的宽度和高度
height, width = gray_image.shape
binary_image = np.zeros((height, width), dtype=np.uint8) # 创建同样大小的灰度图片numpy数组
# 使用循环来对每一个像素进行二值化处理
for i in range(height):
for j in range(width):
if gray_image[i, j] > threshold: # 如果像素的灰度值大于阈值,则为白色,否则为黑色
binary_image[i, j] = 255
return binary_image
# 【灰度化】
# 读取图像 matplotlib获取的图片会变成numpy的数组
image = plt.imread('C:/Users/Akaxi/Desktop/Akaxi_python/Sensor_learning_Akaxi/Keli.jpg')
image2 = plt.imread('C:/Users/Akaxi/Desktop/Akaxi_python/Sensor_learning_Akaxi/fig1.jpg')
# 显示彩色图
plt.imshow(image)
plt.axis('off')
plt.show()
plt.imshow(image2)
plt.axis('off')
plt.show()
# 将彩色图像转换为灰度图像
gray_img = rgb_to_gray(image)
gray_img2 = rgb_to_gray(image2)
# 显示灰度图
plt.imshow(gray_img, cmap='gray')
plt.axis('off')
plt.show()
plt.imshow(gray_img2, cmap='gray')
plt.axis('off')
plt.show()
# 【二值化】
# 加载灰度图
gray_image = gray_img
gray_image2 = gray_img2
# 将灰度图像转换为二值图
threshold = 127 # 二值化阈值
# threshold = 200 # 二值化阈值
binary_image = gray_to_binary(gray_image, threshold)
binary_image2 = gray_to_binary(gray_image2, threshold)
# 显示二值图
plt.imshow(binary_image, cmap='gray')
plt.axis('off')
plt.show()
plt.imshow(binary_image2, cmap='gray')
plt.axis('off')
plt.show()
三、参考链接
[1]cv2.cvtColor(input_image, flag)参考博文
https://blog.csdn.net/weixin_40522801/article/details/106517099
[2]cv2.threshold(src, thresh, maxval, type)参考博文
https://blog.csdn.net/weixin_40522801/article/details/106516424
[3]自己编写灰度图参考博文
https://blog.csdn.net/rhyijg/article/details/106934061
[4] 自己编写二值图参考博文
https://blog.csdn.net/bblingbbling/article/details/112793681
2023年9月14日
渝北仙桃数据谷