Python图像处理【3】Python图像处理库应用

Python图像处理库应用

    • 0. 前言
    • 1. 将 RGB 图像转换为灰度图像算法
      • 1.1 算法原理
      • 3.2 算法实现
    • 2. 使用 PIL 库计算图像差异
      • 2.1 算法原理
      • 2.2 算法实现
    • 3. 使用 Scikit-image 转换图像色彩空间
      • 3.1 将 RGB 图像转换至 HSV 色彩空间
      • 3.2 将 RGB 图像转换至 YUV 色彩空间
    • 4. 用 OpenCV 调整图像的大小
    • 5. 使用 Scikit-image 在图像中添加水印
    • 6. 使用线性变换改变图像的亮度/对比度
      • 6.1 算法原理
      • 6.2 算法实现
    • 小结
    • 系列链接

0. 前言

我们已经学习了使用多种不同的 Python库实现常见的图像处理,但这些库只是 Python丰富第三方库的冰山一角,在本节中,我们将继续探索更多 Python图像处理库处理图像分析问题。

1. 将 RGB 图像转换为灰度图像算法

在本节中,我们将学习实现六种不同的算法,以将 RGB彩色图像(具有 RGB三个颜色通道的图像)转换为灰度图像。我们首先介绍不同算法的原理,然后在 rgb2gray()函数中实现这些算法。

1.1 算法原理

首先,介绍多种不同的强度 (intensity) 算法,将 RGB转换为灰度图像的最简单方法是计算三个颜色通道的平均值:
V = ( R + G + B ) / 3 V = (R+G+B)/3 V=(R+G+B)/3
或者通过使用 RGB通道的加权组合来与人类的亮度感知相匹配,加权计算公式如下:
V = 0.3 R + 0.59 G + 0.11 B V = 0.3R+0.59G+0.11B V=0.3R+0.59G+0.11B

我们也可以通过获取 RGB通道的最大值来计算最终的灰度值:
V = m a x ( R , G , B ) V = max(R, G, B) V=max(R,G,B)
我们也可以通过亮度 (luster)来获取最终灰度强度值,其中亮度是色调、亮度和饱和度 (HLS) 颜色空间中的L通道,亮度是 RGB中最小和最大通道值的平均值:
V = ( m a x ( R , G , B ) + m i n ( R , G , B ) ) / 2 V = (max(R,G,B) + min(R,G,B))/2 V=(max(R,G,B)+min(R,G,B))/2
或者,我们可以使用 Lab色彩空间的 L通道,将图像从 RGB空间转换为 Lab颜色空间,并提取 L(强度)通道值。
最后,我们也可以使用 RGB色彩空间的 R通道,即从 RGB图像中提取红色通道,等效的,我们也可以提取 GB通道。

3.2 算法实现

首先,导入所需的库并定义 rgb2gray()函数,使用该函数实现上述六种计算灰度图像的算法,并返回每种算法的输出灰度图像:

importnumpy asnpfromskimage.color importrgb2labfromskimage.io importimreadimportmatplotlib.pyplot aspltdefrgb2gray(img):gray_images ={ }gray_images['intensity']=np.mean(image,axis=2)gray_images['luminance']=np.average(image,axis=2,weights=[0.3,0.59,0.11])gray_images['value']=np.max(image,axis=2)gray_images['luster']=(np.max(image,axis=2)+np.min(image,axis=2))/2gray_images['Lab L']=rgb2lab(img)[...,0]gray_images['RGB R']=img[...,0]returngray_images

读取并绘制原始图像:

image =imread('1.png')plt.figure(figsize=(5,5))plt.imshow(image),plt.axis('off'),plt.title('RGB image',size=10)plt.show()

RGB图像
调用函数 rgb2gray(),绘制不同算法生成的灰度图像:

