This blog is from: https://www.jianshu.com/p/f2e88197e81d php
基於python腳本語言開發的數字圖片處理包,好比PIL,Pillow, opencv, scikit-image等。
PIL和Pillow只提供最基礎的數字圖像處理,功能有限;opencv其實是一個c++庫,只是提供了python接口,更新速度很是慢。scikit-image是基於scipy的一款圖像處理包,它將圖片做爲numpy數組進行處理,正好與matlab同樣,所以,咱們最終選擇scikit-image進行數字圖像處理。css
Image讀出來的是PIL的類型,而skimage.io讀出來的數據是numpy格式的html
import Image as img import os from matplotlib import pyplot as plot from skimage import io,transform #Image和skimage讀圖片 img_file1 = img.open('./CXR_png/MCUCXR_0042_0.png') img_file2 = io.imread('./CXR_png/MCUCXR_0042_0.png')
輸出能夠看出Img讀圖片的大小是圖片的(width, height);而skimage的是(height,width, channel), [這也是爲何caffe在單獨測試時要要在代碼中設置:transformer.set_transpose('data',(2,0,1)),由於caffe能夠處理的圖片的數據格式是(channel,height,width),因此要轉換數據]python
#讀圖片後數據的大小: print "the picture's size: ", img_file1.size print "the picture's shape: ", img_file2.shape
the picture's size: (4892, 4020) the picture's shape: (4020, 4892)
#獲得像素: print(img_file1.getpixel((500,1000)), img_file2[500][1000]) print(img_file1.getpixel((500,1000)), img_file2[1000][500]) print(img_file1.getpixel((1000,500)), img_file2[500][1000])
(0, 139) (0, 0) (139, 139)
Img讀出來的圖片得到某點像素用getpixel((w,h))能夠直接返回這個點三個通道的像素值
skimage讀出來的圖片能夠直接img_file2[0][0]得到,可是必定記住它的格式,並非你想的(channel,height,width)c++
若是咱們想知道一些skimage圖片信息spring
from skimage import io, data img = data.chelsea() io.imshow(img) print(type(img)) #顯示類型 print(img.shape) #顯示尺寸 print(img.shape[0]) #圖片高度 print(img.shape[1]) #圖片寬度 print(img.shape[2]) #圖片通道數 print(img.size) #顯示總像素個數 print(img.max()) #最大像素值 print(img.min()) #最小像素值 print(img.mean()) #像素平均值 print(img[0][0])#圖像的像素值
PIL image 查看圖片信息,可用以下的方法shell
print type(img) print img.size #圖片的尺寸 print img.mode #圖片的模式 print img.format #圖片的格式 print(img.getpixel((0,0)))#獲得像素: #img讀出來的圖片得到某點像素用getpixel((w,h))能夠直接返回這個點三個通道的像素值
# 獲取圖像的灰度值範圍 width = img.size[0] height = img.size[1] # 輸出圖片的像素值 count = 0 for i in range(0, width): for j in range(0, height): if img.getpixel((i, j))>=0 and img.getpixel((i, j))<=255: count +=1 print count print(height*width)
skimage提供了io模塊,顧名思義,這個模塊是用來圖片輸入輸出操做的。爲了方便練習,也提供一個data模塊,裏面嵌套了一些示例圖片,咱們能夠直接使用。api
skimage包的全稱是scikit-image SciKit (toolkit for SciPy) ,它對scipy.ndimage進行了擴展,提供了更多的圖片處理功能。它是由python語言編寫的,由scipy 社區開發和維護。skimage包由許多的子模塊組成,各個子模塊提供不一樣的功能。主要子模塊列表以下:數組
子模塊名稱 主要實現功能 io 讀取、保存和顯示圖片或視頻 data 提供一些測試圖片和樣本數據 color 顏色空間變換 filters 圖像加強、邊緣檢測、排序濾波器、自動閾值等 draw 操做於numpy數組上的基本圖形繪製,包括線條、矩形、圓和文本等 transform 幾何變換或其它變換,如旋轉、拉伸和拉東變換等 morphology 形態學操做,如開閉運算、骨架提取等 exposure 圖片強度調整,如亮度調整、直方圖均衡等 feature 特徵檢測與提取等 measure 圖像屬性的測量,如類似性或等高線等 segmentation 圖像分割 restoration 圖像恢復 util 通用函數
從外部讀取圖片並顯示bash
讀取單張彩色rgb圖片,使用skimage.io.imread(fname)函數,帶一個參數,表示須要讀取的文件路徑。顯示圖片使用skimage.io.imshow(arr)函數,帶一個參數,表示須要顯示的arr數組(讀取的圖片以numpy數組形式計算)。
from skimage import io img=io.imread('d:/dog.jpg') io.imshow(img)
讀取單張灰度圖片,使用skimage.io.imread(fname,as_grey=True)函數,第一個參數爲圖片路徑,第二個參數爲as_grey, bool型值,默認爲False
from skimage import io img=io.imread('d:/dog.jpg',as_grey=True) io.imshow(img)
程序自帶圖片
skimage程序自帶了一些示例圖片,若是咱們不想從外部讀取圖片,就能夠直接使用這些示例圖片:
astronaut 航員圖片 coffee 一杯咖啡圖片 lena lena美女圖片 camera 拿相機的人圖片 coins 硬幣圖片 moon 月亮圖片 checkerboard 棋盤圖片 horse 馬圖片 page 書頁圖片 chelsea 小貓圖片 hubble_deep_field 星空圖片 text 文字圖片 clock 時鐘圖片 immunohistochemistry 結腸圖片
顯示這些圖片可用以下代碼,不帶任何參數
from skimage import io, data img=data.lena() io.imshow(img)
圖片名對應的就是函數名,如camera圖片對應的函數名爲camera(). 這些示例圖片存放在skimage的安裝目錄下面,路徑名稱爲data_dir,咱們能夠將這個路徑打印出來看看
from skimage import data_dir print(data_dir)
保存圖片
使用io模塊的imsave(fname,arr)函數來實現。第一個參數表示保存的路徑和名稱,第二個參數表示須要保存的數組變量。
from skimage import io,data img=data.chelsea() io.imshow(img) io.imsave('d:/cat.jpg',img)
保存圖片的同時也起到了轉換格式的做用。若是讀取時圖片格式爲jpg圖片,保存爲png格式,則將圖片從jpg圖片轉換爲png圖片並保存。
若是咱們想知道一些圖片信息
from skimage import io, data img = data.chelsea() io.imshow(img) print(type(img)) #顯示類型 print(img.shape) #顯示尺寸 print(img.shape[0]) #圖片高度 print(img.shape[1]) #圖片寬度 print(img.shape[2]) #圖片通道數 print(img.size) #顯示總像素個數 print(img.max()) #最大像素值 print(img.min()) #最小像素值 print(img.mean()) #像素平均值 print(img[0][0])#圖像的像素值
圖片讀入程序中後,是以numpy數組存在的。所以對numpy數組的一切功能,對圖片也適用。對數組元素的訪問,實際上就是對圖片像素點的訪問。
彩色圖片訪問方式爲:img[i,j,c]
i表示圖片的行數,j表示圖片的列數,c表示圖片的通道數(RGB三通道分別對應0,1,2)。座標是從左上角開始。
灰度圖片訪問方式爲:gray[i,j]
例1:輸出小貓圖片的G通道中的第20行30列的像素值
from skimage import io,data img=data.chelsea() pixel=img[20,30,1] print(pixel)
例2:顯示紅色單通道圖片
from skimage import io,data img=data.chelsea() R=img[:,:,0] io.imshow(R)
除了對像素進行讀取,也能夠修改像素值。
例3:對小貓圖片隨機添加椒鹽噪聲
from skimage import io,data import numpy as np img=data.chelsea() #隨機生成5000個椒鹽 rows,cols,dims=img.shape for i in range(5000): x=np.random.randint(0,rows) y=np.random.randint(0,cols) img[x,y,:]=255 io.imshow(img)
這裏用到了numpy包裏的random來生成隨機數,randint(0,cols)表示隨機生成一個整數,範圍在0到cols之間。
用img[x,y,:]=255這句來對像素值進行修改,將原來的三通道像素值,變爲255
經過對數組的裁剪,就能夠實現對圖片的裁剪。
例4:對小貓圖片進行裁剪
from skimage import io,data img=data.chelsea() roi=img[80:180,100:200,:] io.imshow(roi)
對多個像素點進行操做,使用數組切片方式訪問。切片方式返回的是以指定間隔下標訪問 該數組的像素值。下面是有關灰度圖像的一些例子:
img[i,:] = im[j,:] # 將第 j 行的數值賦值給第 i 行 img[:,i] = 100 # 將第 i 列的全部數值設爲 100 img[:100,:50].sum() # 計算前 100 行、前 50 列全部數值的和 img[50:100,50:100] # 50~100 行,50~100 列(不包括第 100 行和第 100 列) img[i].mean() # 第 i 行全部數值的平均值 img[:,-1] # 最後一列 img[-2,:] (or im[-2]) # 倒數第二行
最後咱們再看兩個對像素值進行訪問和改變的例子:
例5:將lena圖片進行二值化,像素值大於128的變爲1,不然變爲0
from skimage import io,data,color img=data.lena() img_gray=color.rgb2gray(img) rows,cols=img_gray.shape for i in range(rows): for j in range(cols): if (img_gray[i,j]<=0.5): img_gray[i,j]=0 else: img_gray[i,j]=1 io.imshow(img_gray)
img_path = 'data/dpclassifier/newtrain/test/1_0.png' import Image as img import os from matplotlib import pyplot as plot from skimage import io,transform, img_as_ubyte img_file1 = img.open(img_path) img_file1.show() img_file2 = io.imread(img_path) io.imshow(img_file2) print(type(img_file1),img_file1.mode, type(img_file2),img_file2.shape, img_file2.dtype,img_file2.max(),img_file2.min(),img_file2.mean()) img_file22=skimage.color.rgb2gray(img_file2) print(type(img_file22),img_file22.shape,img_file22.dtype,img_file22.max(),img_file22.min(),img_file22.mean() ) dst=img_as_ubyte(img_file22) print(type(dst),dst.shape,dst.dtype, dst.max(), dst.min(), dst.mean())
(<class 'PIL.PngImagePlugin.PngImageFile'>, 'RGB', <type 'numpy.ndarray'>, (420, 512, 3), dtype('uint8'), 255, 0, 130.9983863467262) (<type 'numpy.ndarray'>, (420, 512), dtype('float64'), 1.0, 0.0, 0.5137191621440242) (<type 'numpy.ndarray'>, (420, 512), dtype('uint8'), 255, 0, 130.9983863467262)
例6:
from skimage import io,data img=data.chelsea() reddish = img[:, :, 0] >170 img[reddish] = [0, 255, 0] io.imshow(img)
這個例子先對R通道的全部像素值進行判斷,若是大於170,則將這個地方的像素值變爲[0,255,0], 即G通道值爲255,R和B通道值爲0。
在skimage中,一張圖片就是一個簡單的numpy數組,數組的數據類型有不少種,相互之間也能夠轉換。這些數據類型及取值範圍以下表所示:
Data type Range uint8 0 to 255 uint16 0 to 65535 uint32 0 to 232 float -1 to 1 or 0 to 1 int8 -128 to 127 int16 -32768 to 32767 int32 -231 to 231 - 1
一張圖片的像素值範圍是[0,255], 所以默認類型是unit8, 可用以下代碼查看數據類型
from skimage import io,data img=data.chelsea() print(img.dtype.name)
在上面的表中,特別注意的是float類型,它的範圍是[-1,1]或[0,1]之間。一張彩色圖片轉換爲灰度圖後,它的類型就由unit8變成了float
一、unit8轉float
from skimage import data,img_as_float img=data.chelsea() print(img.dtype.name) dst=img_as_float(img) print(dst.dtype.name)
二、float轉uint8
from skimage import img_as_ubyte import numpy as np img = np.array([0, 0.5, 1], dtype=float) print(img.dtype.name) dst=img_as_ubyte(img) print(dst.dtype.name)
除了這兩種最經常使用的轉換之外,其實有一些其它的類型轉換,以下表:
Function name Description img_as_float Convert to 64-bit floating point. img_as_ubyte Convert to 8-bit uint. img_as_uint Convert to 16-bit uint. img_as_int Convert to 16-bit int.
如前所述,除了直接轉換能夠改變數據類型外,還能夠經過圖像的顏色空間轉換來改變數據類型。
經常使用的顏色空間有灰度空間、rgb空間、hsv空間和cmyk空間。顏色空間轉換之後,圖片類型都變成了float型。
全部的顏色空間轉換函數,都放在skimage的color模塊內。
例:rgb轉灰度圖
from skimage import io,data,color img=data.lena() gray=color.rgb2gray(img) io.imshow(gray)
其它的轉換,用法都是同樣的,列舉經常使用的以下:
skimage.color.rgb2grey(rgb) skimage.color.rgb2hsv(rgb) skimage.color.rgb2lab(rgb) skimage.color.gray2rgb(image) skimage.color.hsv2rgb(hsv) skimage.color.lab2rgb(lab)
實際上,上面的全部轉換函數,均可以用一個函數來代替
skimage.color.convert_colorspace(arr, fromspace, tospace)
表示將arr從fromspace顏色空間轉換到tospace顏色空間。
例:rgb轉hsv
from skimage import io,data,color img=data.lena() hsv=color.convert_colorspace(img,'RGB','HSV') io.imshow(hsv)
在color模塊的顏色空間轉換函數中,還有一個比較有用的函數是
skimage.color.label2rgb(arr), 能夠根據標籤值對圖片進行着色。之後的圖片分類後着色就能夠用這個函數。
例:將lena圖片分紅三類,而後用默認顏色對三類進行着色
from skimage import io,data,color import numpy as np img=data.lena() gray=color.rgb2gray(img) rows,cols=gray.shape labels=np.zeros([rows,cols]) for i in range(rows): for j in range(cols): if(gray[i,j]<0.4): labels[i,j]=0 elif(gray[i,j]<0.75): labels[i,j]=1 else: labels[i,j]=2 dst=color.label2rgb(labels) io.imshow(dst)
實際上前面咱們就已經用到了圖像的繪製,如:
io.imshow(img)
這一行代碼的實質是利用matplotlib包對圖片進行繪製,繪製成功後,返回一個matplotlib類型的數據。所以,咱們也能夠這樣寫:
import matplotlib.pyplot as plt plt.imshow(img)
imshow()函數格式爲:
matplotlib.pyplot.imshow(X, cmap=None)
X: 要繪製的圖像或數組。
cmap: 顏色圖譜(colormap), 默認繪製爲RGB(A)顏色空間。
其它可選的顏色圖譜以下列表:
顏色圖譜 描述 autumn 紅-橙-黃 bone 黑-白,x線 cool 青-洋紅 copper 黑-銅 flag 紅-白-藍-黑 gray 黑-白 hot 黑-紅-黃-白 hsv hsv顏色空間, 紅-黃-綠-青-藍-洋紅-紅 inferno 黑-紅-黃 jet 藍-青-黃-紅 magma 黑-紅-白 pink 黑-粉-白 plasma 綠-紅-黃 prism 紅-黃-綠-藍-紫-...-綠模式 spring 洋紅-黃 summer 綠-黃 viridis 藍-綠-黃 winter 藍-綠
用的比較多的有gray,jet等,如:
plt.imshow(image,plt.cm.gray) plt.imshow(img,cmap=plt.cm.jet)
在窗口上繪製完圖片後,返回一個AxesImage對象。要在窗口上顯示這個對象,咱們能夠調用show()函數來進行顯示,但進行練習的時候(ipython環境中),通常咱們能夠省略show()函數,也能自動顯示出來。
from skimage import io,data img=data.astronaut() dst=io.imshow(img) print(type(dst)) io.show()
能夠看到,類型是'matplotlib.image.AxesImage'。顯示一張圖片,咱們一般更願意這樣寫:
import matplotlib.pyplot as plt from skimage import io,data img=data.astronaut() plt.imshow(img) plt.show()
matplotlib是一個專業繪圖的庫,至關於matlab中的plot,能夠設置多個figure窗口,設置figure的標題,隱藏座標尺,甚至可使用subplot在一個figure中顯示多張圖片。通常咱們能夠這樣導入matplotlib庫:
import matplotlib.pyplot as plt
也就是說,咱們繪圖實際上用的是matplotlib包的pyplot模塊。
用figure函數和subplot函數分別建立主窗口與子圖
分開並同時顯示宇航員圖片的三個通道
from skimage import data import matplotlib.pyplot as plt img=data.astronaut() plt.figure(num='astronaut',figsize=(8,8)) #建立一個名爲astronaut的窗口,並設置大小 plt.subplot(2,2,1) #將窗口分爲兩行兩列四個子圖,則可顯示四幅圖片 plt.title('origin image') #第一幅圖片標題 plt.imshow(img) #繪製第一幅圖片 plt.subplot(2,2,2) #第二個子圖 plt.title('R channel') #第二幅圖片標題 plt.imshow(img[:,:,0],plt.cm.gray) #繪製第二幅圖片,且爲灰度圖 plt.axis('off') #不顯示座標尺寸 plt.subplot(2,2,3) #第三個子圖 plt.title('G channel') #第三幅圖片標題 plt.imshow(img[:,:,1],plt.cm.gray) #繪製第三幅圖片,且爲灰度圖 plt.axis('off') #不顯示座標尺寸 plt.subplot(2,2,4) #第四個子圖 plt.title('B channel') #第四幅圖片標題 plt.imshow(img[:,:,2],plt.cm.gray) #繪製第四幅圖片,且爲灰度圖 plt.axis('off') #不顯示座標尺寸 plt.show() #顯示窗口
在圖片繪製過程當中,咱們用matplotlib.pyplot模塊下的figure()函數來建立顯示窗口,該函數的格式爲:
matplotlib.pyplot.figure(num=None, figsize=None, dpi=None, facecolor=None, edgecolor=None)
全部參數都是可選的,都有默認值,所以調用該函數時能夠不帶任何參數,其中:
num: 整型或字符型均可以。若是設置爲整型,則該整型數字表示窗口的序號。若是設置爲字符型,則該字符串表示窗口的名稱。用該參數來命名窗口,若是兩個窗口序號或名相同,則後一個窗口會覆蓋前一個窗口。
figsize: 設置窗口大小。是一個tuple型的整數,如figsize=(8,8)
dpi: 整形數字,表示窗口的分辨率。
facecolor: 窗口的背景顏色。
edgecolor: 窗口的邊框顏色。
用figure()函數建立的窗口,只能顯示一幅圖片,若是想要顯示多幅圖片,則須要將這個窗口再劃分爲幾個子圖,在每一個子圖中顯示不一樣的圖片。咱們可使用subplot()函數來劃分子圖,函數格式爲:
matplotlib.pyplot.subplot(nrows, ncols, plot_number)
nrows: 子圖的行數。
ncols: 子圖的列數。
plot_number: 當前子圖的編號。
如:
plt.subplot(2,2,1)
則表示將figure窗口劃分紅了2行2列共4個子圖,當前爲第1個子圖。咱們有時也能夠用這種寫法:
plt.subplot(221)
兩種寫法效果是同樣的。每一個子圖的標題可用title()函數來設置,是否使用座標尺可用axis()函數來設置,如:
plt.subplot(221) plt.title("first subwindow") plt.axis('off')
用subplots來建立顯示窗口與劃分子圖
除了上面那種方法建立顯示窗口和劃分子圖,還有另一種編寫方法也能夠,以下例:
import matplotlib.pyplot as plt from skimage import data,color img = data.immunohistochemistry() hsv = color.rgb2hsv(img) fig, axes = plt.subplots(2, 2, figsize=(7, 6)) ax0, ax1, ax2, ax3 = axes.ravel() ax0.imshow(img) ax0.set_title("Original image") ax1.imshow(hsv[:, :, 0], cmap=plt.cm.gray) ax1.set_title("H") ax2.imshow(hsv[:, :, 1], cmap=plt.cm.gray) ax2.set_title("S") ax3.imshow(hsv[:, :, 2], cmap=plt.cm.gray) ax3.set_title("V") for ax in axes.ravel(): ax.axis('off') fig.tight_layout() #自動調整subplot間的參數
直接用subplots()函數來建立並劃分窗口。注意,比前面的subplot()函數多了一個s,該函數格式爲:
matplotlib.pyplot.subplots(nrows=1, ncols=1)
nrows: 全部子圖行數,默認爲1。
ncols: 全部子圖列數,默認爲1。
返回一個窗口figure, 和一個tuple型的ax對象,該對象包含全部的子圖,可結合ravel()函數列出全部子圖,如:
fig, axes = plt.subplots(2, 2, figsize=(7, 6))
ax0, ax1, ax2, ax3 = axes.ravel()
建立了2行2列4個子圖,分別取名爲ax0,ax1,ax2和ax3, 每一個子圖的標題用set_title()函數來設置,如:
ax0.imshow(img)
ax0.set_title("Original image")
若是有多個子圖,咱們還可使用tight_layout()函數來調整顯示的佈局,該函數格式爲:
matplotlib.pyplot.tight_layout(pad=1.08, h_pad=None, w_pad=None, rect=None)
全部的參數都是可選的,調用該函數時可省略全部的參數。
pad: 主窗口邊緣和子圖邊緣間的間距,默認爲1.08
h_pad, w_pad: 子圖邊緣之間的間距,默認爲 pad_inches
rect: 一個矩形區域,若是設置這個值,則將全部的子圖調整到這個矩形區域內。
通常調用爲:
plt.tight_layout() #自動調整subplot間的參數
其它方法繪圖並顯示
除了使用matplotlib庫來繪製圖片,skimage還有另外一個子模塊viewer,也提供一個函數來顯示圖片。不一樣的是,它利用Qt工具來建立一塊畫布,從而在畫布上繪製圖像。
例:
from skimage import data from skimage.viewer import ImageViewer img = data.coins() viewer = ImageViewer(img) viewer.show()
最後總結一下,繪製和顯示圖片經常使用到的函數有:
函數名 功能 調用格式 figure 建立一個顯示窗口 plt.figure(num=1,figsize=(8,8) imshow 繪製圖片 plt.imshow(image) show 顯示窗口 plt.show() subplot 劃分子圖 plt.subplot(2,2,1) title 設置子圖標題(與subplot結合使用) plt.title('origin image') axis 是否顯示座標尺 plt.axis('off') subplots 建立帶有多個子圖的窗口 fig,axes=plt.subplots(2,2,figsize=(8,8)) ravel 爲每一個子圖設置變量 ax0,ax1,ax2,ax3=axes.ravel() set_title 設置子圖標題(與axes結合使用) ax0.set_title('first window') tight_layout 自動調整子圖顯示佈局 plt.tight_layout()
有些時候,咱們不只要對一張圖片進行處理,可能還會對一批圖片處理。這時候,咱們能夠經過循環來執行處理,也能夠調用程序自帶的圖片集合來處理。
圖片集合函數爲:
skimage.io.ImageCollection(load_pattern,load_func=None)
這個函數是放在io模塊內的,帶兩個參數,第一個參數load_pattern, 表示圖片組的路徑,能夠是一個str字符串。第二個參數load_func是一個回調函數,咱們對圖片進行批量處理就能夠經過這個回調函數實現。回調函數默認爲imread(),即默認這個函數是批量讀取圖片。
先看一個例子:
import skimage.io as io from skimage import data_dir str=data_dir + '/*.png' coll = io.ImageCollection(str) print(len(coll))
顯示結果爲25, 說明系統自帶了25張png的示例圖片,這些圖片都讀取了出來,放在圖片集合coll裏。若是咱們想顯示其中一張圖片,則能夠在後加上一行代碼:
io.imshow(coll[10])
顯示爲:
若是一個文件夾裏,咱們既存放了一些jpg格式的圖片,又存放了一些png格式的圖片,如今想把它們所有讀取出來,該怎麼作呢?
import skimage.io as io from skimage import data_dir str='d:/pic/*.jpg:d:/pic/*.png' coll = io.ImageCollection(str) print(len(coll))
注意這個地方'd:/pic/.jpg:d:/pic/.png' ,是兩個字符串合在一塊兒的,第一個是'd:/pic/.jpg', 第二個是'd:/pic/.png' ,合在一塊兒後,中間用冒號來隔開,這樣就能夠把d:/pic/文件夾下的jpg和png格式的圖片都讀取出來。若是還想讀取存放在其它地方的圖片,也能夠一併加進去,只是中間一樣用冒號來隔開。
io.ImageCollection()這個函數省略第二個參數,就是批量讀取。若是咱們不是想批量讀取,而是其它批量操做,如批量轉換爲灰度圖,那又該怎麼作呢?
那就須要先定義一個函數,而後將這個函數做爲第二個參數,如:
from skimage import data_dir,io,color def convert_gray(f): rgb=io.imread(f) return color.rgb2gray(rgb) str=data_dir+'/*.png' coll = io.ImageCollection(str,load_func=convert_gray) io.imshow(coll[10])
這種批量操做對視頻處理是極其有用的,由於視頻就是一系列的圖片組合
from skimage import data_dir,io,color class AVILoader: video_file = 'myvideo.avi' def __call__(self, frame): return video_read(self.video_file, frame) avi_load = AVILoader() frames = range(0, 1000, 10) # 0, 10, 20, ...ic =io.ImageCollection(frames, load_func=avi_load)
這段代碼的意思,就是將myvideo.avi這個視頻中每隔10幀的圖片讀取出來,放在圖片集合中。
獲得圖片集合之後,咱們還能夠將這些圖片鏈接起來,構成一個維度更高的數組,鏈接圖片的函數爲:
skimage.io.concatenate_images(ic)
帶一個參數,就是以上的圖片集合,如:
from skimage import data_dir,io,color coll = io.ImageCollection('d:/pic/*.jpg') mat=io.concatenate_images(coll)
使用concatenate_images(ic)函數的前提是讀取的這些圖片尺寸必須一致,不然會出錯。咱們看看圖片鏈接先後的維度變化:
from skimage import data_dir,io,color coll = io.ImageCollection('d:/pic/*.jpg') print(len(coll)) #鏈接的圖片數量 print(coll[0].shape) #鏈接前的圖片尺寸,全部的都同樣 mat=io.concatenate_images(coll) print(mat.shape) #鏈接後的數組尺寸
顯示結果:
2 (870, 580, 3) (2, 870, 580, 3)
能夠看到,將2個3維數組,鏈接成了一個4維數組
若是咱們對圖片進行批量操做後,想把操做後的結果保存起來,也是能夠辦到的。
例:把系統自帶的全部png示例圖片,所有轉換成256256的jpg格式灰度圖,保存在d:/data/文件夾下*
改變圖片的大小,咱們可使用tranform模塊的resize()函數,後續會講到這個模塊。
from skimage import data_dir,io,transform,color import numpy as np def convert_gray(f): rgb=io.imread(f) #依次讀取rgb圖片 gray=color.rgb2gray(rgb) #將rgb圖片轉換成灰度圖 dst=transform.resize(gray,(256,256)) #將灰度圖片大小轉換爲256*256 return dst str=data_dir+'/*.png' coll = io.ImageCollection(str,load_func=convert_gray) for i in range(len(coll)): io.imsave('d:/data/'+np.str(i)+'.jpg',coll[i]) #循環保存圖片
結果:
圖像的形變與縮放,使用的是skimage的transform模塊,函數比較多,功能齊全。
一、改變圖片尺寸resize
函數格式爲:
skimage.transform.resize(image, output_shape)
image: 須要改變尺寸的圖片
output_shape: 新的圖片尺寸
from skimage import transform,data import matplotlib.pyplot as plt img = data.camera() dst=transform.resize(img, (80, 60)) plt.figure('resize') plt.subplot(121) plt.title('before resize') plt.imshow(img,plt.cm.gray) plt.subplot(122) plt.title('before resize') plt.imshow(dst,plt.cm.gray) plt.show()
將camera圖片由原來的512x512大小,變成了80x60大小。從下圖中的座標尺,咱們可以看出來:
二、按比例縮放rescale
函數格式爲:
skimage.transform.rescale(image, scale[, ...])
scale參數能夠是單個float數,表示縮放的倍數,也能夠是一個float型的tuple,如[0.2,0.5],表示將行列數分開進行縮放
from skimage import transform,data img = data.camera() print(img.shape) #圖片原始大小 print(transform.rescale(img, 0.1).shape) #縮小爲原來圖片大小的0.1 print(transform.rescale(img, [0.5,0.25]).shape) #縮小爲原來圖片行數一半,列數四分之一 print(transform.rescale(img, 2).shape) #放大爲原來圖片大小的2倍
結果爲:
(512, 512) (51, 51) (256, 128) (1024, 1024)
三、旋轉 rotate
skimage.transform.rotate(image, angle[, ...],resize=False)
angle參數是個float類型數,表示旋轉的度數
resize用於控制在旋轉時,是否改變大小 ,默認爲False
from skimage import transform,data import matplotlib.pyplot as plt img = data.camera() print(img.shape) #圖片原始大小 img1=transform.rotate(img, 60) #旋轉90度,不改變大小 print(img1.shape) img2=transform.rotate(img, 30,resize=True) #旋轉30度,同時改變大小 print(img2.shape) plt.figure('resize') plt.subplot(121)plt.title('rotate 60') plt.imshow(img1,plt.cm.gray) plt.subplot(122) plt.title('rotate 30') plt.imshow(img2,plt.cm.gray) plt.show()
顯示結果:
四、圖像金字塔
以多分辨率來解釋圖像的一種有效但概念簡單的結構就是圖像金字塔。圖像金字塔最初用於機器視覺和圖像壓縮,一幅圖像的金字塔是一系列以金字塔形狀排列的分辨率逐步下降的圖像集合。金字塔的底部是待處理圖像的高分辨率表示,而頂部是低分辨率的近似。當向金字塔的上層移動時,尺寸和分辨率就下降。
在此,咱們舉一個高斯金字塔的應用實例,函數原型爲:
skimage.transform.pyramid_gaussian(image, downscale=2)
downscale控制着金字塔的縮放比例
import numpy as np import matplotlib.pyplot as plt from skimage import data,transform image = data.astronaut() #載入宇航員圖片 rows, cols, dim = image.shape #獲取圖片的行數,列數和通道數 pyramid = tuple(transform.pyramid_gaussian(image, downscale=2)) #產生高斯金字塔圖像#共生成了log(512)=9幅金字塔圖像,加上原始圖像共10幅,pyramid[0]-pyramid[1] composite_image = np.ones((rows, cols + cols / 2, 3), dtype=np.double) #生成背景composite_image[:rows, :cols, :] = pyramid[0] #融合原始圖像 i_row = 0 for p in pyramid[1:]: n_rows, n_cols = p.shape[:2] composite_image[i_row:i_row + n_rows, cols:cols + n_cols] = p #循環融合9幅金字塔圖像 i_row += n_rows plt.imshow(composite_image) plt.show()
上右圖,就是10張金字塔圖像,下標爲0的表示原始圖像,後面每層的圖像行和列變爲上一層的一半,直至變爲1
除了高斯金字塔外,還有其它的金字塔,如:
skimage.transform.pyramid_laplacian(image, downscale=2)
圖像亮度與對比度的調整,是放在skimage包的exposure模塊裏面
一、gamma調整
原理:I=Ig
對原圖像的像素,進行冪運算,獲得新的像素值。公式中的g就是gamma值。
若是gamma>1, 新圖像比原圖像暗
若是gamma<1,新圖像比原圖像亮
函數格式爲:
skimage.exposure.adjust_gamma(image, gamma=1)
gamma參數默認爲1,原像不發生變化 。
from skimage import data, exposure, img_as_float import matplotlib.pyplot as plt image = img_as_float(data.moon()) gam1= exposure.adjust_gamma(image, 2) #調暗 gam2= exposure.adjust_gamma(image, 0.5) #調亮plt.figure('adjust_gamma',figsize=(8,8)) plt.subplot(131)plt.title('origin image') plt.imshow(image,plt.cm.gray)plt.axis('off') plt.subplot(132) plt.title('gamma=2') plt.imshow(gam1,plt.cm.gray) plt.axis('off') plt.subplot(133) plt.title('gamma=0.5') plt.imshow(gam2,plt.cm.gray) plt.axis('off') plt.show()
二、log對數調整
這個恰好和gamma相反
原理:I=log(I)
from skimage import data, exposure, img_as_float import matplotlib.pyplot as plt image = img_as_float(data.moon()) gam1= exposure.adjust_log(image) #對數調整 plt.figure('adjust_gamma',figsize=(8,8)) plt.subplot(121)plt.title('origin image') plt.imshow(image,plt.cm.gray) plt.axis('off') plt.subplot(122) plt.title('log') plt.imshow(gam1,plt.cm.gray) plt.axis('off') plt.show()
三、判斷圖像對比度是否偏低
函數:is_low_contrast(img)
返回一個bool型值
from skimage import data, exposure image =data.moon() result=exposure.is_low_contrast(image) print(result)
輸出爲False
四、調整強度
函數:
skimage.exposure.rescale_intensity(image, in_range='image', out_range='dtype')
in_range 表示輸入圖片的強度範圍,默認爲'image', 表示用圖像的最大/最小像素值做爲範圍
out_range 表示輸出圖片的強度範圍,默認爲'dype', 表示用圖像的類型的最大/最小值做爲範圍
默認狀況下,輸入圖片的[min,max]範圍被拉伸到[dtype.min, dtype.max],若是dtype=uint8, 那麼dtype.min=0, dtype.max=255
import numpy as np from skimage import exposure image = np.array([51, 102, 153], dtype=np.uint8) mat=exposure.rescale_intensity(image) print(mat)
輸出爲[ 0 127 255]
即像素最小值由51變爲0,最大值由153變爲255,總體進行了拉伸,可是數據類型沒有變,仍是uint8
前面咱們講過,能夠經過img_as_float()函數將unit8類型轉換爲float型,實際上還有更簡單的方法,就是乘以1.0
import numpy as np image = np.array([51, 102, 153], dtype=np.uint8) print(image*1.0)
即由[51,102,153]變成了[ 51. 102. 153.]
而float類型的範圍是[0,1],所以對float進行rescale_intensity 調整後,範圍變爲[0,1],而不是[0,255]
import numpy as np from skimage import exposure image = np.array([51, 102, 153], dtype=np.uint8) tmp=image*1.0 mat=exposure.rescale_intensity(tmp) print(mat)
結果爲[ 0. 0.5 1. ]
若是原始像素值不想被拉伸,只是等比例縮小,就使用in_range參數,如:
import numpy as np from skimage import exposure image = np.array([51, 102, 153], dtype=np.uint8) tmp=image*1.0 mat=exposure.rescale_intensity(tmp,in_range=(0,255)) print(mat)
輸出爲:[ 0.2 0.4 0.6],即原像素值除以255
若是參數in_range的[main,max]範圍要比原始像素值的範圍[min,max] 大或者小,那就進行裁剪,如:
mat=exposure.rescale_intensity(tmp,in_range=(0,102)) print(mat)
輸出[ 0.5 1. 1. ],即原像素值除以102,超出1的變爲1
若是一個數組裏面有負數,如今想調整到正數,就使用out_range參數。如:
import numpy as np from skimage import exposure image = np.array([-10, 0, 10], dtype=np.int8) mat=exposure.rescale_intensity(image, out_range=(0, 127)) print(mat)
輸出[ 0 63 127]
在圖像處理中,直方圖是很是重要,也是很是有用的一個處理要素。
在skimage庫中對直方圖的處理,是放在exposure這個模塊中。
一、計算直方圖
函數:
skimage.exposure.histogram(image, nbins=256)
在numpy包中,也提供了一個計算直方圖的函數histogram(),二者大同小義。
返回一個tuple(hist, bins_center), 前一個數組是直方圖的統計量,後一個數組是每一個bin的中間值
import numpy as np from skimage import exposure,data image =data.camera()*1.0 hist1=np.histogram(image, bins=2) #用numpy包計算直方圖hist2=exposure.histogram(image, nbins=2) #用skimage計算直方圖 print(hist1) print(hist2)
輸出:
(array([107432, 154712], dtype=int64), array([ 0. , 127.5, 255. ])) (array([107432, 154712], dtype=int64), array([ 63.75, 191.25]))
分紅兩個bin,每一個bin的統計量是同樣的,但numpy返回的是每一個bin的兩端的範圍值,而skimage返回的是每一個bin的中間值
二、繪製直方圖
繪圖均可以調用matplotlib.pyplot庫來進行,其中的hist函數能夠直接繪製直方圖。
調用方式:
n, bins, patches = plt.hist(arr, bins=10, normed=0, facecolor='black', edgecolor='black',alpha=1,histtype='bar')
hist的參數很是多,但經常使用的就這六個,只有第一個是必須的,後面四個可選
arr: 須要計算直方圖的一維數組 bins: 直方圖的柱數,可選項,默認爲10 normed: 是否將獲得的直方圖向量歸一化。默認爲0 facecolor: 直方圖顏色 edgecolor: 直方圖邊框顏色 alpha: 透明度 histtype: 直方圖類型,‘bar’, ‘barstacked’, ‘step’, ‘stepfilled’
返回值 :
n: 直方圖向量,是否歸一化由參數normed設定 bins: 返回各個bin的區間範圍 patches: 返回每一個bin裏面包含的數據,是一個list
from skimage import data import matplotlib.pyplot as plt img=data.camera() plt.figure("hist") arr=img.flatten() n, bins, patches = plt.hist(arr, bins=256, normed=1,edgecolor='None',facecolor='red') plt.show()
其中的flatten()函數是numpy包裏面的,用於將二維數組序列化成一維數組。
是按行序列,如
mat=[[1 2 3 4 5 6]]
通過 mat.flatten()後,就變成了
mat=[1 2 3 4 5 6]
三、彩色圖片三通道直方圖
通常來講直方圖都是徵對灰度圖的,若是要畫rgb圖像的三通道直方圖,實際上就是三個直方圖的疊加。
from skimage import data import matplotlib.pyplot as plt img=data.lena() ar=img[:,:,0].flatten() plt.hist(ar, bins=256, normed=1,facecolor='r',edgecolor='r',hold=1) ag=img[:,:,1].flatten() plt.hist(ag, bins=256, normed=1, facecolor='g',edgecolor='g',hold=1) ab=img[:,:,2].flatten() plt.hist(ab, bins=256, normed=1, facecolor='b',edgecolor='b') plt.show()
其中,加一個參數hold=1,表示能夠疊加
四、直方圖均衡化
若是一副圖像的像素佔有不少的灰度級並且分佈均勻,那麼這樣的圖像每每有高對比度和多變的灰度色調。直方圖均衡化就是一種能僅靠輸入圖像直方圖信息自動達到這種效果的變換函數。它的基本思想是對圖像中像素個數多的灰度級進行展寬,而對圖像中像素個數少的灰度進行壓縮,從而擴展取值的動態範圍,提升了對比度和灰度色調的變化,使圖像更加清晰。
from skimage import data,exposure import matplotlib.pyplot as plt img=data.moon() plt.figure("hist",figsize=(8,8)) arr=img.flatten() plt.subplot(221) plt.imshow(img,plt.cm.gray) #原始圖像 plt.subplot(222) plt.hist(arr, bins=256, normed=1,edgecolor='None',facecolor='red') #原始圖像直方圖 img1=exposure.equalize_hist(img) arr1=img1.flatten() plt.subplot(223) plt.imshow(img1,plt.cm.gray) #均衡化圖像 plt.subplot(224) plt.hist(arr1, bins=256, normed=1,edgecolor='None',facecolor='red') #均衡化直方圖 plt.show()
skimage.exposure.``equalize_adapthist
(image, kernel_size=None, clip_limit=0.01, nbins=256)
Contrast Limited Adaptive Histogram Equalization (CLAHE).
An algorithm for local contrast enhancement, that uses histograms computed over different tile regions of the image. Local details can therefore be enhanced even in regions that are darker or lighter than most of the image.
image : (M, N[, C]) ndarray
Input image.
kernel_size: integer or list-like, optional
Defines the shape of contextual regions used in the algorithm. If iterable is passed, it must have the same number of elements asimage.ndim
(without color channel). If integer, it is broadcasted to each image dimension. By default,kernel_size
is 1/8 ofimage
height by 1/8 of its width.
clip_limit : float, optional
Clipping limit, normalized between 0 and 1 (higher values give more contrast).
nbins : int, optional
Number of gray bins for histogram (「data range」).
| Returns: |
out : (M, N[, C]) ndarray
Equalized image.
http://scikit-image.org/docs/dev/api/skimage.exposure.html#equalize-adapthist
from skimage import data,exposure import matplotlib.pyplot as plt #%matplotlib notebook clip_limitnumber=0.01 img=data.moon() print(img.shape) plt.figure("hist",figsize=(8,8)) arr=img.flatten() plt.subplot(5,2,1) plt.title('original') plt.imshow(img,plt.cm.gray) #原始圖像 plt.subplot(5,2,2) plt.hist(arr, bins=256, normed=1,edgecolor='None',facecolor='red') #原始圖像直方圖 # #img1=exposure.equalize_hist(img) # img1=exposure.equalize_hist(img) # arr1=img1.flatten() # plt.subplot(6,2,3) # plt.title('equalize_hist') # plt.imshow(img1,plt.cm.gray) #均衡化圖像 # plt.subplot(6,2,4) # plt.hist(arr1, bins=256, normed=1,edgecolor='None',facecolor='red') #均衡化直方圖 # plt.show() img2=exposure.equalize_adapthist(img, kernel_size=256, clip_limit=clip_limitnumber, nbins=256) arr2=img2.flatten() plt.subplot(5,2,3) plt.title('equalize_adapthist-256-'+ str(clip_limitnumber)) plt.imshow(img2,plt.cm.gray) #均衡化圖像 plt.subplot(5,2,4) plt.hist(arr2, bins=256, normed=1,edgecolor='None',facecolor='red') #均衡化直方圖 plt.show() img3=exposure.equalize_adapthist(img, kernel_size=128, clip_limit=clip_limitnumber, nbins=256) arr3=img3.flatten() plt.subplot(5,2,5) plt.title('equalize_adapthist-128-'+ str(clip_limitnumber)) plt.imshow(img3,plt.cm.gray) #均衡化圖像 plt.subplot(5,2,6) plt.hist(arr3, bins=256, normed=1,edgecolor='None',facecolor='red') #均衡化直方圖 plt.show() img4=exposure.equalize_adapthist(img, kernel_size=64, clip_limit=clip_limitnumber, nbins=256) arr4=img4.flatten() plt.subplot(5,2,7) plt.title('equalize_adapthist-64-'+ str(clip_limitnumber)) plt.imshow