python計算機視覺1:基本操作與直方圖



本文主要內容來源於書籍《python計算機視覺編程》
我是一名初學者,如果你發現文中有錯誤,請留言告訴我,謝謝


 PIL模塊 

PIL模塊全程為Python Imaging Library,是python中一個免費的圖像處理模塊。


 打開圖像 

PIL模塊常用到它的Image類,打開圖像首先要導入Image類
from PIL import Image
然后調用Imageopen方法。
例如

from PIL import Image

image = Image.open("smallpi.jpg") # 返回一個Image圖像對象
print(image)
# 結果
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=800x450 at 0x4731348>
 

 圖像的保存及格式轉換 

圖像保存用的是Image對象的save()方法,傳入的參數為保存圖像文件的名字。
當傳入不同的擴展名時,它會根據擴展名自動轉換圖像的格式。
例如

from PIL import Image

image = Image.open("smallpi.jpg") # 打開jpg圖像文件
image.save("smallpi.png") # 保存圖像,並轉換成png格式
 

 

 轉化成灰度圖像 

獲得Image對象后,調用其convert()方法,傳入參數"L",即可以返回該圖像的灰度圖像對象。

from PIL import Image

image = Image.open("smallpi.jpg")

image_gray = image.convert("L") # 轉化成灰度圖像
print(image_gray)
# 結果
<PIL.Image.Image image mode=L size=800x450 at 0x46AD648>

 


 Image對象與圖像矩陣相互轉化 

 Image對象轉化成圖像矩陣 

Image對象轉化成圖像矩陣只要將Image對象作為numpy.array()參數即可。

import numpy as np
from PIL import Image

image = Image.open("smallpi.jpg")
image_array = np.array(image)
print(image_array)
# 結果
[[[177 177 177]
  [177 177 177]
  [176 176 176]
  ..., 
  #此處省略
  ...,
  [232 232 232]
  [232 232 232]
  [232 232 232]]]

 


 

 圖像矩陣轉化成Image對象 

圖像矩陣轉化成Image對象通過Image模塊的fromarray()方法。

import numpy as np
from PIL import Image

image = Image.open("smallpi.jpg")
image_array = np.array(image.convert("L"))
image_array = 255 - image_array # 圖像矩陣處理,將灰度圖像反相
                                # 反相指的是,黑變白,白變黑
image2 = Image.fromarray(image_array)
print(image2)
# 結果
<PIL.Image.Image image mode=RGB size=800x450 at 0x4753748>

 


 

 圖像的顯示 

圖像的顯示需要用到matplotlib模塊。
首先需要導入matplotlib.pyplot
import matplotlib.pyplot as plt
然后,調用pyplot的imshow()方法,傳入Image對象即可

from PIL import Image
import matplotlib.pyplot as plt

image = Image.open("smallpi.jpg")
plt.imshow(image) # 繪制圖像image
plt.show() # 需要調用show()方法,不然圖像只會在內存中而不顯示出來

  

圖像顯示結果(帶坐標軸)

如果想把坐標軸去掉只需要調用pyplot的axis()方法,傳入"off"參數

from PIL import Image
import matplotlib.pyplot as plt

image = Image.open("smallpi.jpg")
plt.imshow(image) # 繪制圖像image
plt.axis("off") # 去掉坐標軸
plt.show() # 需要調用show()方法,不然圖像只會在內存中而不顯示出來 

圖像顯示結果(不帶坐標軸)

如果要顯示灰度圖像,需要導入matplotlib的cm模塊
import matplotlib.cm as cm
然后在調用pyplot.show()時,傳入關鍵字參數cmap=cm.gray

from PIL import Image            
import matplotlib.pyplot as plt
import matplotlib.cm as cm         

image = Image.open("smallpi.jpg") # 打開圖像
image_gray = image.convert("L") # 轉化成灰度圖像

plt.subplot(2,1,1)
plt.imshow(image_gray) # 沒傳入關鍵字參數cmap=cm.gray
plt.axis("off") # 去掉坐標軸

plt.subplot(2,1,2)
plt.imshow(image_gray, cmap=cm.gray) # 指明 cmap=cm.gray
plt.axis("off") # 去掉坐標軸

plt.show() # 顯示圖像 

顯示結果
上:沒指定cmap , 下:指定cmap=cm.gray


 創建縮略圖 

創建圖像縮略圖可以通過Image的thumbnail()方法,參數傳入一個元組,指明縮略圖的大小,如thumbnail((128,128))
例如

from PIL import Image

image = Image.open("smallpi.jpg")
image_thumbnail = image.thumbnail((128,128))

image.save("thumbnail.jpg") 

結果為


 復制和粘貼區域 

復制區域是指截取圖像中的一部分,並將這一部分作為一個新的Image對象。
復制區域的方法為crop(),參數為一個含4個元素的元組,用來指定截取區域的左上角點和右下角點。

from PIL import Image

image = Image.open("smallpi.jpg") # 打開圖像
box = (300,100,500,300) # 截取區域
image_crop = image.crop(box) # 按指定截取區域對圖像進行截取復制

image_crop.save("image_crop.jpg") # 保存

 

保存的截取區域圖像為

 

粘貼區域是指在指定圖像中放入另一個圖像,其方法為paste()。該方法有兩個參數,第一個參數為需要粘貼進去的圖像,第二個參數為粘貼區域。

from PIL import Image

image = Image.open("smallpi.jpg")
box = (300,100,500,300)        # 先截取一部分
image_crop = image.crop(box)    

# 為了看到粘貼效果,現將截取部分轉180度
image_crop = image_crop.transpose(Image.ROTATE_180) # 轉180度
image.paste(image_crop,box) # 將轉180度后的圖像粘貼到原圖像