gray_images =rgb2gray(image)i =1plt.figure(figsize=(15,10))plt.gray()forgray_type insorted(gray_images):plt.subplot(2,3,i),plt.imshow(gray_images[gray_type]),plt.axis('off'),plt.title(gray_type,size=10)i +=1plt.suptitle('Conerting RGB to GrayScale image with different methods',size=25)plt.show()

灰度图像

2. 使用 PIL 库计算图像差异

图像差异的相关研究一直受到业界的广泛关注,其具有极大的研究价值,旨在从相似的图像对中定位差异目标。

2.1 算法原理

在实践中,我们通常需要计算两个仅略有不同的图像之间的差异,例如,实现视频压缩的一种方法是存储一帧以及其他帧与该帧的差异,而不是存储所有帧,如果视频帧之间仅略有不同,则该技术可以实现较高的压缩比,从而节省存储空间,或者我们可以利用两张图像之间的差异来得到目标对象的图像。在本节中,我们将学习如何使用 PIL库函数 difference()来计算两个图像的差异图像。

2.2 算法实现

首先,导入所需的模块,包括 PIL模块中的 Image类用于加载/保存图像以及计算图像差异所需的 difference()函数和用于图像可视化的 matplotlit库中 pyplot模块,模块加载完成后使用 Image模块中的 open()函数读取两张输入图像。要计算图像间的差异,两张输入图像的尺寸大小必须相同,为了提高程序的鲁棒性,我们可以使用 resize()函数调整第二幅图像的尺寸大小,使其与第一幅图像尺寸大小相同,加载完成后可以使用 Image.show()函数查看加载完成的输入图像:

fromPIL.ImageChops importdifferencefromPIL importImagefrommatplotlib importpyplot asplt# 加载两张图像im1 =Image.open("1.png")im2 =Image.open("2.png").resize((im1.width,im1.height))plt.figure(figsize=(20,20))plt.subplot(121),plt.imshow(im1),plt.title('image1')plt.xticks([]),plt.yticks([])plt.subplot(122),plt.imshow(im2),plt.title('image2')plt.xticks([]),plt.yticks([])plt.show()

原始图像
要计算第二幅图像与第一幅图像之间的差异,可以使用 PIL ImageChop模块的 difference()函数计算两个图像的差异图像,最后使用 Image模块中的 save()函数保存差异图像:

# 计算两张图像的差异,并将差异图像保存在本地文件系统中difference(im2,im1).show()difference(im2,im1).save('D1.png')

图像差异

3. 使用 Scikit-image 转换图像色彩空间

将图像从一个颜色空间转换为另一个颜色空间是一种非常有用的操作,在多种不同应用程序中都有着重要作用,例如图像分割等。

3.1 将 RGB 图像转换至 HSV 色彩空间

在本节中,我们将介绍以下内容,使用 Scikit-Image.Color模块的 RGB2HSV()HSV2RGB()函数将彩色图像从 RGB转换为 HSV色彩空间,我们还将研究修改 H(hue)S(saturation)V(value)通道中的值对图像的影响。接下来,我们实现将图像从 RGB色彩空间转换到 HSV颜色空间,并返回转换后的图像。

(1)首先导入所需的库、模块和函数,然后读取输入 RGB彩色图像:

fromskimage.io importimreadfromskimage.color importrgb2hsv,hsv2rgbimportnumpy asnpimportmatplotlib.pyplot asplt

(2)使用 skimage.rgb2hsv()函数将其转换为 HSV色彩空间,并且使用 Numpyclip()函数来确保输出像素值在 [0,1]区间内:

im =imread("1.png")im_hsv =np.clip(rgb2hsv(im),0,1)

绘制原始输入图像,以及转换后图像的 HSV通道。然后,分别更改图像的 HSV通道,修改后将图像转换回 RGB色彩空间,以查看修改通道像素值对输出图像的影响。

(3)使用 Matplotlib的函数 subplots_adjust()可以调整子图之间的边距,例如,通过指定子图之间的水平和垂直间距来使图像展示更为紧凑:

plt.figure(figsize=(20,12))plt.subplots_adjust(0,0,1,0.925,0.05,0.05)plt.gray()plt.subplot(231),plt.imshow(im_hsv[...,0]),plt.title('h',size=10),plt.axis('off')plt.subplot(232),plt.imshow(im_hsv[...,1]),plt.title('s',size=10),plt.axis('off')plt.subplot(233),plt.imshow(im_hsv[...,2]),plt.title('v',size=10),plt.axis('off')im_hsv_copy =np.copy(im_hsv)im_hsv[...,0]/=4plt.subplot(234),plt.imshow(np.clip(hsv2rgb(im_hsv),0,1)),plt.title('original image with h=h/4',size=10),plt.axis('off')im_hsv =im_hsv_copyim_hsv[...,1]/=3plt.subplot(235),plt.imshow(np.clip(hsv2rgb(im_hsv),0,1)),plt.title('original image with s=s/3',size=10),plt.axis('off')im_hsv =im_hsv_copyim_hsv[...,2]/=5plt.subplot(236),plt.imshow(np.clip(hsv2rgb(im_hsv),0,1)),plt.title('original image with v=v/5',size=10),plt.axis('off')plt.show()

HSV色彩空间

3.2 将 RGB 图像转换至 YUV 色彩空间

接下来,我们将介绍另一个颜色模型 YUV,其中通道 Y代表亮度 (brightness),uv通道表示色彩 (color)。我们将实现使用 color模块函数将彩色图像从 RGB空间转换为 YUV颜色空间。

(1)首先导入相应库中的必需函数,然后读取 RGB输入图像,并使用 skimage.ColorRGB2YUV()函数将其转换为 YUV图像:

fromskimage.color importrgb2yuv,yuv2rgbim =imread("2.png")im_Yuv =rgb2yuv(im)

(2)分别绘制 YUV图像中的亮度 (y) 和色彩通道 (u, v),然后修改 YUV色彩空间中每个通道的值,再使用 skimage.color.yuv2rgb()函数将图像转换回 RGB色彩空间,观察修改不同通道对图像的影响:

plt.figure(figsize=(20,15))plt.subplots_adjust(0,0,1,0.925,0.05,0.05)plt.gray()plt.subplot(231),plt.imshow(im_Yuv[...,0]),plt.title('Y',size=10),plt.axis('off')plt.subplot(232),plt.imshow(im_Yuv[...,1]),plt.title('u',size=10),plt.axis('off')plt.subplot(233),plt.imshow(im_Yuv[...,2]),plt.title('v',size=10),plt.axis('off')im_Yuv_copy =np.copy(im_Yuv)im_Yuv[...,0]/=2plt.subplot(234),plt.imshow(np.clip(yuv2rgb(im_Yuv),0,1)),plt.title('original image with Y=Y/2',size=10),plt.axis('off')im_Yuv =im_Yuv_copyim_Yuv[...,1]/=3plt.subplot(235),plt.imshow(np.clip(yuv2rgb(im_Yuv),0,1)),plt.title('original image with u=u/3',size=10),plt.axis('off')im_Yuv =im_Yuv_copyim_Yuv[...,2]/=4plt.subplot(236),plt.imshow(np.clip(yuv2rgb(im_Yuv),0,1)),plt.title('original image with v=v/4',size=10),plt.axis('off')plt.show()

YUV色彩空间
从上图可以看出,降低 Y通道值会降低图像的亮度(不会改变颜色),而更改 UV通道会改变图像颜色。

4. 用 OpenCV 调整图像的大小

本节我们介绍使用 OpenCV和多种插值技术来调整图像大小,cv2.resize()函数可以用于调整图像大小:

cv2.resize(src,dsize,fx,fy,interpolation)

OpenCV中常用的插值标志 interpolation包括:cv2.INTER_NEARESTcv2.INTER_LINEARcv2.INTER_AREAcv2.INTER_LANCZOS4cv2.INTER_CUBIC
当我们缩放图像时,为避免混叠图像伪影需要使用插值技术。不同的插值技术对图像的平滑度具有不同的影响。接下来,我们通过使用不同的插值技术将图像放大四倍(沿垂直和水平尺寸均放大四倍),从而观察使用不同插值技术对图像缩放的影响。

(1)首先导入所需的库。读取输入图像,指定我们将使用的插值算法:

importcv2importmatplotlib.pylab aspltim =cv2.imread("1.png")interps =['nearest','bilinear','area','lanczos','bicubic']

(2)用每种插值算法调整原始图像(将图像放大 4倍),并绘制每种插值情况下获得的输出图像:

i =1plt.figure(figsize=(18,12))forinterp in[cv2.INTER_NEAREST,cv2.INTER_LINEAR,cv2.INTER_AREA,cv2.INTER_LANCZOS4,cv2.INTER_CUBIC]:im1 =cv2.resize(im,None,fx=8.,fy=8.,interpolation =interp)# 4 timesplt.subplot(2,3,i)plt.imshow(cv2.cvtColor(im1,cv2.COLOR_BGR2RGB))plt.axis('off')plt.title(interps[i-1],size=20)i +=1print(im.shape,im1.shape)plt.show()

图像缩放

5. 使用 Scikit-image 在图像中添加水印

在图像中添加版权信息的一种常见方法是在图中添加一个 logo图像作为水印。在本节中,我们将学习如何将 logo图像添加到图像中。

(1)加载所需的库。使用 imread()函数从磁盘中读取原始图像和 logo图像:

fromskimage.color importrgb2gray,gray2rgbimportnumpy asnpimportmatplotlib.pylab aspltimg1 =imread('1.png').astype(np.uint8)img2 =imread('logo.jpg').astype(np.uint8)

(2)使用 skimage.colorrgb2gray()函数将 logo图像转换为灰度,然后应用阈值算法。将 logo图像用作掩码图像,然后使用感兴趣区域作为要插入 logo的位置:

rows,cols,_ =img2.shaperoi =img1[0:rows,0:cols]img2gray =(255*rgb2gray(img2)).astype(np.uint8)mask =255*(img2gray <150)# cv2.threshold(img2gray, 10, 255, cv2.THRESH_BINARY)mask_inv =np.invert(mask)# cv2.bitwise_not(mask)mask_inv =mask_inv.astype(np.uint8)img1_bg =np.bitwise_and(roi,gray2rgb(mask_inv))# cv2.bitwise_and(roi,roi,mask = mask_inv)img2_fg =np.bitwise_and(img2,gray2rgb(mask))# cv2.bitwise_and(img2,img2,mask = mask)

(3)最后,对前景图像和背景图像求和以获取修改后的感兴趣区域,并将其分配给原始图像中相应位置以获取水印图像:

dst =img1_bg +img2_fgimg1[0:rows,0:cols ]=dstplt.figure(figsize=(20,20))plt.imshow(img1)plt.axis('off')plt.show()

添加图像水印

6. 使用线性变换改变图像的亮度/对比度

对比度、亮度增强技术是两种非常常见技术,这些技术是在许多图像处理任务(例如,图像分类)中使用预处理步骤。在本节中,我们将学习如何使用 OpenCV库来修改图像的对比度和亮度。

6.1 算法原理

乘法和加法是两种常用的图像操作运算,使用这两种运算可以组成基本线性变换:g ( x ) = α f ( x ) + β g(x)=αf(x)+β g(x)=αf(x)+β,其中常数参数 α > 0 α>0 α>0β β β通常分别称为对比度(增益)和亮度(偏置)参数。可以将 f ( x ) f(x) f(x)视为源图像像素,而 g ( x ) g(x) g(x)则是输出图像像素,因此,我们可以将表达式改写为 g ( i , j ) = α ⋅ f ( i , j ) + β g(i,j)=α·f(i,j)+β g(i,j)=αf(i,j)+β,其中 i i ij j j表示像素位于第 i i i行和第 j j j列中。在本节中,我们将学习如何使用 OpenCVconvertscaleabs()实现基本线性变换,并观察其对图像的影响,该函数用法如下:

cv2.convertScaleAbs(src,alpha,beta)

在输入图像的每个通道上,该函数顺序执行三个操作,缩放,计算绝对值,转换为无符号的 8位类型(对于输入图像 s r c src src,返回的输出图像是 s r c ∗ a l p h a + b e t a src*alpha+beta srcalpha+beta)。
幂转换也称为 gamma校正,当 γ > 1 γ>1 γ>1时图像将转移到频谱的黑色端,而在 γ < 1 γ<1 γ<1时会使图像显得偏淡,使用 LUT()函数可以将图像的查找表更改为具有幂转换的新图像,该用法函数如下:

cv2.LUT(src,lut)

6.2 算法实现

(1)首先导入所需的库和函数,并加载输出图像,然后使用 OpenCV函数定义函数 basic_linear_transform()gamma_correction()分别实现对比度修改和伽马校正:

importcv2importnumpy asnpimportmatplotlib.pylab aspltalpha,beta,gamma =1,0,1defbasic_linear_transform(img,alpha,beta):returncv2.convertScaleAbs(img,alpha=alpha,beta=beta)defgamma_correction(img,gamma):lookup_table =np.empty((1,256),np.uint8)fori inrange(256):lookup_table[0,i]=np.clip(pow(i /255.0,gamma)*255.0,0,255)returncv2.LUT(img,lookup_table)image =cv2.imread('1.png')

(2)用不同的 alphagamma值调用函数 basic_linear_transform()以改变输入图像的亮度,并绘制输出图像:

plt.figure(figsize=(20,20))i =1foralpha in[0.25,0.5,1,1.5,2.5]:forbeta in[0,0.5,1,1.5,2]:image_corrected =basic_linear_transform(image,alpha,beta)plt.subplot(5,5,i),plt.imshow(cv2.cvtColor(image_corrected,cv2.COLOR_BGR2RGB)),plt.axis('off')plt.title(r'$\alpha$={ :.2f}, $\beta$={ :.2f}'.format(alpha,beta),size=10)i +=1plt.suptitle('Basic linear transform to change brightness',size=20)plt.show()

亮度增强

(3)用不同的 gamma参数值调用函数 gamma_correction(),并绘制输出图像:

plt.figure(figsize=(20,20))i =1forgamma innp.linspace(0,2,16):image_gamma_corrected =gamma_correction(image,gamma)plt.subplot(4,4,i),plt.imshow(cv2.cvtColor(image_gamma_corrected,cv2.COLOR_BGR2RGB)),plt.axis('off')plt.title(r'$\gamma$={ :.2f}'.format(gamma),size=10)i +=1plt.suptitle('Gamma correction',size=20)plt.show()

对比度增强

小结

在本节中,我们介绍了多个用于图像处理的流行 Python第三方库,利用这些图像处理库我们可以快速执行基本的图像变换操作。本节我们重点介绍多种可以将 RGB图像转换为灰度图像算法、介绍了如何使用 PIL库计算图像间的差异、使用 Scikit-image转换图像色彩空间以及在图像中添加水印、同时介绍了如何使用 OpenCV库指定不同的插值算法调整图像大小、最后我们还介绍了如何利用线性变换改变图像的亮度/对比度。

系列链接

Python图像处理【1】图像与视频处理
Python图像处理【2】探索Python图像处理库
Python图像处理【4】图像线性变换
Python图像处理【5】图像扭曲与逆扭曲详解
Python图像处理【6】通过哈希查找重复和类似的图像