Image.open和cv2.imread读取图像的区别,及改变图像分辨率

本文讲述了如何在Python中使用PIL和OpenCV处理高分辨率图像,包括图像读取的区别、通道转换技巧,重点在于解决RGBA到RGB的转换以及调整分辨率以减少内存消耗。作者分享了在处理RGBA图像时遇到的问题和解决方案,确保后续图像处理的顺利进行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

需求

图像的读取

两者区别

两者相互转换

具体需求代码


需求

需要对一些图片做图像处理,但是原数据图像太大了(2700x2500左右),实际的处理过程中并不需要这么高的分辨率,所以需要对数据进行预处理。

图像的读取

比较熟悉的图像读取方式有2种:

  1. img = cv2.imread(imgpath)        opencv中处理图片的函数,需要import cv2
  2. img = Image.open(imgpath)       PIL中处理图片的函数,需要from PIL import Image
imgpath = "D:\\xxx\\xxx\\xxx.png"
img1 = Image.open(imgpath) 
print("im1的类型是",type(img1))    #<class 'PIL.PngImagePlugin.PngImageFile'>
w,h = img1.size
print("w,h",w,h)    #2754 2426
img = cv2.imread(imgpath)
print("img.shape",img.shape)    #(2426, 2754, 3)
print("type",type(img))        #<class 'numpy.ndarray'>

可以看到cv2.imread读取图像后返回值是numpy格式的,并且它读取的是图片的真实数据。而Image.open读取图像类型是Image对象,不是数组,且只是保持图象被读取的状态。所以如果要操作具体某个元素,比如输出某个像素点的RGB值时,需要先img = img.load()读取数据。 然后print(img[0,0]) 就可以看到(0,0)坐标像素点的RGB值。

两者区别

一个就是上面写到的,返回值及读取是否是真实数据

另一个就是,Image.open函数默认彩色图像读取通道的顺序是RGB的,而cv2.imread读取通道是BGR的。同时,如果图像格式是RGBA时,Image.open读取格式是RGBA,是四通道,cv2.imread是BGR,只有三通道。

写这篇博客主要就是因为,处理的图片数据其实是RGBA四通道的,而我需要用改变分辨率后,还只需要三通道的numpy返回值

两者相互转换

#1、Image对象 --> np.adarray
img = Image.open(imgpath)
img_array = np.array(img)

#2、np.adarry --> Image对象
img = cv2.imread(imgpath)
img_Image = Image.fromarray(np.uint8(img))

这样就可以实现两者的简单转换了。那放在我这个需求中应该怎么具体处理呢

具体需求代码

首先,明确步骤: 读取图片,改变分辨率,转换通道,输出图片

一开始,我仅考虑了改变分辨率的问题,代码如下

    imgpath = "D:\\T18.png"
    img1 = Image.open(imgpath)   #通过Image打开,进行resize操作
    print("img1的类型是",type(img1))   #<class 'PIL.PngImagePlugin.PngImageFile'>
    w,h = img1.size
    print("w,h",w,h)        #2754 2426
    img1 = img1.resize((1000,1000))
    print("resize,w,h:",img1.size)    #(1000,1000)
    img = np.asarray(img1)
    print("img的类型是", type(img)) #<class 'numpy.ndarray'>
    
    plt.imshow(img)
    plt.show()

首先,用Image读取,使用resize函数进行分辨率改变,将原本2754 2426的图片缩小到1000 1000上去,然后将Image对象转换为numpy进行展示,发现居然可以!

就在我以为已经大功告成的时候,接下去的图像处理,就出现问题了

比如就以 给图像的某一个像素点涂色 这个小功能来说,其实就是 img[i][j] = (255,0,0) ,但是出现了问题,报错为

    img[up][j] = (255,0,0)
ValueError: could not broadcast input array from shape (3,) into shape (4,)

 意思是,它的通道其实是四通道!还有一个通道似乎是alpha,所以它的通道顺序是RGBA!

所以需要找到它对应的通道,并重新组合

    imgpath = "D:\\T18.png"
    img1 = Image.open(imgpath)   #通过Image打开,进行resize操作
    print("img1的类型是",type(img1))   #<class 'PIL.PngImagePlugin.PngImageFile'>
    w,h = img1.size
    print("w,h",w,h)        #2754 2426
    img1 = img1.resize((1000,1000))
    print("resize,w,h:",img1.size)    #(1000,1000)
    img = np.asarray(img1)
    r,g,b,a = cv2.split(img)
    img = cv2.merge([b,g,r])
    print("img的类型是", type(img)) #<class 'numpy.ndarray'>
    print("img.shape", img.shape)    #img.shape (1000, 1000, 3)
    plt.imshow(img)
    plt.show()

split找到它的四个通道,分别是rgba,cv2.merge将通道重新排序,因为cv2.imread读取图片就是以BGR的顺序,所以干脆也以b,g,r的顺序组合,这样也方便后面用。

最后,整个功能需求就实现了。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值