image.save("image_paste.jpg")
粘貼后原圖像變成 

 


 圖像的尺寸調整和旋轉 

尺寸調整方法為resize(),參數為一元組,指定調整后的大小,如resize((128,128))。
圖像旋轉的方法為
rotate(),參數為旋轉角度(數值,單位為度),逆時針方向,如rotate(45)`

from PIL import Image

image = Image.open("smallpi.jpg")

image_resize = image.resize((200,200)) # 尺寸調整
image_rotate = image.rotate(45) # 圖像旋轉
# image.transpose()也可以旋轉圖像,但只能旋轉90度的整數倍
# 參數為 Image.ROTATE_90 旋轉90度
# 180度,270度可類推

image_resize.save("image_resize.jpg")
image_rotate.save("image_rotate.jpg")

尺寸調整為200*200

 

圖像逆時針旋轉45度

 


 圖像直方圖 

圖像直方圖用來統計圖像中像素值的分布情況,即統計不同像素值出現的次數。方法為調用matplotlib.pyplothist方法,參數傳入圖像像素序列和統計區間個數。

from PIL import Image
import matplotlib.pyplot as plt
import matplotlib.cm as cm

#打開圖像,並轉化成灰度圖像
image = Image.open("smallpi.jpg").convert("L") 
image_array = np.array(image)

plt.subplot(2,1,1)
plt.imshow(image,cmap=cm.gray)
plt.axis("off")
plt.subplot(2,1,2)
plt.hist(image_array.flatten(),256) #flatten可以將矩陣轉化成一維序列
plt.show()

結果為


 灰度變換 

對於一張灰度圖像,其每個像素點都用一個0-255之間的值表示,0表示黑色,越接近0越黑;255表示白色,越接近255越白。
灰度變換就是通過一個特定的函數,使灰度值從一個值轉換成另外一個值。
這里列出3種灰度變換

1. 【反相】= 255

2.【轉換到100-200】變換后的灰度值 =(原灰度值/255)*100+100

3. 【像素平方】變換后的灰度值 = 255*(原灰度值/255)2

2

from PIL import Image
import matplotlib.pyplot as plt
import matplotlib.cm as cm

image = Image.open("smallpi.jpg").convert("L")
image_array = np.array(image)

x = np.arange(255)

# 反相
plt.subplot(3,2,1)
plt.plot(x,255-x) # 畫出變換函數圖像
plt.subplot(3,2,2)
plt.imshow(Image.fromarray(255-image_array),cmap=cm.gray)
plt.axis("off")

# 轉換到 100-200
plt.subplot(3,2,3)
plt.plot(x,(x/255.0)*100+100) # 畫出變換函數圖像
plt.subplot(3,2,4)
plt.imshow( Image.fromarray((image_array/255.0)*100+100), cmap=cm.gray )
plt.axis("off")

# 像素平方
plt.subplot(3,2,5)
plt.plot(x,255*(x/255.0)**2) # 畫出變換函數圖像
plt.subplot(3,2,6)
plt.imshow( Image.fromarray(255*(image_array/255.0)**2), cmap=cm.gray )
plt.axis("off")

plt.show()

  

`結果如下,(左邊是變換函數,右邊是圖像變換結果)


 直方圖均衡化 

由上面圖像的直方圖可以看出,一般情況下,圖像上某些灰度值較多,有些灰度值較少,直方圖均衡化為的是使灰度值較為均衡。

直方圖均衡化是利用直方圖的累積函數作為灰度變換函數,對圖像進行轉換。直方圖均衡化可以增強圖像的對比度。

累積函數和概率論中的累積分布函數類似。例如對於還有5個數的序列[1,2,3,4,5],其累積函數含有5個數,第一個數是1,第二個是1+2=3,……,第五個數是1+2+3+4+5=15,所以其累積函數是[1,3,6,10,15]。

我們把直方圖均衡化的過程封裝在一個函數里面,函數名字叫做histeq,輸入原圖像矩陣和直方圖分塊數,輸出均衡化后的圖像矩陣和累積函數。

import numpy as np 
from PIL import Image
import matplotlib.pyplot as plt
import matplotlib.cm as cm

def histeq(image_array,image_bins=256):
    
    # 將圖像矩陣轉化成直方圖數據,返回元組(頻數,直方圖區間坐標)
    image_array2,bins = np.histogram(image_array.flatten(),image_bins)

    # 計算直方圖的累積函數
    cdf = image_array2.cumsum()

    # 將累積函數轉化到區間[0,255]
    cdf = (255.0/cdf[-1])*cdf
    
    # 原圖像矩陣利用累積函數進行轉化,插值過程
    image2_array = np.interp(image_array.flatten(),bins[:-1],cdf)

    # 返回均衡化后的圖像矩陣和累積函數
    return image2_array.reshape(image_array.shape),cdf



image = Image.open("pika.jpg").convert("L") 
image_array = np.array(image)
plt.subplot(2,2,1)
plt.hist(image_array.flatten(),256)
plt.subplot(2,2,2)
plt.imshow(image,cmap=cm.gray)
plt.axis("off")

a = histeq(image_array)  # 利用剛定義的直方圖均衡化函數對圖像進行均衡化處理
plt.subplot(2,2,3)
plt.hist(a[0].flatten(),256)
plt.subplot(2,2,4)
plt.imshow(Image.fromarray(a[0]),cmap=cm.gray)
plt.axis("off")

plt.show()

 

 結果如下圖所示,第一行為原圖像直方圖和原圖像,第二行為均衡化后的直方圖和圖像。可以看出均衡化后圖像對比度增強了,原先灰色區域的細節變得清晰。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM