用 Image 和 cv2 库读取 BMP 图 像

本次内容中包含了图片的读取和写入,以及“图片融合”、‘图片拼接’、‘图片的灰度直方图展示’

1、 BMP 图像的读

使用深度为8位24位的格式为bmp的图片,存放在“file”文件夹,实现位数为8和24的BMP图像读取和存储,并绘制其对应的灰度直方图。

(1)导入标准库numpy,赋给对象np,用于数据计算和处理。
(2)导入可视化模块matplotlib.pyplot,赋给对象plt,用于绘制可视化图像。
(3)导入第三方库matplotlib,用于调用库中的图像处理函数。
(4)导入标准库os,用于文件和目录操作。
(5)从struct模块导入unpack库,struct模块用于解析字节数据,unpack库用于将字节流转换成python数据类型,返回值为元组。
 # 标准库,用于数据计算和处理
import numpy as np
 # 可视化模块,用于绘制可视化图像
import matplotlib.pyplot as plt
 # 第三方库
import matplotlib
 # 标准库,用于文件和目录操作
import os
 # struct模块用于解析字节数据,unpack库用于将字节流转换成python数据类型,返回值为元组
from struct import  unpack
(6)从第三方图像处理模块PIL导入Image库,用于读取图像。
(7)导入cv2库,用于读取图像。
(8)使用Image库的open函数读取24位的BMP图像,赋值给变量im_24;使用show()方法和可视化模块的imshow函数显示图片,其中,运用可视化模块是为了在输出框输出图片;使用save()方法保存图片,设置图片名为“im_24.jpg”。
(9)使用cv2库的imread函数读取8位的BMP图像,赋值给变量im_8;使用cv2库的imshow函数显示图像,设置窗口名称为“im_8”;使用可视化模块的figure函数创建画布,imshow函数输出图片;使用cv2库的imwrite函数保存图片,设置图片名为“im_8.jpg”。
(10)创建一组for循环,循环对象为range(4),循环变量为i。
①通过plt.subplot(1,4,i+1)函数创建4个子图。
②通过plt.imshow(pictures[i],'gray')函数展示灰度图。
③通过plt.title(titles[i]), plt.xticks([]), plt.yticks([])函数设置图片的标题,并去除横纵坐标轴上的数字坐标。
(11)通过plt.show()函数展示绘制的子图。
from PIL import Image  # 用于读取图像
import cv2  # 用于读取图像
# 读取24位BMP
im_24 = Image.open('./file/24bits.bmp')
#显示图像
plt.imshow(im_24)
#以jpg格式进行存储
im_24.save('im_24.jpg')

# 读取8位BMP
im_8 =  cv2.imread('./file/8bits.bmp')
#显示图像
cv2.imshow('im_8',im_8)
# 设置图片展示时间
cv2.waitKey()
# 释放内存
cv2.destroyAllWindows()

plt.figure()
plt.imshow(im_8)
cv2.imwrite('im_8.jpg',im_8)
# 设置图片标题
titles = ['24bits','8bits']
pictures = [im_24,im_8]
 # 灰度图、idc变换图、高频信息图、增强高频信息后的图

# 设置画布大小
plt.figure(6, figsize=(16, 8))
for i in range(2):
    # 绘制子图
    plt.subplot(1,2,i+1)
    # 绘制图片
    plt.imshow(pictures[i],'gray')
    # 设置标题,并去除横纵坐标轴上的数字坐标
    plt.title(titles[i]), plt.xticks([]), plt.yticks([])
plt.show()
(12)对“24bits.bmp”和“8bits.bmp”进行读取并显示其直方图。
(1)定义Rgb2gray函数
#定义Rgb2gray函数
def Rgb2gray(image):
    h = image.shape[0]
    w = image.shape[1]
    grayimage  = np.zeros((h,w),np.uint8)
    for i in tqdm(range(h)):
        for j in range(w):
            #Gray = R*0.299 + G*0.587 + B*0.114.
            gray =h*0.299+w*0.587
    return grayimage
(2)导入图片画直方图
from PIL import Image
from pylab import *
import cv2
from tqdm import tqdm
# 读取24bits.bmp图像到数组中,并灰度化
image = cv2.imread('./file/24bits.bmp')
im = array(Image.open('./file/24bits.bmp').convert('L'))
# 直方图图像
# flatten可将二维数组转化为一维
hist(image.flatten(), 128)
# 显示
show() 

# 读取8bits.bmp图像到数组中,并灰度化
image = cv2.imread('./file/8bits.bmp')
im = Rgb2gray(image)
# 直方图图像
# flatten可将二维数组转化为一维
hist(image.flatten(), 128)
# 显示
show()

bmp图像的写

(1)从第三方图像处理模块PIL导入Image库,用于调用图像处理方法。
(2)导入可视化模块matplotlib.pyplot,赋给对象plt,用于显示图像。
(3)导入标准库os,用于文件和目录操作。
(4)导入cv2库,用于图像处理和操作。
(5)使用Image库的open函数读取本地真彩色图片,即深度为24位的BMP图,赋值给变量im_24。
(6)使用可视化模块的imshow函数显示图片。
# 用于调用图像处理方法
from PIL import Image
 # 用于显示图像
import matplotlib.pyplot as plt
# 用于文件和目录操作
import os
# 用于图像处理和操作
import cv2
# 读取本地真彩色图片
im_24 = Image.open('24.bmp')
# 显示图片
plt.imshow(im_24)
(7)使用对象im_24的convert()方法实现图像格式转换,设置参数为“L”,实现将图像转换为灰色图像,每个像素用8个字节表示,0表示黑,255表示白,其他数字表示不同的灰度,赋值给变量Lim。
(8)使用可视化模块的imshow函数显示图像,设置参数“gray”,实现灰度图显示,save()方法保存图像,命名为“24bit_灰度.jpg”。
(9)使用convert函数,设置参数为“1”,实现将图像转换为二值图像,非黑即白,每个像素用8个字节表示,0表示黑,255表示白,赋值给变量Bim;使用可视化模块的figure函数创建画布,将图像进行显示并保存,命名为“24bit_二值.jpg”。
(10)定义循环,使用range函数进行遍历,设置值为256,当值小于所定义的变量threshold,向列表填充值“0”,否则填充值“1”。
(11)使用对象Lim的point()方法,设置参数为“table”和“1”,实现通过带有常量阈值的转换表将图像转换为二进制图像;创建画布,将图像进行显示并保存,命名为“24bit_二进制.png”。
# 转换为灰度图像(8位)# 灰度化,8位像素,黑白
#显示为灰度图像
Lim = im_24.convert('L')
plt.figure(figsize=(4,4))
plt.imshow(Lim,'gray')
#matplotlib.pyplot.imshow(X, cmap=None),cmap:颜色图谱(colormap), 默认绘制为RGB(A)颜色空间
# 保存的灰度化图片,jpg形式
im_24.save('24bit_灰度.jpg')
# 转换为二值图像(1位)# 1位像素,黑白,每个字节一个像素存储
Bim = im_24.convert('1')
#创建第二个figure
plt.figure(figsize=(4,4))
#显示图像
plt.imshow(Bim)
#保存为jpg格式图片
Bim.save('24bit_二值.jpg')
# 设置一个带有常量阈值的转换表
threshold = 185
table = []
for i in range(256):
    if i < threshold:
        table.append(0)
    else:
        table.append(1)
# 通过表格转换为二进制图像
img = Lim.point(table,'1')
#创建第三个figure
plt.figure(figsize=(4,4))
#显示灰度图像
plt.imshow(img,'gray')
#保存png格式图片
img.save('24bit_二进制.png')
(12)构造拼接函数
def image_compose():
  # 创建一个新图
    to_image = Image.new('RGB', (IMAGE_COLUMN * IMAGE_SIZE, IMAGE_ROW * IMAGE_SIZE))
    # 循环遍历,把每张图片按顺序粘贴到对应位置上
    for y in range(1, IMAGE_ROW + 1):
        for x in range(1, IMAGE_COLUMN + 1):
            from_image = Image.open(IMAGES_PATH + image_names[IMAGE_COLUMN * (y - 1) + x - 1]).resize(
                (IMAGE_SIZE, IMAGE_SIZE), Image.ANTIALIAS)
            to_image.paste(from_image, ((x - 1) * IMAGE_SIZE, (y - 1) * IMAGE_SIZE))
    plt.imshow(to_image)
    return to_image.save("拼接结果.jpg")  # 保存拼接之后的结果图
(13)定义参数,调用拼接函数
# 图片集地址
IMAGES_PATH = 'img/'
# 图片格式
IMAGES_FORMAT = ['.bmp','.jpg']
# 每张小图片的大小为256
IMAGE_SIZE = 256 
# 图片间隔,也就是合并成一张图后,一共有几行
IMAGE_ROW = 2
# 图片间隔,也就是合并成一张图后,一共有几列
IMAGE_COLUMN = 2
# 获取图片集地址下的所有图片名称
image_names = [name for name in os.listdir(IMAGES_PATH) for item in IMAGES_FORMAT if
               os.path.splitext(name)[1] == item]
print(image_names)
# 简单的对于参数的设定和实际图片集的大小进行数量判断
l=len(image_names)
if l!=IMAGE_SIZE*IMAGE_COLUMN:
    print('错误')
image_compose()  # 调用函数
(14)图片融合叠加
import cv2  # 用于图像处理和操作
#采用cv2读取24.bmp图像
img1 = cv2.imread('24.bmp')
img1 = cv2.cvtColor(img1,cv2.COLOR_BGR2RGB)
#采用cv2读取1.jpg图像
img2 = cv2.imread('1.jpg')
# 调整大小为(300,300)
img2 = cv2.resize(img2,(300,300))
# 获取矩阵行、列和维度
    #rows = img2.shape[0]
    #cols = img2.shape[1]
    #channels = img2.shape[2]
rows,cols,channels = img2.shape
roi = img1[0:rows,0:cols]
dst = cv2.addWeighted(img2, 0.9, roi, 0.1, 0)#图像融合
dst1 = img1.copy()#对原图像进行拷贝
dst1[0:rows,0:cols] = dst

plt.imshow(dst1)
plt.show()

cv2.imshow('dst',dst)#查看融合结果
cv2.imshow('reusult',dst1)#显示处理后的结果
#保存为reusult.jpg
cv2.imwrite('reusult.jpg',dst1)
# 设置图片展示时间
cv2.waitKey()
# 释放内存
cv2.destroyAllWindows()
"""
cv2.imshow()和plt.imshow()的区别
如果需要展示读入的图像,或者展示对读入图像进行一系列操作后的图像时,使用cv2.imshow()
如果不需要展示原始图像,而是绘制一张新的图像,使用plt.imshow()
注意
opencv是BGR通道,plt默认RGB通道,若使用cv2.imread()读入图像,用plt.imshow()展示原始图像或者展示对读入图像进行一系列操作后的图像时,
需要进行通道转换。
在展示灰度图像时,cv2.imshow(‘gray’, gray)
plt.imshow(gray,cmap=‘gray’), plt.title(‘gray’)
"""

整个代码敲下来,也花费我不少时间,总结了一下一些难点(仅针对我自己):

1.图像的融合叠加

在思考这一部分的时候完全是懵的,在网上也找了许多资料,但都没有解决工作问题,后来是看到以前朋友写的代码才得以解决。

首先是对cv2.addWeighted((img2, 1, roi, 0.1, 0)函数的理解

img2 权重为0.9,roi 权重为0.1,补偿量为0。补偿量的作用为亮度调节。

其次呢roi = img1[0:rows,0:cols]这一行代码我将其都运行出来进行对比

通过运行结果可以发现

roi是图像img1同等大小的一个角

dst是roi与img2融合的结果

而最后的结果是经过dst1(就是img1)拷贝dst(融合好的)的r,g,因此就会出现图片上的情况

第二个问题就是上面颜色的问题

我在同时使用plt.show和cv2.imshow展示出来的效果不一样,查询后发现是其两个默认通道不同

opencv是BGR通道,plt默认RGB通道,若使用cv2.imread()读入图像,用plt.imshow()展示原始图像或者展示对读入图像进行一系列操作后的图像时,需要进行通道转换。


猜你喜欢

转载自blog.csdn.net/YYANyk/article/details/129693148