日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

python的窗口处理模块_python的图像处理模块

發(fā)布時(shí)間:2025/4/17 80 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python的窗口处理模块_python的图像处理模块 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

除了opencv專門用來(lái)進(jìn)行圖像處理,可以進(jìn)行像素級(jí)、特征級(jí)、語(yǔ)義級(jí)、應(yīng)用級(jí)的圖像處理外,python中還有其他庫(kù)用來(lái)進(jìn)行簡(jiǎn)單的圖像處理,比如圖像的讀入和保存、濾波、直方圖均衡等簡(jiǎn)單的操作,下面對(duì)這些庫(kù)進(jìn)行詳細(xì)的介紹。

目錄

一、PIL庫(kù)

一、安裝命令sudo apt-get install python-imaging

二、Image模塊

Image模塊是在Python PIL圖像處理中常見(jiàn)的模塊,對(duì)圖像進(jìn)行基礎(chǔ)操作的功能基本都包含于此模塊內(nèi)。如open、save、conver、show…等功能。

open類Image.open(file) ? image

Image.open(file, mode) ? image

要從文件加載圖像,使用 open() 函數(shù), 在 Image 模塊:@zhangziju

from PIL import Image ##調(diào)用庫(kù)

im = Image.open("E:\mywife.jpg") ##文件存在的路徑

im.show()

需要知道的是在win的環(huán)境下im.show的方式為win自帶的圖像顯示應(yīng)用。打開(kāi)并確認(rèn)給定的圖像文件。這個(gè)是一個(gè)懶操作;該函數(shù)只會(huì)讀文件頭,而真實(shí)的圖像數(shù)據(jù)直到試圖處理該數(shù)據(jù)才會(huì)從文件讀取(調(diào)用load()方法將強(qiáng)行加載圖像數(shù)據(jù))。如果變量mode被設(shè)置,那必須是“r”。用戶可以使用一個(gè)字符串(表示文件名稱的字符串)或者文件對(duì)象作為變量file的值。文件對(duì)象必須實(shí)現(xiàn)read(),seek()和tell()方法,并且以二進(jìn)制模式打開(kāi)。

Save類im.save(outfile,options…)

im.save(outfile, format, options…)

若要保存文件,則使用 Image 類的 save() 方法,此時(shí)保存文件的文件名就變得十分重要了,除非指定格式,否則這個(gè)庫(kù)將會(huì)以文件名的擴(kuò)展名作為格式保存。使用給定的文件名保存圖像。如果變量format缺省,如果可能的話,則從文件名稱的擴(kuò)展名判斷文件的格式。該方法返回為空。關(guān)鍵字options為文件編寫(xiě)器提供一些額外的指令。如果編寫(xiě)器不能識(shí)別某個(gè)選項(xiàng),它將忽略它。用戶可以使用文件對(duì)象代替文件名稱。在這種情況下,用戶必須指定文件格式。文件對(duì)象必須實(shí)現(xiàn)了seek()、tell()和write()方法,且其以二進(jìn)制模式打開(kāi)。如果方法save()因?yàn)槟承┰蚴?#xff0c;這個(gè)方法將產(chǎn)生一個(gè)異常(通常為IOError異常)。如果發(fā)生了異常,該方法也有可能已經(jīng)創(chuàng)建了文件,并向文件寫(xiě)入了一些數(shù)據(jù)。如果需要的話,用戶的應(yīng)用程序可以刪除這個(gè)不完整的文件。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

print(im)

im.save("E:\mywife.png") ## 將"E:\mywife.jpg"保存為"E:\mywife.png"

im = Image.open("E:\mywife.png") ##打開(kāi)新的png圖片

print(im.format, im.size, im.mode)

如下圖,在指定路徑下可看到新保存的png格式的圖片。

三、format類im.format ? string or None

這個(gè)屬性標(biāo)識(shí)了圖像來(lái)源,如果圖像不是從文件讀取它的值就是None。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

print(im.format) ## 打印出格式信息

im.show()

如下圖可以看到其format為”JPEG”。

四、Mode類im.mode ? string

圖像的模式,常見(jiàn)的mode 有 “L” (luminance) 表示灰度圖像,“RGB”表示真彩色圖像,和 “CMYK” 表示出版圖像,表明圖像所使用像素格式。如面為常見(jiàn)的nodes描述:modes ?? ?????? 描述

1 ?? ?????????????? 1位像素,黑和白,存成8位的像素

L ?? ?????????????? 8位像素,黑白

P ?? ?????????????? 8位像素,使用調(diào)色板映射到任何其他模式

RGB ?? ? ? ? ??? 3× 8位像素,真彩

RGBA ?? ?????? 4×8位像素,真彩+透明通道

CMYK ?? ?????? 4×8位像素,顏色隔離

YCbCr ?? ?????? 3×8位像素,彩色視頻格式

I ?? ???????????????? 32位整型像素

F ?? ??????????????? 32位浮點(diǎn)型像素@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

print(im.mode) ## 打印出模式信息

im.show()

如下圖為圖片的mode為“RGB”模式。

五、convert類im.convert(mode)? image

將當(dāng)前圖像轉(zhuǎn)換為其他模式,并且返回新的圖像。當(dāng)從一個(gè)調(diào)色板圖像轉(zhuǎn)換時(shí),這個(gè)方法通過(guò)這個(gè)調(diào)色板來(lái)轉(zhuǎn)換像素。如果不對(duì)變量mode賦值,該方法將會(huì)選擇一種模式,在沒(méi)有調(diào)色板的情況下,使得圖像和調(diào)色板中的所有信息都可以被表示出來(lái)。當(dāng)從一個(gè)顏色圖像轉(zhuǎn)換為黑白圖像時(shí),PIL庫(kù)使用ITU-R601-2 luma轉(zhuǎn)換公式:L = R * 299/1000 + G * 587/1000 + B * 114/1000

當(dāng)轉(zhuǎn)換為2位圖像(模式“1”)時(shí),源圖像首先被轉(zhuǎn)換為黑白圖像。結(jié)果數(shù)據(jù)中大于127的值被設(shè)置為白色,其他的設(shè)置為黑色;這樣圖像會(huì)出現(xiàn)抖動(dòng)。如果要使用其他閾值,更改閾值127,可以使用方法point()。為了去掉圖像抖動(dòng)現(xiàn)象,可以使用dither選項(xiàng)。from PIL import Image

im = Image.open("E:\mywife.jpg")

new_im = im.convert('P')

print(new_im.mode)

new_im.show()

如下,將圖像轉(zhuǎn)換為“P”模式。

對(duì)比原始圖像。

這里寫(xiě)圖片描述im.convert(“P”,**options) ? image

這個(gè)與第一個(gè)方法定義一樣,但是當(dāng)“RGB”圖像轉(zhuǎn)換為8位調(diào)色板圖像時(shí)能更好的處理。可供選擇的選項(xiàng)為:

Dither=. 控制顏色抖動(dòng)。默認(rèn)是FLOYDSTEINBERG,與鄰近的像素一起承擔(dān)錯(cuò)誤。不使能該功能,則賦值為NONE。

Palette=. 控制調(diào)色板的產(chǎn)生。默認(rèn)是WEB,這是標(biāo)準(zhǔn)的216色的“web palette”。要使用優(yōu)化的調(diào)色板,則賦值為ADAPTIVE。

Colors=. 當(dāng)選項(xiàng)palette為ADAPTIVE時(shí),控制用于調(diào)色板的顏色數(shù)目。默認(rèn)是最大值,即256種顏色im.convert(mode,matrix) ? image

使用轉(zhuǎn)換矩陣將一個(gè)“RGB”圖像轉(zhuǎn)換為“L”或者“RGB”圖像。變量matrix為4或者16元組。from PIL import Image

im = Image.open("E:\mywife.jpg")

print(im.mode)

rgb2xyz = (0.412453,0.357580, 0.180423, 0,

0.212671,0.715160, 0.072169, 0,

0.019334,0.119193, 0.950227, 0 )

new_im = im.convert("L", rgb2xyz)

print(new_im.mode)

new_im.show()

轉(zhuǎn)換后效果

這里寫(xiě)圖片描述

Size類

六、size類im.size ? (width, height)

圖像的尺寸,按照像素?cái)?shù)計(jì)算,它的返回值為寬度和高度的二元組(width, height)。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

print(im.size) ## 打印出尺寸信息

im.show()

如下圖所示為圖片的尺寸信息,750*560。

七、Palette類im.palette ? palette or None

顏色調(diào)色板表格。如果圖像的模式是“P”,則返回ImagePalette類的實(shí)例;否則,將為None。

如下為對(duì)非“P”模式下的圖像進(jìn)行palette信息顯示。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

print(im.palette)

易知,返回值為空,none

對(duì)圖像進(jìn)行convert操作,轉(zhuǎn)換成“P”模式@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

new_im = im.convert('P')

print(new_im.mode)

print(new_im.palette)

則返回值為ImagePalette類的實(shí)例。如下:

八、Info類im.info ? dictionary

存儲(chǔ)圖像相關(guān)數(shù)據(jù)的字典。文件句柄使用該字典傳遞從文件中讀取的各種非圖像信息。大多數(shù)方法在返回新的圖像時(shí)都會(huì)忽略這個(gè)字典;因?yàn)樽值渲械逆I并非標(biāo)準(zhǔn)化的,對(duì)于一個(gè)方法,它不能知道自己的操作如何影響這個(gè)字典。如果用戶需要這些信息,需要在方法open()返回時(shí)保存這個(gè)字典。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

print(im.info)

九、new類Image.new(mode,size) ? image

Image.new(mode, size,color) ? image

使用給定的變量mode和size生成新的圖像。Size是給定的寬/高二元組,這是按照像素?cái)?shù)來(lái)計(jì)算的。對(duì)于單通道圖像,變量color只給定一個(gè)值;對(duì)于多通道圖像,變量color給定一個(gè)元組(每個(gè)通道對(duì)應(yīng)一個(gè)值)。在版本1.1.4及其之后,用戶也可以用顏色的名稱,比如給變量color賦值為“red”。如果沒(méi)有對(duì)變量color賦值,圖像內(nèi)容將會(huì)被全部賦值為0(為黑色)。如果變量color是空,圖像將不會(huì)被初始化,即圖像的內(nèi)容全為0。這對(duì)向該圖像復(fù)制或繪制某些內(nèi)容是有用的。

如下為將圖像設(shè)置為128x128大小的紅色圖像。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

n_im= Image.new("RGB", (128, 128), "#FF0000")

n_im.show()

顯示效果如下:

如下圖像為128x128大小的黑色圖像,因?yàn)樽兞縞olor不賦值的話,圖像內(nèi)容被設(shè)置為0,即黑色。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

n_im= Image.new("RGB", (128, 128))

n_im.show()

黑圖像為128x128大小的綠色圖像。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

n_im= Image.new("RGB", (128, 128),"green")

n_im.show()

十、Copy 類im.copy() ? image

拷貝這個(gè)圖像。如果用戶想粘貼一些數(shù)據(jù)到這張圖,可以使用這個(gè)方法,但是原始圖像不會(huì)受到影響。from PIL import Image

im = Image.open("E:\mywife.jpg")

im_copy = im.copy()

圖像im_copy和im完全一樣。

十一、Crop類im.crop(box) ? image

從當(dāng)前的圖像中返回一個(gè)矩形區(qū)域的拷貝。變量box是一個(gè)四元組,定義了左、上、右和下的像素坐標(biāo)。用來(lái)表示在原始圖像中截取的位置坐標(biāo),如box(100,100,200,200)就表示在原始圖像中以左上角為坐標(biāo)原點(diǎn),截取一個(gè)100*100(像素為單位)的圖像,為方便理解,如下為示意圖box(b1,a1,b2,a2)。作圖軟件為Visio2016。這是一個(gè)懶操作。對(duì)源圖像的改變可能或者可能不體現(xiàn)在裁減下來(lái)的圖像中。為了獲取一個(gè)分離的拷貝,對(duì)裁剪的拷貝調(diào)用方法load()。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

box = (300, 100, 700, 700) ##確定拷貝區(qū)域大小

region = im.crop(box) ##將im表示的圖片對(duì)象拷貝到region中,大小為box

region.show()

如下圖為box截取的圖像區(qū)域顯示。

十二、Paste類im.paste(image,box)

將一張圖粘貼到另一張圖像上。變量box或者是一個(gè)給定左上角的2元組,或者是定義了左,上,右和下像素坐標(biāo)的4元組,或者為空(與(0,0)一樣)。如果給定4元組,被粘貼的圖像的尺寸必須與區(qū)域尺寸一樣。如果模式不匹配,被粘貼的圖像將被轉(zhuǎn)換為當(dāng)前圖像的模式。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

box=[0,0,100,100]

im_crop = im.crop(box)

print(im_crop.size,im_crop.mode)

im.paste(im_crop, (100,100)) ##(100,100,0,0)

im.paste(im_crop, (400,400,500,500))

im.show()

如下圖為paste操作:

十三、Filter類im.filter(filter) ? image

返回一個(gè)使用給定濾波器處理過(guò)的圖像的拷貝。具體參考圖像濾波在ImageFilter 模塊的應(yīng)用,在該模塊中,預(yù)先定義了很多增強(qiáng)濾波器,可以通過(guò)filter( )函數(shù)使用,預(yù)定義濾波器包括:BLUR、CONTOUR、DETAIL、EDGE_ENHANCE、EDGE_ENHANCE_MORE、EMBOSS、FIND_EDGES、SMOOTH、SMOOTH_MORE、SHARPEN。其中BLUR就是均值濾波,CONTOUR找輪廓,FIND_EDGES邊緣檢測(cè),使用該模塊時(shí),需先導(dǎo)入。@zhangziju

from PIL import Image

from PIL import ImageFilter ## 調(diào)取ImageFilter

imgF = Image.open("E:\mywife.jpg")

bluF = imgF.filter(ImageFilter.BLUR) ##均值濾波

conF = imgF.filter(ImageFilter.CONTOUR) ##找輪廓

edgeF = imgF.filter(ImageFilter.FIND_EDGES) ##邊緣檢測(cè)

imgF.show()

bluF.show()

conF.show()

edgeF.show()

濾波處理下的gakki~

十四、Blend類Image.blend(image1,image2, alpha) ? image

使用給定的兩張圖像及透明度變量alpha,插值出一張新的圖像。這兩張圖像必須有一樣的尺寸和模式。合成公式為:out = image1 (1.0 - alpha) + image2 alpha

若變量alpha為0.0,返回第一張圖像的拷貝。若變量alpha為1.0,將返回第二張圖像的拷貝。對(duì)變量alpha的值無(wú)限制。@zhangziju

from PIL import Image

im1 = Image.open("E:\mywife.jpg")

im2 = Image.open("E:\mywife2.jpg")

print(im1.mode,im1.size)

print(im2.mode,im2.size)

im = Image.blend(im1, im2, 0.2)

im.show()

需保證兩張圖像的模式和大小是一致的,如下為顯示im1和im2的具體信息。

im1和im2按照第一張80%的透明度,第二張20%的透明度,合成為一張。

十五、Splitim.split() ? sequence

返回當(dāng)前圖像各個(gè)通道組成的一個(gè)元組。例如,分離一個(gè)“RGB”圖像將產(chǎn)生三個(gè)新的圖像,分別對(duì)應(yīng)原始圖像的每個(gè)通道(紅,綠,藍(lán))。from PIL import Image

im = Image.open("E:\mywife.jpg")

r,g,b = im.split()

print(r.mode)

print(r.size)

print(im.size)

十六、Composite類Image.composite(image1,image2, mask) ? image

復(fù)合類使用給定的兩張圖像及mask圖像作為透明度,插值出一張新的圖像。變量mask圖像的模式可以為“1”,“L”或者“RGBA”。所有圖像必須有相同的尺寸。@zhangziju

from PIL import Image

im1 = Image.open("E:\mywife.jpg")

im2 = Image.open("E:\mywife2.jpg")

r,g,b = im1.split() ##分離出r,g,b

print(b.mode)

print(im1.mode,im1.size)

print(im2.mode,im2.size)

im = Image.composite(im1,im2,b)

im.show()

十七、Eval類Image.eval(image,function) ? image

使用變量function對(duì)應(yīng)的函數(shù)(該函數(shù)應(yīng)該有一個(gè)參數(shù))處理變量image所代表圖像中的每一個(gè)像素點(diǎn)。如果變量image所代表圖像有多個(gè)通道,那變量function對(duì)應(yīng)的函數(shù)作用于每一個(gè)通道。注意:變量function對(duì)每個(gè)像素只處理一次,所以不能使用隨機(jī)組件和其他生成器。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

def fun01(x):

return x*0.3

def fun02(y):

return y*2.0

im1_eval = Image.eval(im, fun01)

im2_eval = Image.eval(im, fun02)

im1_eval.show()

im2_eval.show()

在函數(shù)fun01和fun02下的圖像顯示。

十八、Merge類Image.merge(mode,bands) ? image

合并類使用一些單通道圖像,創(chuàng)建一個(gè)新的圖像。變量bands為一個(gè)圖像的元組或者列表,每個(gè)通道的模式由變量mode描述。所有通道必須有相同的尺寸。

變量mode與變量bands的關(guān)系:len(ImageMode.getmode(mode).bands)= len(bands)@zhangziju

from PIL import Image

im1 = Image.open("E:\mywife.jpg")

im2 = Image.open("E:\mywife2.jpg")

r1,g1,b1 = im1.split()

r2,g2,b2 = im2.split()

print(r1.mode,r1.size,g1.mode,g1.size)

print(r2.mode,r2.size,g2.mode,g2.size)

new_im=[r1,g2,b2]

print(len(new_im))

im_merge = Image.merge("RGB",new_im)

im_merge.show()

打印信息顯示

merge操作

十九、Draft類im.draft(mode,size)

配置圖像文件加載器,使得返回一個(gè)與給定的模式和尺寸盡可能匹配的圖像的版本。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

print(im.size,im.mode)

new_im = im.draft("L", (200,200))

print(new_im.size,new_im.mode)

new_im.show()

關(guān)鍵信息顯示

轉(zhuǎn)換效果

二十、Getbands類im.getbands()? tuple of strings

返回包括每個(gè)通道名稱的元組。例如,對(duì)于RGB圖像將返回(“R”,“G”,“B”)。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

print(im.getbands())

這里寫(xiě)圖片描述

二十一、Getbbox類im.getbbox() ? 4-tuple or None

計(jì)算圖像非零區(qū)域的包圍盒。這個(gè)包圍盒是一個(gè)4元組,定義了左、上、右和下像素坐標(biāo)。如果圖像是空的,這個(gè)方法將返回空。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

print(im.getbbox())

二十二、Getdata類im.getdata() ? sequence

以包含像素值的sequence對(duì)象形式返回圖像的內(nèi)容。這個(gè)sequence對(duì)象是扁平的,以便第一行的值直接跟在第零行的值后面,等等。這個(gè)方法返回的sequence對(duì)象是PIL內(nèi)部數(shù)據(jù)類型,它只支持某些sequence操作,包括迭代和基礎(chǔ)sequence訪問(wèn)。使用list(im.getdata()),將它轉(zhuǎn)換為普通的sequence。Sequence對(duì)象的每一個(gè)元素對(duì)應(yīng)一個(gè)像素點(diǎn)的R、G和B三個(gè)值。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

sequ = im.getdata()

sequ0 = list(sequ)

print(sequ0[0])

print(sequ0[1])

print(sequ0[2])

可視化顯示sequence0里面的數(shù)據(jù)。

打印顯示結(jié)果,與前面對(duì)比。

二十三、Getextrema類im.getextrema() ? 2-tuple

返回一個(gè)2元組,包括該圖像中的最小和最大值。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

print(im.getextrema())

該方法返回了R/G/B三個(gè)通道的最小和最大值的2元組。

二十四、Getpixel類im.getpixel(xy) ? value or tuple

返回給定位置的像素值。如果圖像為多通道,則返回一個(gè)元組。該方法執(zhí)行比較慢;如果用戶需要使用python處理圖像中較大部分?jǐn)?shù)據(jù),可以使用像素訪問(wèn)對(duì)象(見(jiàn)load),或者方法getdata()。@zahngziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

print(im.getpixel((0,0)))

print(im.getpixel((4,0)))

r,g,b = im.split()

print(b.getpixel((11,8)))

二十五、Histogram類im.histogram()? list

返回一個(gè)圖像的直方圖。這個(gè)直方圖是關(guān)于像素?cái)?shù)量的list,圖像中的每個(gè)象素值對(duì)應(yīng)一個(gè)成員。如果圖像有多個(gè)通道,所有通道的直方圖會(huì)連接起來(lái)(例如,“RGB”圖像的直方圖有768個(gè)值)。二值圖像(模式為“1”)當(dāng)作灰度圖像(模式為“L”)處理。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

imhis = im.histogram()

print(len(imhis))

print(imhis[0])

print(imhis[150])

print(imhis[300])im.histogram(mask)? list

返回圖像中模板圖像非零地方的直方圖。模板圖像與處理圖像的尺寸必須相同,并且要么是二值圖像(模式為“1”),要么為灰度圖像(模式為“L”)。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

r,g,b = im.split()

imhis = im.histogram()

print(r.mode)

print(len(imhis))

print(imhis[0])

print(imhis[150])

print(imhis[300])

二十六、Load類im.load()

為圖像分配內(nèi)存并從文件中加載它(或者從源圖像,對(duì)于懶操作)。正常情況下,用戶不需要調(diào)用這個(gè)方法,因?yàn)樵诘谝淮卧L問(wèn)圖像時(shí),Image類會(huì)自動(dòng)地加載打開(kāi)的圖像。在1.1.6及以后的版本,方法load()返回一個(gè)用于讀取和修改像素的像素訪問(wèn)對(duì)象。這個(gè)訪問(wèn)對(duì)象像一個(gè)二維隊(duì)列,如:pix = im.load()

print pix[x, y]

pix[x, y] =value

通過(guò)這個(gè)對(duì)象訪問(wèn)比方法getpixel()和putpixel()快很多。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

pix = im.load()

print(pix[0,2])im.paste(colour,box)

使用同一種顏色填充變量box對(duì)應(yīng)的區(qū)域。對(duì)于單通道圖像,變量colour為單個(gè)顏色值;對(duì)于多通道,則為一個(gè)元組。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

im.paste((256,256,0),(0,0,100,100)) ##(256,256,0)表示黃色

im.show()@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

im.paste("blue",(0,0,100,100)) ##或者“blue”

im.show()im.paste(image,box, mask)

使用變量mask對(duì)應(yīng)的模板圖像來(lái)填充所對(duì)應(yīng)的區(qū)域??梢允褂媚J綖椤?”、“L”或者“RGBA”的圖像作為模板圖像。模板圖像的尺寸必須與變量image對(duì)應(yīng)的圖像尺寸一致。如果變量mask對(duì)應(yīng)圖像的值為255,則模板圖像的值直接被拷貝過(guò)來(lái);如果變量mask對(duì)應(yīng)圖像的值為0,則保持當(dāng)前圖像的原始值。變量mask對(duì)應(yīng)圖像的其他值,將對(duì)兩張圖像的值進(jìn)行透明融合,如果變量image對(duì)應(yīng)的為“RGBA”圖像,即粘貼的圖像模式為“RGBA”,則alpha通道被忽略。用戶可以使用同樣的圖像作為原圖像和模板圖像。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

box=[300,300,400,400]

im_crop =im.crop(box)

r,g,b =im_crop.split()

im.paste(im_crop, (200,200,300,300), r)

im.show()

二十七、Putdata類im.putdata(data)

im.putdata(data, scale, offset)

從sequence對(duì)象中拷貝數(shù)據(jù)到當(dāng)前圖像,從圖像的左上角(0,0)位置開(kāi)始。變量scale和offset用來(lái)調(diào)整sequence中的值:pixel = value*scale + offset

如果變量scale忽略,則默認(rèn)為1.0。如果變量offset忽略,則默認(rèn)為0.0。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

r, g, b = im.split()

print(

r.getpixel((0, 0)),

r.getpixel((1, 0)),

r.getpixel((2, 0)),

r.getpixel((3, 0)),

r.putdata([1, 2, 3, 4]),

r.getpixel((0, 0)),

r.getpixel((1, 0)),

r.getpixel((2, 0)),

r.getpixel((3, 0)),

)

二十八、Resize類im.resize(size) ? image

im.resize(size, filter) ? image

返回改變尺寸的圖像的拷貝。變量size是所要求的尺寸,是一個(gè)二元組:(width, height)。變量filter為NEAREST、BILINEAR、BICUBIC或者ANTIALIAS之一。如果忽略,或者圖像模式為“1”或者“P”,該變量設(shè)置為NEAREST。在當(dāng)前的版本中bilinear和bicubic濾波器不能很好地適應(yīng)大比例的下采樣(例如生成縮略圖)。用戶需要使用ANTIALIAS,除非速度比質(zhì)量更重要。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

region = im.resize((400, 400)) ##重新設(shè)定大小

region.show()

很明顯由于大小的重新設(shè)定,圖片的顯示效果有所轉(zhuǎn)變,gakki依然美膩~

二十九、Rotate類im.rotate(angle) ? image

im.rotate(angle,filter=NEAREST, expand=0) ? image

返回一個(gè)按照給定角度順時(shí)鐘圍繞圖像中心旋轉(zhuǎn)后的圖像拷貝。變量filter是NEAREST、BILINEAR或者BICUBIC之一。如果省略該變量,或者圖像模式為“1”或者“P”,則默認(rèn)為NEAREST。變量expand,如果為true,表示輸出圖像足夠大,可以裝載旋轉(zhuǎn)后的圖像。如果為false或者缺省,則輸出圖像與輸入圖像尺寸一樣大。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

im_45 = im.rotate(45)

im_30 = im.rotate(30, Image.NEAREST,1)

print(im_45.size,im_30.size)

im_45.show()

im_30.show()

三十、Seek類im.seek(frame)

在給定的文件序列中查找指定的幀。如果查找超越了序列的末尾,則產(chǎn)生一個(gè)EOFError異常。當(dāng)文件序列被打開(kāi)時(shí),PIL庫(kù)自動(dòng)指定到第0幀上。@zhangziju

from PIL import Image

im_gif = Image.open("E:\mywife.gif")

print(im_gif.mode)

im_gif.show() ##第0幀

im_gif.seek(3)

im_gif.show()

im_gif.seek(9)

im_gif.show()

來(lái)來(lái)來(lái)~這是gakki原圖欣賞下~

這里寫(xiě)圖片描述

查找?guī)瑂eek()的效果如下:

三十一、Tell類im.tell() ? integer

返回當(dāng)前幀所處位置,從0開(kāi)始計(jì)算。@zhangziju

from PIL import Image

im_gif = Image.open("E:\mywife.gif")

print(im_gif.tell())

im_gif.seek(8)

print(im_gif.tell())

三十二、Thumbnail類im.thumbnail(size)

im.thumbnail(size, filter)

修改當(dāng)前圖像,使其包含一個(gè)自身的縮略圖,該縮略圖尺寸不大于給定的尺寸。這個(gè)方法會(huì)計(jì)算一個(gè)合適的縮略圖尺寸,使其符合當(dāng)前圖像的寬高比,調(diào)用方法draft()配置文件讀取器,最后改變圖像的尺寸。變量filter應(yīng)該是NEAREST、BILINEAR、BICUBIC或者ANTIALIAS之一。如果省略該變量,則默認(rèn)為NEAREST。注意:在當(dāng)前PIL的版本中,濾波器bilinear和bicubic不能很好地適應(yīng)縮略圖產(chǎn)生。用戶應(yīng)該使用ANTIALIAS,圖像質(zhì)量最好。如果處理速度比圖像質(zhì)量更重要,可以選用其他濾波器。這個(gè)方法在原圖上進(jìn)行修改。如果用戶不想修改原圖,可以使用方法copy()拷貝一個(gè)圖像。這個(gè)方法返回空。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

im.thumbnail((100,100))

三十三、Transform類im.transform(size,method, data) ? image

im.transform(size, method, data, filter) ? image

使用給定的尺寸生成一張新的圖像,與原圖有相同的模式,使用給定的轉(zhuǎn)換方式將原圖數(shù)據(jù)拷貝到新的圖像中。在當(dāng)前的PIL版本中,參數(shù)method為EXTENT(裁剪出一個(gè)矩形區(qū)域),AFFINE(仿射變換),QUAD(將正方形轉(zhuǎn)換為矩形),MESH(一個(gè)操作映射多個(gè)正方形)或者PERSPECTIVE。變量filter定義了對(duì)原始圖像中像素的濾波器。在當(dāng)前的版本中,變量filter為NEAREST、BILINEAR、BICUBIC或者ANTIALIAS之一。如果忽略,或者圖像模式為“1”或者“P”,該變量設(shè)置為NEAREST。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

print(im.size)

imtra = im.transform((200, 200), Image.EXTENT, (0, 0, 500, 500))

print(imtra.size)

imtra.show()im.transform(size,EXTENT, data) ? image

im.transform(size, EXTENT, data, filter) ? image

從圖像中裁剪一個(gè)區(qū)域。變量data為指定輸入圖像中兩個(gè)坐標(biāo)點(diǎn)的4元組(x0,y0,x1,y1)。輸出圖像為這兩個(gè)坐標(biāo)點(diǎn)之間像素的采樣結(jié)果。例如,如果輸入圖像的(x0,y0)為輸出圖像的(0,0)點(diǎn),(x1,y1)則與變量size一樣。這個(gè)方法可以用于在當(dāng)前圖像中裁剪,放大,縮小或者鏡像一個(gè)任意的長(zhǎng)方形。它比方法crop()稍慢,但是與resize操作一樣快。im.transform(size, AFFINE, data) ? image

im.transform(size, AFFINE,data, filter) ? image

對(duì)當(dāng)前的圖像進(jìn)行仿射變換,變換結(jié)果體現(xiàn)在給定尺寸的新圖像中。變量data是一個(gè)6元組(a,b,c,d,e,f),包含一個(gè)仿射變換矩陣的第一個(gè)兩行。輸出圖像中的每一個(gè)像素(x,y),新值由輸入圖像的位置(ax+by+c, dx+ey+f)的像素產(chǎn)生,使用最接近的像素進(jìn)行近似。這個(gè)方法用于原始圖像的縮放、轉(zhuǎn)換、旋轉(zhuǎn)和裁剪。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

print(im.size)

imtra = im.transform((200, 200), Image.AFFINE, (1,2,3,2,1,4))

print(imtra.size)

imtra.show()im.transform(size,QUAD, data) ? image

im.transform(size, QUAD, data, filter) ? image

輸入圖像的一個(gè)四邊形(通過(guò)四個(gè)角定義的區(qū)域)映射到給定尺寸的長(zhǎng)方形。變量data是一個(gè)8元組(x0,y0,x1,y1,x2,y2,x3,y3),它包括源四邊形的左上,左下,右下和右上四個(gè)角。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

print(im.size)

imtra = im.transform((200, 200), Image.QUAD, (0,0,0,500,600,500,600,0))

print(imtra.size)

imtra.show()im.transform(size,PERSPECTIVE, data) ? image

im.transform(size, PERSPECTIVE, data, filter) ? image

對(duì)當(dāng)前圖像進(jìn)行透視變換,產(chǎn)生給定尺寸的新圖像。變量data是一個(gè)8元組(a,b,c,d,e,f,g,h),包括一個(gè)透視變換的系數(shù)。對(duì)于輸出圖像中的每個(gè)像素點(diǎn),新的值來(lái)自于輸入圖像的位置的(a x + b y + c)/(g x + h y + 1), (d x+ e y + f)/(g x + h y + 1)像素,使用最接近的像素進(jìn)行近似。這個(gè)方法用于原始圖像的2D透視。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

print(im.size)

imtra = im.transform((200, 200), Image.PERSPECTIVE, (1,2,3,2,1,6,1,2))

print(imtra.size)

imtra.show()

wocao!!!gakki不見(jiàn)了!!!

三十四、Transpose類im.transpose(method)? image

返回當(dāng)前圖像的翻轉(zhuǎn)或者旋轉(zhuǎn)的拷貝。變量method的取值為:FLIP_LEFT_RIGHT,FLIP_TOP_BOTTOM,ROTATE_90,ROTATE_180,或ROTATE_270。@zhangziju

from PIL import Image

im = Image.open("E:\mywife.jpg")

im.rotate(45) #逆時(shí)針旋轉(zhuǎn) 45 度角。

im.transpose(Image.FLIP_LEFT_RIGHT) #左右對(duì)換。

im.transpose(Image.FLIP_TOP_BOTTOM) #上下對(duì)換。

im.transpose(Image.ROTATE_90) #旋轉(zhuǎn) 90 度角。

im.transpose(Image.ROTATE_180) #旋轉(zhuǎn) 180 度角。

im.transpose(Image.ROTATE_270) #旋轉(zhuǎn) 270 度角。

二、skimage庫(kù)

基于python腳本語(yǔ)言開(kāi)發(fā)的數(shù)字圖片處理包,比如PIL,Pillow, opencv, scikit-image等。PIL和Pillow只提供最基礎(chǔ)的數(shù)字圖像處理,功能有限;opencv實(shí)際上是一個(gè)c++庫(kù),只是提供了python接口,更新速度非常慢。scikit-image是基于scipy的一款圖像處理包,它將圖片作為numpy數(shù)組進(jìn)行處理,正好與matlab一樣,因此,我們最終選擇scikit-image進(jìn)行數(shù)字圖像處理。

Image讀出來(lái)的是PIL的類型,而skimage.io讀出來(lái)的數(shù)據(jù)是numpy格式的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在單獨(dú)測(cè)試時(shí)要要在代碼中設(shè)置:transformer.set_transpose('data',(2,0,1)),因?yàn)閏affe可以處理的圖片的數(shù)據(jù)格式是(channel,height,width),所以要轉(zhuǎn)換數(shù)據(jù)]#讀圖片后數(shù)據(jù)的大小:

print "the picture's size: ", img_file1.size

print "the picture's shape: ", img_file2.shapethe 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讀出來(lái)的圖片獲得某點(diǎn)像素用getpixel((w,h))可以直接返回這個(gè)點(diǎn)三個(gè)通道的像素值

skimage讀出來(lái)的圖片可以直接img_file2[0][0]獲得,但是一定記住它的格式,并不是你想的(channel,height,width)

一、圖片信息

如果我們想知道一些skimage圖片信息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]) #圖片通道數(shù)

print(img.size) #顯示總像素個(gè)數(shù)

print(img.max()) #最大像素值

print(img.min()) #最小像素值

print(img.mean()) #像素平均值

print(img[0][0])#圖像的像素值

PIL image 查看圖片信息,可用如下的方法print type(img)

print img.size #圖片的尺寸

print img.mode #圖片的模式

print img.format #圖片的格式

print(img.getpixel((0,0)))#得到像素:

#img讀出來(lái)的圖片獲得某點(diǎn)像素用getpixel((w,h))可以直接返回這個(gè)點(diǎn)三個(gè)通道的像素值# 獲取圖像的灰度值范圍

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模塊,顧名思義,這個(gè)模塊是用來(lái)圖片輸入輸出操作的。為了方便練習(xí),也提供一個(gè)data模塊,里面嵌套了一些示例圖片,我們可以直接使用。

二、skimage包的子模塊

skimage包的全稱是scikit-image SciKit (toolkit for SciPy) ,它對(duì)scipy.ndimage進(jìn)行了擴(kuò)展,提供了更多的圖片處理功能。它是由python語(yǔ)言編寫(xiě)的,由scipy 社區(qū)開(kāi)發(fā)和維護(hù)。skimage包由許多的子模塊組成,各個(gè)子模塊提供不同的功能。主要子模塊列表如下:子模塊名稱  主要實(shí)現(xiàn)功能

io 讀取、保存和顯示圖片或視頻

data 提供一些測(cè)試圖片和樣本數(shù)據(jù)

color 顏色空間變換

filters 圖像增強(qiáng)、邊緣檢測(cè)、排序?yàn)V波器、自動(dòng)閾值等

draw 操作于numpy數(shù)組上的基本圖形繪制,包括線條、矩形、圓和文本等

transform 幾何變換或其它變換,如旋轉(zhuǎn)、拉伸和拉東變換等

morphology 形態(tài)學(xué)操作,如開(kāi)閉運(yùn)算、骨架提取等

exposure 圖片強(qiáng)度調(diào)整,如亮度調(diào)整、直方圖均衡等

feature 特征檢測(cè)與提取等

measure 圖像屬性的測(cè)量,如相似性或等高線等

segmentation 圖像分割

restoration 圖像恢復(fù)

util 通用函數(shù)

從外部讀取圖片并顯示

讀取單張彩色rgb圖片,使用skimage.io.imread(fname)函數(shù),帶一個(gè)參數(shù),表示需要讀取的文件路徑。顯示圖片使用skimage.io.imshow(arr)函數(shù),帶一個(gè)參數(shù),表示需要顯示的arr數(shù)組(讀取的圖片以numpy數(shù)組形式計(jì)算)。from skimage import io

img=io.imread('d:/dog.jpg')

io.imshow(img)

讀取單張灰度圖片,使用skimage.io.imread(fname,as_grey=True)函數(shù),第一個(gè)參數(shù)為圖片路徑,第二個(gè)參數(shù)為as_grey, bool型值,默認(rèn)為Falsefrom skimage import io

img=io.imread('d:/dog.jpg',as_grey=True)

io.imshow(img)

skimage程序自帶了一些示例圖片,如果我們不想從外部讀取圖片,就可以直接使用這些示例圖片:astronaut 航員圖片 coffee 一杯咖啡圖片

lena lena美女圖片 camera 拿相機(jī)的人圖片

coins 硬幣圖片 moon 月亮圖片

checkerboard 棋盤(pán)圖片 horse 馬圖片

page 書(shū)頁(yè)圖片 chelsea 小貓圖片

hubble_deep_field 星空?qǐng)D片 text 文字圖片

clock 時(shí)鐘圖片 immunohistochemistry 結(jié)腸圖片

顯示這些圖片可用如下代碼,不帶任何參數(shù)from skimage import io, data

img=data.lena()

io.imshow(img)

圖片名對(duì)應(yīng)的就是函數(shù)名,如camera圖片對(duì)應(yīng)的函數(shù)名為camera(). 這些示例圖片存放在skimage的安裝目錄下面,路徑名稱為data_dir,我們可以將這個(gè)路徑打印出來(lái)看看from skimage import data_dir

print(data_dir)

保存圖片

使用io模塊的imsave(fname,arr)函數(shù)來(lái)實(shí)現(xiàn)。第一個(gè)參數(shù)表示保存的路徑和名稱,第二個(gè)參數(shù)表示需要保存的數(shù)組變量。from skimage import io,data

img=data.chelsea()

io.imshow(img)

io.imsave('d:/cat.jpg',img)

保存圖片的同時(shí)也起到了轉(zhuǎn)換格式的作用。如果讀取時(shí)圖片格式為jpg圖片,保存為png格式,則將圖片從jpg圖片轉(zhuǎn)換為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]) #圖片通道數(shù)

print(img.size) #顯示總像素個(gè)數(shù)

print(img.max()) #最大像素值

print(img.min()) #最小像素值

print(img.mean()) #像素平均值

print(img[0][0])#圖像的像素值

三、圖像像素的訪問(wèn)與裁剪

圖片讀入程序中后,是以numpy數(shù)組存在的。因此對(duì)numpy數(shù)組的一切功能,對(duì)圖片也適用。對(duì)數(shù)組元素的訪問(wèn),實(shí)際上就是對(duì)圖片像素點(diǎn)的訪問(wèn)。

彩色圖片訪問(wèn)方式為:img[i,j,c]

i表示圖片的行數(shù),j表示圖片的列數(shù),c表示圖片的通道數(shù)(RGB三通道分別對(duì)應(yīng)0,1,2)。坐標(biāo)是從左上角開(kāi)始。

灰度圖片訪問(wèn)方式為: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)

除了對(duì)像素進(jìn)行讀取,也可以修改像素值。

例3:對(duì)小貓圖片隨機(jī)添加椒鹽噪聲from skimage import io,data

import numpy as np

img=data.chelsea()

#隨機(jī)生成5000個(gè)椒鹽

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來(lái)生成隨機(jī)數(shù),randint(0,cols)表示隨機(jī)生成一個(gè)整數(shù),范圍在0到cols之間。用img[x,y,:]=255這句來(lái)對(duì)像素值進(jìn)行修改,將原來(lái)的三通道像素值,變?yōu)?55。通過(guò)對(duì)數(shù)組的裁剪,就可以實(shí)現(xiàn)對(duì)圖片的裁剪。

例4:對(duì)小貓圖片進(jìn)行裁剪from skimage import io,data

img=data.chelsea()

roi=img[80:180,100:200,:]

io.imshow(roi)

對(duì)多個(gè)像素點(diǎn)進(jìn)行操作,使用數(shù)組切片方式訪問(wèn)。切片方式返回的是以指定間隔下標(biāo)訪問(wèn) 該數(shù)組的像素值。下面是有關(guān)灰度圖像的一些例子:img[i,:] = im[j,:] # 將第 j 行的數(shù)值賦值給第 i 行

img[:,i] = 100 # 將第 i 列的所有數(shù)值設(shè)為 100

img[:100,:50].sum() # 計(jì)算前 100 行、前 50 列所有數(shù)值的和

img[50:100,50:100] # 50~100 行,50~100 列(不包括第 100 行和第 100 列)

img[i].mean() # 第 i 行所有數(shù)值的平均值

img[:,-1] # 最后一列

img[-2,:] (or im[-2]) # 倒數(shù)第二行

最后我們?cè)倏磧蓚€(gè)對(duì)像素值進(jìn)行訪問(wèn)和改變的例子:

例5:將lena圖片進(jìn)行二值化,像素值大于128的變?yōu)?,否則變?yōu)?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)

使用了color模塊的rgb2gray()函數(shù),將彩色三通道圖片轉(zhuǎn)換成灰度圖。轉(zhuǎn)換結(jié)果為float64類型的數(shù)組,范圍為[0,1]之間。將彩色三通道圖片轉(zhuǎn)換成灰度圖,最后變成unit8, float轉(zhuǎn)換為unit8是有信息損失的。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())

結(jié)果(, 'RGB', , (420, 512, 3), dtype('uint8'), 255, 0, 130.9983863467262)

(, (420, 512), dtype('float64'), 1.0, 0.0, 0.5137191621440242)

(, (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)

這個(gè)例子先對(duì)R通道的所有像素值進(jìn)行判斷,如果大于170,則將這個(gè)地方的像素值變?yōu)閇0,255,0], 即G通道值為255,R和B通道值為0。

四、圖像數(shù)據(jù)類型及顏色空間轉(zhuǎn)換

在skimage中,一張圖片就是一個(gè)簡(jiǎn)單的numpy數(shù)組,數(shù)組的數(shù)據(jù)類型有很多種,相互之間也可以轉(zhuǎn)換。這些數(shù)據(jù)類型及取值范圍如下表所示: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], 因此默認(rèn)類型是unit8, 可用如下代碼查看數(shù)據(jù)類型from skimage import io,data

img=data.chelsea()

print(img.dtype.name)

在上面的表中,特別注意的是float類型,它的范圍是[-1,1]或[0,1]之間。一張彩色圖片轉(zhuǎn)換為灰度圖后,它的類型就由unit8變成了float

1、unit8轉(zhuǎn)floatfrom skimage import data,img_as_float

img=data.chelsea()

print(img.dtype.name)

dst=img_as_float(img)

print(dst.dtype.name)

2、float轉(zhuǎn)uint8from 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)

float轉(zhuǎn)為unit8,有可能會(huì)造成數(shù)據(jù)的損失,因此會(huì)有警告提醒。除了這兩種最常用的轉(zhuǎn)換以外,其實(shí)有一些其它的類型轉(zhuǎn)換,如下表: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.

如前所述,除了直接轉(zhuǎn)換可以改變數(shù)據(jù)類型外,還可以通過(guò)圖像的顏色空間轉(zhuǎn)換來(lái)改變數(shù)據(jù)類型。常用的顏色空間有灰度空間、rgb空間、hsv空間和cmyk空間。顏色空間轉(zhuǎn)換以后,圖片類型都變成了float型。所有的顏色空間轉(zhuǎn)換函數(shù),都放在skimage的color模塊內(nèi)。

例:rgb轉(zhuǎn)灰度圖from skimage import io,data,color

img=data.lena()

gray=color.rgb2gray(img)

io.imshow(gray)

其它的轉(zhuǎn)換,用法都是一樣的,列舉常用的如下:skimage.color.rgb2grey(rgb)

skimage.color.rgb2hsv(rgb)

skimage.color.rgb2lab(rgb)

skimage.color.gray2rgb(image)

skimage.color.hsv2rgb(hsv)

skimage.color.lab2rgb(lab)

實(shí)際上,上面的所有轉(zhuǎn)換函數(shù),都可以用一個(gè)函數(shù)來(lái)代替skimage.color.convert_colorspace(arr, fromspace, tospace)

表示將arr從fromspace顏色空間轉(zhuǎn)換到tospace顏色空間。

例:rgb轉(zhuǎn)hsvfrom skimage import io,data,color

img=data.lena()

hsv=color.convert_colorspace(img,'RGB','HSV')

io.imshow(hsv)

在color模塊的顏色空間轉(zhuǎn)換函數(shù)中,還有一個(gè)比較有用的函數(shù)是

skimage.color.label2rgb(arr), 可以根據(jù)標(biāo)簽值對(duì)圖片進(jìn)行著色。以后的圖片分類后著色就可以用這個(gè)函數(shù)。

例:將lena圖片分成三類,然后用默認(rèn)顏色對(duì)三類進(jìn)行著色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)

五、圖像的繪制

實(shí)際上前面我們就已經(jīng)用到了圖像的繪制,如:io.imshow(img)

這一行代碼的實(shí)質(zhì)是利用matplotlib包對(duì)圖片進(jìn)行繪制,繪制成功后,返回一個(gè)matplotlib類型的數(shù)據(jù)。因此,我們也可以這樣寫(xiě):import matplotlib.pyplot as plt

plt.imshow(img)

imshow()函數(shù)格式為:matplotlib.pyplot.imshow(X, cmap=None)

X: 要繪制的圖像或數(shù)組。cmap: 顏色圖譜(colormap), 默認(rèn)繪制為RGB(A)顏色空間。其它可選的顏色圖譜如下列表:顏色圖譜 描述

autumn 紅-橙-黃

bone 黑-白,x線

cool 青-洋紅

copper 黑-銅

flag 紅-白-藍(lán)-黑

gray 黑-白

hot 黑-紅-黃-白

hsv hsv顏色空間, 紅-黃-綠-青-藍(lán)-洋紅-紅

inferno 黑-紅-黃

jet 藍(lán)-青-黃-紅

magma 黑-紅-白

pink 黑-粉-白

plasma 綠-紅-黃

prism 紅-黃-綠-藍(lán)-紫-...-綠模式

spring 洋紅-黃

summer 綠-黃

viridis 藍(lán)-綠-黃

winter 藍(lán)-綠

用的比較多的有g(shù)ray,jet等,如:plt.imshow(image,plt.cm.gray)

plt.imshow(img,cmap=plt.cm.jet)

在窗口上繪制完圖片后,返回一個(gè)AxesImage對(duì)象。要在窗口上顯示這個(gè)對(duì)象,我們可以調(diào)用show()函數(shù)來(lái)進(jìn)行顯示,但進(jìn)行練習(xí)的時(shí)候(ipython環(huán)境中),一般我們可以省略show()函數(shù),也能自動(dòng)顯示出來(lái)。from skimage import io,data

img=data.astronaut()

dst=io.imshow(img)

print(type(dst))

io.show()

可以看到,類型是'matplotlib.image.AxesImage'。顯示一張圖片,我們通常更愿意這樣寫(xiě):import matplotlib.pyplot as plt

from skimage import io,data

img=data.astronaut()

plt.imshow(img)

plt.show()

matplotlib是一個(gè)專業(yè)繪圖的庫(kù),相當(dāng)于matlab中的plot,可以設(shè)置多個(gè)figure窗口,設(shè)置figure的標(biāo)題,隱藏坐標(biāo)尺,甚至可以使用subplot在一個(gè)figure中顯示多張圖片。一般我們可以這樣導(dǎo)入matplotlib庫(kù):import matplotlib.pyplot as plt

也就是說(shuō),我們繪圖實(shí)際上用的是matplotlib包的pyplot模塊。用figure函數(shù)和subplot函數(shù)分別創(chuàng)建主窗口與子圖。分開(kāi)并同時(shí)顯示宇航員圖片的三個(gè)通道from skimage import data

import matplotlib.pyplot as plt

img=data.astronaut()

plt.figure(num='astronaut',figsize=(8,8)) #創(chuàng)建一個(gè)名為astronaut的窗口,并設(shè)置大小

plt.subplot(2,2,1) #將窗口分為兩行兩列四個(gè)子圖,則可顯示四幅圖片

plt.title('origin image') #第一幅圖片標(biāo)題

plt.imshow(img) #繪制第一幅圖片

plt.subplot(2,2,2) #第二個(gè)子圖

plt.title('R channel') #第二幅圖片標(biāo)題

plt.imshow(img[:,:,0],plt.cm.gray) #繪制第二幅圖片,且為灰度圖

plt.axis('off') #不顯示坐標(biāo)尺寸

plt.subplot(2,2,3) #第三個(gè)子圖

plt.title('G channel') #第三幅圖片標(biāo)題

plt.imshow(img[:,:,1],plt.cm.gray) #繪制第三幅圖片,且為灰度圖

plt.axis('off') #不顯示坐標(biāo)尺寸

plt.subplot(2,2,4) #第四個(gè)子圖

plt.title('B channel') #第四幅圖片標(biāo)題

plt.imshow(img[:,:,2],plt.cm.gray) #繪制第四幅圖片,且為灰度圖

plt.axis('off') #不顯示坐標(biāo)尺寸

plt.show() #顯示窗口

在圖片繪制過(guò)程中,我們用matplotlib.pyplot模塊下的figure()函數(shù)來(lái)創(chuàng)建顯示窗口,該函數(shù)的格式為:matplotlib.pyplot.figure(num=None, figsize=None, dpi=None, facecolor=None, edgecolor=None)

所有參數(shù)都是可選的,都有默認(rèn)值,因此調(diào)用該函數(shù)時(shí)可以不帶任何參數(shù),其中:num: 整型或字符型都可以。如果設(shè)置為整型,則該整型數(shù)字表示窗口的序號(hào)。如果設(shè)置為字符型,則該字符串表示窗口的名稱。用該參數(shù)來(lái)命名窗口,如果兩個(gè)窗口序號(hào)或名相同,則后一個(gè)窗口會(huì)覆蓋前一個(gè)窗口。

figsize: 設(shè)置窗口大小。是一個(gè)tuple型的整數(shù),如figsize=(8,8)

dpi: 整形數(shù)字,表示窗口的分辨率。

facecolor: 窗口的背景顏色。

edgecolor: 窗口的邊框顏色。

用figure()函數(shù)創(chuàng)建的窗口,只能顯示一幅圖片,如果想要顯示多幅圖片,則需要將這個(gè)窗口再劃分為幾個(gè)子圖,在每個(gè)子圖中顯示不同的圖片。我們可以使用subplot()函數(shù)來(lái)劃分子圖,函數(shù)格式為:matplotlib.pyplot.subplot(nrows, ncols, plot_number)nrows: 子圖的行數(shù)。

ncols: 子圖的列數(shù)。

plot_number: 當(dāng)前子圖的編號(hào)。

如:plt.subplot(2,2,1)

則表示將figure窗口劃分成了2行2列共4個(gè)子圖,當(dāng)前為第1個(gè)子圖。我們有時(shí)也可以用這種寫(xiě)法:plt.subplot(221)

兩種寫(xiě)法效果是一樣的。每個(gè)子圖的標(biāo)題可用title()函數(shù)來(lái)設(shè)置,是否使用坐標(biāo)尺可用axis()函數(shù)來(lái)設(shè)置,如:plt.subplot(221)

plt.title("first subwindow")

plt.axis('off')

用subplots來(lái)創(chuàng)建顯示窗口與劃分子圖

除了上面那種方法創(chuàng)建顯示窗口和劃分子圖,還有另外一種編寫(xiě)方法也可以,如下例: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() #自動(dòng)調(diào)整subplot間的參數(shù)

直接用subplots()函數(shù)來(lái)創(chuàng)建并劃分窗口。注意,比前面的subplot()函數(shù)多了一個(gè)s,該函數(shù)格式為:matplotlib.pyplot.subplots(nrows=1, ncols=1)。

nrows: 所有子圖行數(shù),默認(rèn)為1。

ncols: 所有子圖列數(shù),默認(rèn)為1。

返回一個(gè)窗口figure, 和一個(gè)tuple型的ax對(duì)象,該對(duì)象包含所有的子圖,可結(jié)合ravel()函數(shù)列出所有子圖,如:fig, axes = plt.subplots(2, 2, figsize=(7, 6))

ax0, ax1, ax2, ax3 = axes.ravel()

創(chuàng)建了2行2列4個(gè)子圖,分別取名為ax0,ax1,ax2和ax3, 每個(gè)子圖的標(biāo)題用set_title()函數(shù)來(lái)設(shè)置,如:ax0.imshow(img)

ax0.set_title("Original image")

如果有多個(gè)子圖,我們還可以使用tight_layout()函數(shù)來(lái)調(diào)整顯示的布局,該函數(shù)格式為:matplotlib.pyplot.tight_layout(pad=1.08, h_pad=None, w_pad=None, rect=None)

所有的參數(shù)都是可選的,調(diào)用該函數(shù)時(shí)可省略所有的參數(shù)。pad: 主窗口邊緣和子圖邊緣間的間距,默認(rèn)為1.08

h_pad, w_pad: 子圖邊緣之間的間距,默認(rèn)為 pad_inches

rect: 一個(gè)矩形區(qū)域,如果設(shè)置這個(gè)值,則將所有的子圖調(diào)整到這個(gè)矩形區(qū)域內(nèi)。

一般調(diào)用為:plt.tight_layout() #自動(dòng)調(diào)整subplot間的參數(shù)

其它方法繪圖并顯示

除了使用matplotlib庫(kù)來(lái)繪制圖片,skimage還有另一個(gè)子模塊viewer,也提供一個(gè)函數(shù)來(lái)顯示圖片。不同的是,它利用Qt工具來(lái)創(chuàng)建一塊畫(huà)布,從而在畫(huà)布上繪制圖像。

例:from skimage import data

from skimage.viewer import ImageViewer

img = data.coins()

viewer = ImageViewer(img)

viewer.show()

最后總結(jié)一下,繪制和顯示圖片常用到的函數(shù)有:函數(shù)名 功能 調(diào)用格式

figure 創(chuàng)建一個(gè)顯示窗口 plt.figure(num=1,figsize=(8,8)

imshow 繪制圖片 plt.imshow(image)

show 顯示窗口 plt.show()

subplot 劃分子圖 plt.subplot(2,2,1)

title 設(shè)置子圖標(biāo)題(與subplot結(jié)合使用) plt.title('origin image')

axis 是否顯示坐標(biāo)尺 plt.axis('off')

subplots 創(chuàng)建帶有多個(gè)子圖的窗口 fig,axes=plt.subplots(2,2,figsize=(8,8))

ravel 為每個(gè)子圖設(shè)置變量 ax0,ax1,ax2,ax3=axes.ravel()

set_title 設(shè)置子圖標(biāo)題(與axes結(jié)合使用) ax0.set_title('first window')

tight_layout 自動(dòng)調(diào)整子圖顯示布局 plt.tight_layout()

六、圖像的批量處理

有些時(shí)候,我們不僅要對(duì)一張圖片進(jìn)行處理,可能還會(huì)對(duì)一批圖片處理。這時(shí)候,我們可以通過(guò)循環(huán)來(lái)執(zhí)行處理,也可以調(diào)用程序自帶的圖片集合來(lái)處理。圖片集合函數(shù)為:skimage.io.ImageCollection(load_pattern,load_func=None)

這個(gè)函數(shù)是放在io模塊內(nèi)的,帶兩個(gè)參數(shù),第一個(gè)參數(shù)load_pattern, 表示圖片組的路徑,可以是一個(gè)str字符串。第二個(gè)參數(shù)load_func是一個(gè)回調(diào)函數(shù),我們對(duì)圖片進(jìn)行批量處理就可以通過(guò)這個(gè)回調(diào)函數(shù)實(shí)現(xiàn)?;卣{(diào)函數(shù)默認(rèn)為imread(),即默認(rèn)這個(gè)函數(shù)是批量讀取圖片。先看一個(gè)例子:import skimage.io as io

from skimage import data_dir

str=data_dir + '/*.png'

coll = io.ImageCollection(str)

print(len(coll))

顯示結(jié)果為25, 說(shuō)明系統(tǒng)自帶了25張png的示例圖片,這些圖片都讀取了出來(lái),放在圖片集合coll里。如果我們想顯示其中一張圖片,則可以在后加上一行代碼:io.imshow(coll[10])

如果一個(gè)文件夾里,我們既存放了一些jpg格式的圖片,又存放了一些png格式的圖片,現(xiàn)在想把它們?nèi)孔x取出來(lái),該怎么做呢?import skimage.io as io

from skimage import data_dir

str='d:/pic/*.jpg:d:/pic/*.png'

coll = io.ImageCollection(str)

print(len(coll))

注意這個(gè)地方'd:/pic/.jpg:d:/pic/.png' ,是兩個(gè)字符串合在一起的,第一個(gè)是'd:/pic/.jpg', 第二個(gè)是'd:/pic/.png' ,合在一起后,中間用冒號(hào)來(lái)隔開(kāi),這樣就可以把d:/pic/文件夾下的jpg和png格式的圖片都讀取出來(lái)。如果還想讀取存放在其它地方的圖片,也可以一并加進(jìn)去,只是中間同樣用冒號(hào)來(lái)隔開(kāi)。io.ImageCollection()這個(gè)函數(shù)省略第二個(gè)參數(shù),就是批量讀取。如果我們不是想批量讀取,而是其它批量操作,如批量轉(zhuǎn)換為灰度圖,那又該怎么做呢?那就需要先定義一個(gè)函數(shù),然后將這個(gè)函數(shù)作為第二個(gè)參數(shù),如: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])

這種批量操作對(duì)視頻處理是極其有用的,因?yàn)橐曨l就是一系列的圖片組合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這個(gè)視頻中每隔10幀的圖片讀取出來(lái),放在圖片集合中。

得到圖片集合以后,我們還可以將這些圖片連接起來(lái),構(gòu)成一個(gè)維度更高的數(shù)組,連接圖片的函數(shù)為:skimage.io.concatenate_images(ic)

帶一個(gè)參數(shù),就是以上的圖片集合,如:from skimage import data_dir,io,color

coll = io.ImageCollection('d:/pic/*.jpg')

mat=io.concatenate_images(coll)

使用concatenate_images(ic)函數(shù)的前提是讀取的這些圖片尺寸必須一致,否則會(huì)出錯(cuò)。我們看看圖片連接前后的維度變化:from skimage import data_dir,io,color

coll = io.ImageCollection('d:/pic/*.jpg')

print(len(coll)) #連接的圖片數(shù)量

print(coll[0].shape) #連接前的圖片尺寸,所有的都一樣

mat=io.concatenate_images(coll)

print(mat.shape) #連接后的數(shù)組尺寸

顯示結(jié)果:2

(870, 580, 3)

(2, 870, 580, 3)

可以看到,將2個(gè)3維數(shù)組,連接成了一個(gè)4維數(shù)組

如果我們對(duì)圖片進(jìn)行批量操作后,想把操作后的結(jié)果保存起來(lái),也是可以辦到的。

例:把系統(tǒng)自帶的所有png示例圖片,全部轉(zhuǎn)換成256256的jpg格式灰度圖,保存在d:/data/文件夾下*

改變圖片的大小,我們可以使用tranform模塊的resize()函數(shù),后續(xù)會(huì)講到這個(gè)模塊。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圖片轉(zhuǎn)換成灰度圖

dst=transform.resize(gray,(256,256)) #將灰度圖片大小轉(zhuǎn)換為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]) #循環(huán)保存圖片

七、圖像的形變與縮放

圖像的形變與縮放,使用的是skimage的transform模塊,函數(shù)比較多,功能齊全。

1、改變圖片尺寸resize

函數(shù)格式為: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圖片由原來(lái)的512x512大小,變成了80x60大小。從下圖中的坐標(biāo)尺,我們能夠看出來(lái):

2、按比例縮放rescale

函數(shù)格式為:skimage.transform.rescale(image, scale[, ...])

scale參數(shù)可以是單個(gè)float數(shù),表示縮放的倍數(shù),也可以是一個(gè)float型的tuple,如[0.2,0.5],表示將行列數(shù)分開(kāi)進(jìn)行縮放from skimage import transform,data

img = data.camera()

print(img.shape) #圖片原始大小

print(transform.rescale(img, 0.1).shape) #縮小為原來(lái)圖片大小的0.1

print(transform.rescale(img, [0.5,0.25]).shape) #縮小為原來(lái)圖片行數(shù)一半,列數(shù)四分之一

print(transform.rescale(img, 2).shape) #放大為原來(lái)圖片大小的2倍

結(jié)果為:(512, 512)

(51, 51)

(256, 128)

(1024, 1024)

3、旋轉(zhuǎn)rotateskimage.transform.rotate(image, angle[, ...],resize=False)

angle參數(shù)是個(gè)float類型數(shù),表示旋轉(zhuǎn)的度數(shù)

resize用于控制在旋轉(zhuǎn)時(shí),是否改變大小 ,默認(rèn)為Falsefrom skimage import transform,data

import matplotlib.pyplot as plt

img = data.camera()

print(img.shape) #圖片原始大小

img1=transform.rotate(img, 60) #旋轉(zhuǎn)90度,不改變大小

print(img1.shape)

img2=transform.rotate(img, 30,resize=True) #旋轉(zhuǎn)30度,同時(shí)改變大小

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()

4、圖像金字塔

以多分辨率來(lái)解釋圖像的一種有效但概念簡(jiǎn)單的結(jié)構(gòu)就是圖像金字塔。圖像金字塔最初用于機(jī)器視覺(jué)和圖像壓縮,一幅圖像的金字塔是一系列以金字塔形狀排列的分辨率逐步降低的圖像集合。金字塔的底部是待處理圖像的高分辨率表示,而頂部是低分辨率的近似。當(dāng)向金字塔的上層移動(dòng)時(shí),尺寸和分辨率就降低。在此,我們舉一個(gè)高斯金字塔的應(yīng)用實(shí)例,函數(shù)原型為: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 #獲取圖片的行數(shù),列數(shù)和通道數(shù)

pyramid = tuple(transform.pyramid_gaussian(image, downscale=2)) #產(chǎn)生高斯金字塔圖像#共生成了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 #循環(huán)融合9幅金字塔圖像

i_row += n_rows

plt.imshow(composite_image)

plt.show()

上右圖,就是10張金字塔圖像,下標(biāo)為0的表示原始圖像,后面每層的圖像行和列變?yōu)樯弦粚拥囊话?#xff0c;直至變?yōu)?

除了高斯金字塔外,還有其它的金字塔,如:skimage.transform.pyramid_laplacian(image, downscale=2)

八、對(duì)比度與亮度調(diào)整

圖像亮度與對(duì)比度的調(diào)整,是放在skimage包的exposure模塊里面

1、gamma調(diào)整

原理:I=Ig

對(duì)原圖像的像素,進(jìn)行冪運(yùn)算,得到新的像素值。公式中的g就是gamma值。

如果gamma>1, 新圖像比原圖像暗

如果gamma<1,新圖像比原圖像亮

函數(shù)格式為:skimage.exposure.adjust_gamma(image, gamma=1)

gamma參數(shù)默認(rèn)為1,原像不發(fā)生變化 。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) #調(diào)暗

gam2= exposure.adjust_gamma(image, 0.5) #調(diào)亮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()

2、log對(duì)數(shù)調(diào)整

這個(gè)剛好和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) #對(duì)數(shù)調(diào)整

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()

3、判斷圖像對(duì)比度是否偏低

函數(shù):is_low_contrast(img)

返回一個(gè)bool型值from skimage import data, exposure

image =data.moon()

result=exposure.is_low_contrast(image)

print(result)

輸出為False

4、調(diào)整強(qiáng)度

函數(shù):skimage.exposure.rescale_intensity(image, in_range='image', out_range='dtype')

in_range 表示輸入圖片的強(qiáng)度范圍,默認(rèn)為'image', 表示用圖像的最大/最小像素值作為范圍

out_range 表示輸出圖片的強(qiáng)度范圍,默認(rèn)為'dype', 表示用圖像的類型的最大/最小值作為范圍

默認(rèn)情況下,輸入圖片的[min,max]范圍被拉伸到[dtype.min, dtype.max],如果dtype=uint8, 那么dtype.min=0, dtype.max=255import 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變?yōu)?,最大值由153變?yōu)?55,整體進(jìn)行了拉伸,但是數(shù)據(jù)類型沒(méi)有變,還是uint8

前面我們講過(guò),可以通過(guò)img_as_float()函數(shù)將unit8類型轉(zhuǎn)換為float型,實(shí)際上還有更簡(jiǎn)單的方法,就是乘以1.0import 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],因此對(duì)float進(jìn)行rescale_intensity 調(diào)整后,范圍變?yōu)閇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)

結(jié)果為[ 0. 0.5 1. ]

如果原始像素值不想被拉伸,只是等比例縮小,就使用in_range參數(shù),如: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

如果參數(shù)in_range的[main,max]范圍要比原始像素值的范圍[min,max] 大或者小,那就進(jìn)行裁剪,如:mat=exposure.rescale_intensity(tmp,in_range=(0,102))

print(mat)

輸出[ 0.5 1. 1. ],即原像素值除以102,超出1的變?yōu)?

如果一個(gè)數(shù)組里面有負(fù)數(shù),現(xiàn)在想調(diào)整到正數(shù),就使用out_range參數(shù)。如: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]

九、直方圖與均衡化

在圖像處理中,直方圖是非常重要,也是非常有用的一個(gè)處理要素。在skimage庫(kù)中對(duì)直方圖的處理,是放在exposure這個(gè)模塊中。

1、計(jì)算直方圖

函數(shù):skimage.exposure.histogram(image, nbins=256)

在numpy包中,也提供了一個(gè)計(jì)算直方圖的函數(shù)histogram(),兩者大同小義。返回一個(gè)tuple(hist, bins_center), 前一個(gè)數(shù)組是直方圖的統(tǒng)計(jì)量,后一個(gè)數(shù)組是每個(gè)bin的中間值import numpy as np

from skimage import exposure,data

image =data.camera()*1.0

hist1=np.histogram(image, bins=2) #用numpy包計(jì)算直方圖hist2=exposure.histogram(image, nbins=2) #用skimage計(jì)算直方圖

print(hist1)

print(hist2)

輸出:(array([107432, 154712], dtype=int64), array([ 0. , 127.5, 255. ]))

(array([107432, 154712], dtype=int64), array([ 63.75, 191.25]))

分成兩個(gè)bin,每個(gè)bin的統(tǒng)計(jì)量是一樣的,但numpy返回的是每個(gè)bin的兩端的范圍值,而skimage返回的是每個(gè)bin的中間值

2、繪制直方圖

繪圖都可以調(diào)用matplotlib.pyplot庫(kù)來(lái)進(jìn)行,其中的hist函數(shù)可以直接繪制直方圖。調(diào)用方式:n, bins, patches = plt.hist(arr, bins=10, normed=0, facecolor='black', edgecolor='black',alpha=1,histtype='bar')

hist的參數(shù)非常多,但常用的就這六個(gè),只有第一個(gè)是必須的,后面四個(gè)可選arr: 需要計(jì)算直方圖的一維數(shù)組

bins: 直方圖的柱數(shù),可選項(xiàng),默認(rèn)為10

normed: 是否將得到的直方圖向量歸一化。默認(rèn)為0

facecolor: 直方圖顏色

edgecolor: 直方圖邊框顏色

alpha: 透明度

histtype: 直方圖類型,‘bar’, ‘barstacked’, ‘step’, ‘stepfilled’

返回值 :n: 直方圖向量,是否歸一化由參數(shù)normed設(shè)定

bins: 返回各個(gè)bin的區(qū)間范圍

patches: 返回每個(gè)bin里面包含的數(shù)據(jù),是一個(gè)listfrom 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()函數(shù)是numpy包里面的,用于將二維數(shù)組序列化成一維數(shù)組。

是按行序列,如mat=[[1 2 3

4 5 6]]

經(jīng)過(guò) mat.flatten()后,就變成了mat=[1 2 3 4 5 6]

3、彩色圖片三通道直方圖

一般來(lái)說(shuō)直方圖都是征對(duì)灰度圖的,如果要畫(huà)rgb圖像的三通道直方圖,實(shí)際上就是三個(gè)直方圖的疊加。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()

其中,加一個(gè)參數(shù)hold=1,表示可以疊加

4、直方圖均衡化

如果一副圖像的像素占有很多的灰度級(jí)而且分布均勻,那么這樣的圖像往往有高對(duì)比度和多變的灰度色調(diào)。直方圖均衡化就是一種能僅靠輸入圖像直方圖信息自動(dòng)達(dá)到這種效果的變換函數(shù)。它的基本思想是對(duì)圖像中像素個(gè)數(shù)多的灰度級(jí)進(jìn)行展寬,而對(duì)圖像中像素個(gè)數(shù)少的灰度進(jìn)行壓縮,從而擴(kuò)展取值的動(dòng)態(tài)范圍,提高了對(duì)比度和灰度色調(diào)的變化,使圖像更加清晰。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()

十、CLAHE

skimage.exposure.``equalize_adapthist(image, kernel_size=None, clip_limit=0.01, nbins=256)

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]) ndarrayInput 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 as image.ndim (without color channel). If integer, it is broadcasted to each image dimension. By default, kernel_size is 1/8 of image height by 1/8 of its width.

clip_limit : float, optionalClipping 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]) ndarrayEqualized image.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(img4,plt.cm.gray) #均衡化圖像

plt.subplot(5,2,8)

plt.hist(arr4, bins=256, normed=1,edgecolor='None',facecolor='red') #均衡化直方圖

plt.show()

img5=exposure.equalize_adapthist(img, kernel_size=32, clip_limit=clip_limitnumber, nbins=256)

arr5=img5.flatten()

plt.subplot(5,2,9)

plt.title('equalize_adapthist-32-'+ str(clip_limitnumber))

plt.imshow(img5,plt.cm.gray) #均衡化圖像

plt.subplot(5,2,10)

plt.hist(arr5, bins=256, normed=1,edgecolor='None',facecolor='red') #均衡化直方圖

plt.show()from skimage import data,exposure

import matplotlib.pyplot as plt

#%matplotlib notebook

kernel_sizenuber=64

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=kernel_sizenuber, clip_limit=0.001, nbins=256)

arr2=img2.flatten()

plt.subplot(5,2,3)

plt.title('equalize_adapthist-'+ str(kernel_sizenuber)+'-0.001')

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=kernel_sizenuber, clip_limit=0.005, nbins=256)

arr3=img3.flatten()

plt.subplot(5,2,5)

plt.title('equalize_adapthist-'+ str(kernel_sizenuber)+'-0.005')

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=kernel_sizenuber, clip_limit=0.01, nbins=256)

arr4=img4.flatten()

plt.subplot(5,2,7)

plt.title('equalize_adapthist-'+ str(kernel_sizenuber)+'-0.01')

plt.imshow(img4,plt.cm.gray) #均衡化圖像

plt.subplot(5,2,8)

plt.hist(arr4, bins=256, normed=1,edgecolor='None',facecolor='red') #均衡化直方圖

plt.show()

img5=exposure.equalize_adapthist(img, kernel_size=kernel_sizenuber, clip_limit=0.05, nbins=256)

arr5=img5.flatten()

plt.subplot(5,2,9)

plt.title('equalize_adapthist-'+ str(kernel_sizenuber)+'-0.05')

plt.imshow(img5,plt.cm.gray) #均衡化圖像

plt.subplot(5,2,10)

plt.hist(arr5, bins=256, normed=1,edgecolor='None',facecolor='red') #均衡化直方圖

plt.show()

三、各種imread函數(shù)的區(qū)別與聯(lián)系

先來(lái)看看常用的讀取圖片的方式:PIL.Image.open

scipy.misc.imread

scipy.ndimage.imread

cv2.imread

matplotlib.image.imread

skimge

caffe.io.load_iamge

這些方法可以分為四大家族:

一、PILPIL.Image.open + numpy

scipy.misc.imread

scipy.ndimage.imread

這些方法都是通過(guò)調(diào)用PIL.Image.open 讀取圖像的信息; PIL.Image.open 不直接返回numpy對(duì)象,可以用numpy提供的函數(shù)進(jìn)行轉(zhuǎn)換,參考Image和Ndarray互相轉(zhuǎn)換; 其他模塊都直接返回numpy.ndarray對(duì)象,通道順序?yàn)镽GB,通道值得默認(rèn)范圍為0-255。

二、matplotlibmatplot.image.imread

從名字中可以看出這個(gè)模塊是具有matlab風(fēng)格的,直接返回numpy.ndarray格式通道順序是RGB,通道值默認(rèn)范圍0-255。

三、opencvcv2.imread

使用opencv讀取圖像,直接返回numpy.ndarray 對(duì)象,通道順序?yàn)锽GR ,注意是BGR,通道值默認(rèn)范圍0-255。

四、skimageskimage.io.imread: 直接返回numpy.ndarray 對(duì)象,通道順序?yàn)镽GB,通道值默認(rèn)范圍0-255。

caffe.io.load_image: 沒(méi)有調(diào)用默認(rèn)的skimage.io.imread,返回值為0-1的float型數(shù)據(jù),通道順序?yàn)镽GB

關(guān)于圖像的一些說(shuō)明:

可以使用matplotlib的pyplot模塊的show也可以使用cv2的imshow方法,對(duì)于這些方法只要你傳入的參數(shù)是numpy.ndarray(通道值范圍0-255) 就可以正常顯示,不存在區(qū)別,這也可以看出numpy在python中的重要地位;但是cv2.imshow方法由于它針對(duì)的是cv2的imread 所以它內(nèi)部會(huì)做通道順序的變化,傳入為BGR轉(zhuǎn)換為RGB,所以你如果傳入RGB顯示的就是BGR了。

以下是測(cè)試代碼

運(yùn)行環(huán)境為windows10+python3.6#encoding=utf8

from PIL import Image

import numpy as np

import cv2

import matplotlib.pyplot as plt # plt 用于顯示圖片

import matplotlib.image as mpimg # mpimg 用于讀取圖片

import skimage

import sys

from skimage import io

#PIL

#相關(guān):scipy.misc.imread, scipy.ndimage.imread

#misc.imread 提供可選參數(shù)mode,但本質(zhì)上是調(diào)用PIL,具體的模式可以去看srccode或者document

#https://github.com/scipy/scipy/blob/v0.17.1/scipy/misc/pilutil.py

imagepath='test1.jpg'

im1=Image.open(imagepath)

im1=np.array(im1)#獲得numpy對(duì)象,RGB

print(type(im1))

print(im1.shape)

#2 opencv

im2=cv2.imread(imagepath)

print(type(im2))#numpy BGR

print(im2.shape)#[width,height,3]

#3 matplotlib 類似matlab的方式

im3 = mpimg.imread(imagepath)

print(type(im3))#np.array

print(im3.shape)

#4 skimge?

#caffe.io.load_iamge()也是調(diào)用的skimage實(shí)現(xiàn)的,返回的是0-1 float型數(shù)據(jù)

im4 = io.imread(imagepath)

print(type(im4))#np.array

print(im4.shape)

#print(im4)

# cv2.imshow('test',im4)

# cv2.waitKey()

#統(tǒng)一使用plt進(jìn)行顯示,不管是plt還是cv2.imshow,在python中只認(rèn)numpy.array,但是由于cv2.imread 的圖片是BGR,cv2.imshow 時(shí)相應(yīng)的換通道顯示

plt.subplot(221)

plt.title('PIL read')

plt.imshow(im1)

plt.subplot(222)

plt.title('opencv read')

plt.imshow(im2)

plt.subplot(223)

plt.title('matplotlib read')

plt.imshow(im3)

plt.subplot(224)

plt.title('skimage read')

plt.imshow(im4)

#plt.axis('off') # 不顯示坐標(biāo)軸

plt.show()

##################################### cmd output################################

#

# (851, 1279, 3)

#

# (851, 1279, 3)

#

# (851, 1279, 3)

#

# (851, 1279, 3)

測(cè)試結(jié)果:

四、深度學(xué)習(xí)框架自帶的圖像處理函數(shù)

tensorflow提供了簡(jiǎn)單的圖像處理函數(shù),可以對(duì)圖像進(jìn)行預(yù)處理,可以盡量避免模型受到無(wú)關(guān)因素的影響。大部分圖像識(shí)別問(wèn)題中,通過(guò)圖像預(yù)處理過(guò)程可以提高模型的準(zhǔn)確率。封裝在類tf.image中。

一、API列表

函數(shù)列表為:adjust_brightness(): 調(diào)整RGB或灰度圖像的亮度。

adjust_contrast(): 調(diào)整RGB或灰度圖像的對(duì)比度。

adjust_gamma(): 對(duì)輸入圖像執(zhí)行伽瑪校正。

adjust_hue(): 調(diào)整RGB圖像的色調(diào)。

adjust_saturation(): 調(diào)整RGB圖像的飽和度。

central_crop(): 裁剪圖像的中心區(qū)域。

convert_image_dtype(): 將圖像轉(zhuǎn)換為dtype,如果需要可以縮放它的值。

crop_and_resize(): 從輸入的圖像張量中提取作物并對(duì)其進(jìn)行雙線性調(diào)整(可能)。

crop_to_bounding_box(): 將圖像裁剪到指定的邊框。

decode_and_crop_jpeg(): 將圖像裁剪到指定的邊框。

decode_bmp(): 將bmp編碼圖像的第一幀解碼為uint8張量。

decode_gif(): 將gif編碼圖像的第一幀解碼為uint8張量。

decode_image(): bmp、gif、jpeg的解碼函數(shù)

decode_jpeg(): 將jpeg編碼的圖像解碼為uint8張量。

decode_png(): 將png編碼的圖像解碼為uint8或uint16張量。

draw_bounding_boxes(): 在一批圖像上繪制邊框。

encode_jpeg(): 在一幅圖像中進(jìn)行JPEG編碼。

encode_png(): 在一幅圖像中進(jìn)行PNG編碼。

extract_glimpse(): 從一個(gè)輸入張量中提取一點(diǎn)點(diǎn)。

extract_jpeg_shape(): 提取jpeg編碼圖像的形狀信息。

flip_left_right(): 水平翻轉(zhuǎn)圖像(從左到右)。

flip_up_down(): 垂直翻轉(zhuǎn)圖片(上下顛倒)。

grayscale_to_rgb(): 將一個(gè)或多個(gè)圖像從灰度轉(zhuǎn)換為RGB。

hsv_to_rgb(): 將一個(gè)或多個(gè)圖像從HSV轉(zhuǎn)換為RGB。

image_gradients(): 返回每個(gè)顏色通道的圖像梯度(dy, dx)。

is_jpeg(): 檢查'內(nèi)容'編碼的JPEG圖像。

non_max_suppression(): 貪婪地選擇按得分降序排列的邊界框子集。

pad_to_bounding_box(): 用0填充指定高度和寬度的圖像。

per_image_standardization(): 線性尺度圖像具有零均值和單位范數(shù)。

psnr(): 返回a和b之間的峰值信噪比。

random_brightness(): 用一個(gè)隨機(jī)因素調(diào)整圖像的亮度。

random_contrast(): 用隨機(jī)因素調(diào)整圖像的對(duì)比度。

random_flip_left_right(): 隨機(jī)水平翻轉(zhuǎn)圖像(從左到右)。

random_flip_up_down(): 隨機(jī)垂直翻轉(zhuǎn)圖像(上下顛倒)。

random_hue(): 通過(guò)隨機(jī)因素調(diào)整RGB圖像的色調(diào)。

random_saturation(): 通過(guò)隨機(jī)因素調(diào)整RGB圖像的飽和度。

resize_area(): 使用面積插值調(diào)整圖像的大小。

resize_bicubic(): 使用雙三次插值調(diào)整圖像的大小。

resize_bilinear(): 使用雙線性插值調(diào)整圖像的大小。

resize_image_with_crop_or_pad(): 裁剪和/或?qū)D像填充到目標(biāo)寬度和高度。

resize_images(): 使用指定的方法調(diào)整圖像的大小。

resize_nearest_neighbor(): 使用最近鄰插值調(diào)整圖像的大小。

rgb_to_grayscale(): 將一個(gè)或多個(gè)圖像從RGB轉(zhuǎn)換為灰度。

rgb_to_hsv(): 將一個(gè)或多個(gè)圖像從RGB轉(zhuǎn)換為HSV。

rgb_to_yiq(): 將一個(gè)或多個(gè)圖像從RGB轉(zhuǎn)換為YIQ。

rgb_to_yuv(): 將一個(gè)或多個(gè)圖像從RGB轉(zhuǎn)換為YUV。

rot90(): 逆時(shí)針旋轉(zhuǎn)圖像90度。

sample_distorted_bounding_box(): 為圖像生成一個(gè)隨機(jī)扭曲的邊框。

sobel_edges(): 返回一個(gè)包含索貝爾邊映射的張量。

ssim(): 計(jì)算img1和img2之間的SSIM索引。

ssim_multiscale(): 計(jì)算img1和img2之間的MS-SSIM。

total_variation(): 計(jì)算并返回一個(gè)或多個(gè)圖像的總變化量。

transpose_image(): 通過(guò)交換高度和寬度維度來(lái)轉(zhuǎn)置圖像。

yiq_to_rgb(): 將一個(gè)或多個(gè)圖像從YIQ轉(zhuǎn)換為RGB。

yuv_to_rgb(): 將一個(gè)或多個(gè)圖像從YUV轉(zhuǎn)換為RGB。

二、tensorflow圖像處理函數(shù)例程

1、圖像編碼處理

一張RGB彩色模型的圖像可以看成一個(gè)三維矩陣,矩陣中的每一個(gè)數(shù)表示了圖像上不同的位置,不同顏色的亮度。然而圖像在存儲(chǔ)時(shí)并不是直接記錄這些矩陣中的數(shù)字,而是記錄經(jīng)過(guò)壓縮編碼之后的結(jié)果。所以要將一張圖片還原成一個(gè)三維矩陣,需要解碼過(guò)程。tensorflow提供了jpeg和png格式圖像的編碼/解碼的函數(shù)。以下代碼示范了如何使用tensorflow中對(duì)jpeg格式圖像進(jìn)行編碼/解碼。# matplotlib.pyplot是一個(gè)python的畫(huà)圖工具。下面的代碼將使用這個(gè)工具

# 來(lái)可視化經(jīng)過(guò)tensorflow處理的圖像。

import matplotlib.pyplot as plt

import tensorflow as tf

# 讀取圖像的原始數(shù)據(jù)

image_raw_data = tf.gfile.FastGFile("/path/to/picture", 'r').read()

with tf.Session() as sess:

# 對(duì)圖像進(jìn)行jpeg的格式解碼從而得到圖像對(duì)應(yīng)的三維矩陣。tensorflow還提供了

# tf.image.decode_png 函數(shù)對(duì)png格式的圖像進(jìn)行解碼。解碼之后的結(jié)果為一個(gè)

# 張量,在使用它的取值之前需要明確調(diào)用運(yùn)行的過(guò)程。

img_data = tf.image.decode_jpeg(image_raw_data)

print img_data.eval()

# 輸出解碼之后的三維矩陣,上面這一行代碼將輸出以下內(nèi)容。

'''

[[[165 160 138]

...,

[105 140 50]

[[166 161 139]

...,

[106 139 48]]

...,

[207 200 181]

...,

[106 81 50]]]

'''# 使用pyplot工具可視化得到的圖像。

plt.imshow(img_data.eval())

plt.show()

# 將表示一張圖像的三維矩陣重新按照jpeg格式編碼并存入文件中。打開(kāi)這張圖片,

# 可以得到和原始圖像一樣的圖像。

encoded_image = tf.image.encode_jpeg(img_data)

with tf.gfile.GFile("/path/to/output", "wb") as f:

f.write(encode_image.eval())

2、圖像大小調(diào)整

一般來(lái)說(shuō),網(wǎng)絡(luò)上獲取的圖像大小是不固定,但神經(jīng)網(wǎng)絡(luò)輸入節(jié)點(diǎn)的個(gè)數(shù)是固定的,所以在將圖像的像素作為輸入提供給神經(jīng)網(wǎng)路之前,需要先將圖像的大小統(tǒng)一。這就是圖像大小調(diào)整需要完成的任務(wù)。圖像大小調(diào)整有兩種方式,第一種是通過(guò)算法使得新的圖像盡量保存原始圖像上的所有信息。tensorflow提供了4種不同的方法,并且將它們封裝到了tf.image.resize_images函數(shù)。以下代碼示范了如何使用這個(gè)函數(shù)。# 加載原始圖像,定義會(huì)話等過(guò)程和圖像編碼處理中代碼一致,

# 假設(shè)img_data是已經(jīng)解碼的圖像。

# 首先將圖片數(shù)據(jù)轉(zhuǎn)化為實(shí)數(shù)類型。這一步將0-255的像素值轉(zhuǎn)化為 0.0-1.0 范圍內(nèi)的實(shí)數(shù),

# 大多數(shù)圖像處理API支持整數(shù)和實(shí)數(shù)類型的輸入,如果輸入是整數(shù)類型,這些API會(huì)

# 在內(nèi)部將輸入轉(zhuǎn)化為實(shí)數(shù)后處理,再將輸出轉(zhuǎn)化為整數(shù)。如果有多個(gè)處理步驟,在整數(shù)和

# 實(shí)數(shù)之間的反復(fù)轉(zhuǎn)化將導(dǎo)致精度損失,因此推進(jìn)在圖像處理前將其轉(zhuǎn)化為實(shí)數(shù)類型。

# 下面的樣例子將略去這一步驟,假設(shè)img_data是經(jīng)過(guò)類型轉(zhuǎn)化的圖像

img_data = tf.image.convert_image_dtype(img_data, dtype=tf.float32)

# 通過(guò)tf.image.resize_images函數(shù)調(diào)整圖像的大小。這個(gè)函數(shù)第一個(gè)參數(shù)為原始圖像,

# 第二個(gè)和第三個(gè)參數(shù)為調(diào)整后圖像的大小,method參數(shù)給出了調(diào)整圖像大小的算法。

# 注意,如果輸入數(shù)據(jù)時(shí)unit8格式,那么輸出將是0-255內(nèi)的實(shí)數(shù),不方便后續(xù)處理。

resized = tf.image.resize_images(img_data, [300, 300], method=0)

# 通過(guò)pyplot可視化過(guò)程和圖像編碼處理中給出的代碼一致

下表給出了tf.image.resize_images函數(shù)的method參數(shù)取值對(duì)應(yīng)的圖像大小調(diào)整算法。

Method取值 ?? ?圖像大小調(diào)整算法0 ?? ?雙線性插值(Bilinear interpolation)

1 ?? ?最鄰近發(fā)(Nearest nighbor interpolation)

2 ?? ?雙三次插值(Bicubic interpolation)

3 ?? ?面積插值法(Area interpolation)

不同算法調(diào)整出來(lái)的結(jié)果會(huì)有細(xì)微差別,但不會(huì)相差太遠(yuǎn)。除了將整張圖像信息完整保存,tensorflow還提供了API對(duì)圖像進(jìn)行剪裁或者填充。以下代碼展示了通過(guò)tf.image.resize_image_with_crop_or_pad函數(shù)來(lái)調(diào)整圖像大小的功能。# 通過(guò)tf.image.resize_image_with_crop_or_pad函數(shù)調(diào)整圖像的大小。這個(gè)函數(shù)的

# 第一個(gè)參數(shù)為原始圖像,后面兩個(gè)參數(shù)是調(diào)整后的目標(biāo)圖像大小。如果原始圖像的尺寸大于目標(biāo)

# 圖像,那么這個(gè)函數(shù)會(huì)自動(dòng)截取原始圖像中的部分。如果目標(biāo)圖像

# 大于原始圖像,這個(gè)函數(shù)會(huì)自動(dòng)在原始圖像的四周填充全0背景。因?yàn)樵?/p>

# 始圖像的大小為1797*2673,所以下面的第一個(gè)命令會(huì)自動(dòng)剪裁,而第二個(gè)命令會(huì)自動(dòng)填充。

croped = tf.image.resize_image_crop_or_pad(img_data, 1000, 1000)

padded = tf.image.resize_image_crop_or_pad(img_data, 3000, 3000)

tensorflow還支持通過(guò)比例調(diào)整圖像大小,以下代碼給出了一個(gè)樣例:# 通過(guò)tf.image.central_crop函數(shù)可以按比例剪裁圖像。這個(gè)函數(shù)的第一個(gè)參數(shù)為原始圖

# 像,第二個(gè)為調(diào)整比例,這個(gè)比例需要時(shí)一個(gè)(0,1]的實(shí)數(shù)。

central_cropped = tf.image.central_crop(img_data, 0.5)

上面介紹的圖像剪切函數(shù)都是截取或者填充圖像中間的部分。tensorflow也提供了tf.image.crop_to_bounding_box函數(shù)和tf.image.pad_to_bounding_box函數(shù)來(lái)剪切或者填充給定區(qū)域的圖像。這兩個(gè)函數(shù)都要求給出的尺寸滿足一定的要求,否則程序會(huì)報(bào)錯(cuò)。比如在使用tf.image.crop_to_bounding_box函數(shù)時(shí),tensorflow要求提供的圖像尺寸要大于目標(biāo)尺寸,也就是要求原始圖像能夠剪切目標(biāo)圖像的大小。

3、圖像翻轉(zhuǎn)

tensorflow提供了一些函數(shù)來(lái)支持對(duì)圖像的翻轉(zhuǎn)。以下代碼實(shí)現(xiàn)了將圖像上下翻轉(zhuǎn)、左右翻轉(zhuǎn)以及沿對(duì)角線翻轉(zhuǎn)的功能。# 將圖像上下翻轉(zhuǎn)

flipped = tf.image.flip_up_down(img_data)

# 將圖像左右翻轉(zhuǎn)

flipped = tf.image.flip_left_right(img_data)

# 將圖像沿對(duì)角線

transposed = tf.image.transpose_image(img_data)

在很多圖像識(shí)別問(wèn)題中,圖像的翻轉(zhuǎn)不應(yīng)該影響識(shí)別的結(jié)果。于是在訓(xùn)練圖像識(shí)別的神經(jīng)網(wǎng)絡(luò)模型時(shí),可以隨機(jī)地翻轉(zhuǎn)訓(xùn)練圖像,這樣訓(xùn)練得到的模型可以識(shí)別不同角度的實(shí)體。比如假設(shè)在訓(xùn)練模型中所有的貓頭都是向右的,那么訓(xùn)練出來(lái)的模型就無(wú)法很好地識(shí)別貓頭向左的貓。雖然這個(gè)問(wèn)題可以通過(guò)收集更多的訓(xùn)練數(shù)據(jù)來(lái)解決,但是通過(guò)隨機(jī)翻轉(zhuǎn)識(shí)別訓(xùn)練圖像的方式可以在零成本的情況下很大程度地緩解該問(wèn)題。所以隨機(jī)翻轉(zhuǎn)訓(xùn)練圖像時(shí)一種很常用的圖像預(yù)處理方式。tensorflow提供了方便的API完成隨機(jī)圖像翻轉(zhuǎn)的過(guò)程。

# 以50%概率上下翻轉(zhuǎn)

??? flipped = tf.image.random_flip_up_down(img_data)

# 以50%概率左右翻轉(zhuǎn)圖像

??? flipped = tf.image.random_flip_left_right(img_data)

4、圖像色彩調(diào)整

和圖像翻轉(zhuǎn)類似,調(diào)整圖像的亮度、對(duì)比度、飽和度和色相在很多圖像識(shí)別應(yīng)用中都不會(huì)影響識(shí)別的結(jié)果。所以在訓(xùn)練神經(jīng)網(wǎng)絡(luò)模型時(shí),可以隨機(jī)調(diào)整訓(xùn)練圖像的這些屬性,從而使得到的模型盡可能小地受到無(wú)關(guān)因素的影響。tensorflow提供了調(diào)整這些色彩相關(guān)屬性的API。以下代碼顯示了如何修改圖像的亮度。# 將圖像的亮度-0.5

adjusted = tf.image.adjust_brightness(img_data, -0.5)

# 色彩調(diào)整的API可能導(dǎo)致像素的實(shí)數(shù)超出0.0-1.0的范圍,因此在輸出最終圖像前需要

# 將其值截?cái)嘣?.0-1.0范圍區(qū)間,否則不僅圖像無(wú)法正常可視化,以此為輸入的神經(jīng)網(wǎng)絡(luò)

# 的訓(xùn)練質(zhì)量也可能受到影響。

# 如果對(duì)圖像進(jìn)行多項(xiàng)處理操作,那么這一截?cái)噙^(guò)程應(yīng)在所有處理完成后進(jìn)行。舉例而言,

# 假如對(duì)圖像進(jìn)行多項(xiàng)處理操作,那么這一截?cái)噙^(guò)程應(yīng)當(dāng)在所有處理完成后進(jìn)行。舉例而言。

# 假如對(duì)圖像一次提高亮度和減少對(duì)比度,那么第二個(gè)操作可能將第一個(gè)操作生成的部分

# 過(guò)亮的像素回到不超過(guò)1.0的范圍內(nèi),因此在第一個(gè)操作后不應(yīng)該立即截?cái)唷?/p>

# 下面的樣例假設(shè)截?cái)嗖僮髟谧罱K可視化圖像前進(jìn)行。

adjusted = tf.clip_by_value(adjusted, 0.0, 1.0)

# 將圖像的亮度+0.5

adjuested = tf.image.adjusted_brightness(img_data, 0.5)

# 在(-max_delta, max_delta)的范圍隨機(jī)調(diào)整圖像的亮度。

adjusted = tf.image.random_brightness(image, max_delta)

以下代碼顯示了如何調(diào)整圖像的對(duì)比度:# 將圖像的對(duì)比度減少到0.5倍

adjusted = tf.image.adjust_contrast(img_data, 0.5)

# 將圖像的對(duì)比度增加5倍

adjusted = tf.image.adjust_contrast(img_data, 5)

# 在[lower, upper]的范圍隨機(jī)調(diào)整圖的對(duì)比度

adjusted = tf.image.random_contrast(image, lower, upper)

以下代碼顯示了如何調(diào)整圖像的色相:# 下面4條命令分別將色相加0.1, 0.3, 0.6和0.9

adjusted = tf.image.adjust_hue(img_data, 0.1)

adjusted = tf.image.adjust_hue(img_data, 0.3)

adjusted = tf.image.adjust_hue(img_data, 0.6)

adjusted = tf.image.adjust_hue(img_data, 0.9)

# 在[-max_delta, max_delta]的范圍內(nèi)隨機(jī)調(diào)整圖像的色相。max_delta的取值在[0, 0.5]之間

adjusted = tf.image.random_hue(image, max_delta)

以下代碼顯示了如何調(diào)整圖像的飽和度:# 將圖像的飽和度-5

adjusted = tf.image.adjust_saturation(img_data, -5)

# 將圖像的飽和度+5

adjusted = tf.image.adjust_saturation(img_data, +5)

# 在[lower, upper]的范圍內(nèi)隨機(jī)調(diào)整圖像的飽和度

adjusted = tf.images.random_satutation(image, lower, upper)

除了調(diào)整圖像的亮度、對(duì)比度、飽和度和色相,tensorflow還提供API來(lái)完成圖像標(biāo)準(zhǔn)化的操作。這個(gè)操作就是將圖像上的亮度均值變?yōu)?,方差變?yōu)?.以下代碼實(shí)現(xiàn)了這個(gè)功能。# 將代表一張圖像的三維矩陣中的數(shù)字均值變?yōu)?,方差變?yōu)?

adjusted = tf.image.pet_standerdization(img_data)

5、處理框標(biāo)準(zhǔn)

在很多圖像識(shí)別任務(wù)的數(shù)據(jù)集中,圖像中需要關(guān)注的物體通常會(huì)被標(biāo)注框圈出來(lái)。tensorflow提供了一些工具來(lái)處理標(biāo)注框。以下代碼展示了如何通過(guò)tf.image.draw_bounding_boxes函數(shù)加入標(biāo)注框。# 將圖像縮小一些,這樣可視化能讓標(biāo)注框更加清楚。

img_data = tf.image.resize_images(img_data, [180, 26], method=1)

# tf.image.draw_bounding_boxes函數(shù)要求圖像矩陣中的數(shù)字為實(shí)數(shù),所以需要先將

# 圖像轉(zhuǎn)化為實(shí)數(shù)類型。tf.images.draw_bounding_boxes函數(shù)圖像的輸入是一個(gè)

# batch的數(shù)據(jù),也就是多張圖像組成的四維矩陣,所以需要將解碼之后的圖像矩陣加一維。

batched = tf.expand_dims(

tf.images.convert_image_dtype(img_data, tf.float32), 0)

# 給出每一張圖像的所有標(biāo)注框。一個(gè)標(biāo)注框有4個(gè)數(shù)字,分別代表[ymin, xmin, ymax, xmax]

# 注意這里給出的數(shù)字都是圖像的相對(duì)位置。比如在180*267的圖像中,

# [0.35, 0.47, 0.5, 0.56]代表了從(63, 125)到(90, 150)的圖像。

boxes = tf.constant([[[0.05, 0.05, 0.9, 0.7], [0.35, 0.47, 0.5, 0.56]]])

result = tf.image.draw_bounding_boxes(batched, boxes)

和隨機(jī)翻轉(zhuǎn)圖像、隨機(jī)調(diào)整顏色類似,隨機(jī)截取圖像上有信息含量的部分也是一個(gè)提高模型健壯性(robustness)的一種方式。這樣可以使訓(xùn)練得到的模型不受被識(shí)別物體大小的影響。以下程序中展示了如何通過(guò)tf.image.sample_distored_bounding_box函數(shù)來(lái)完成截取圖像的過(guò)程。boxes = tf.constant([[[0.05, 0.05, 0.9, 0.7],[0.35, 0.47, 0.5, 0.56]]])

# 可以通過(guò)提供標(biāo)注框的方式來(lái)告訴隨機(jī)截取圖像的算法哪些部分是“有信息量”的

# min_object_covered=0.4 表示截取部分至少包含某個(gè)標(biāo)注框40%的內(nèi)容。

begin, size, bbox_for_draw = tf.image.sample_distorted_bounding_box(

tf.shape(img_data), bounding_boxes=boxes,

min_object_covered=0.4)

# 通過(guò)標(biāo)注框可視化隨機(jī)截取得到的圖像。

batched = tf.expand_dims(tf.images.covert_image_dtype(img_data, tf.float32), 0)

image_with_box = tf.image.draw_bounding_boxes(batched, bbox_for_draw)

# 截取隨機(jī)出來(lái)的圖像。因?yàn)樗惴◣в须S機(jī)成分,所以

# 每次得到的結(jié)果會(huì)有所不同

distorted_image = tf.slice(img_data, begin, size)

6、圖像預(yù)處理完整例程

在解決真實(shí)的圖像識(shí)別問(wèn)題時(shí),一般同時(shí)使用多種處理方法。這節(jié)將給出一個(gè)完整的樣例程序展示如何將不同的圖像處理函數(shù)結(jié)合成一個(gè)完成了從圖像片段截取,到圖像大小調(diào)整再到圖像翻轉(zhuǎn)及色彩調(diào)整的整個(gè)圖像預(yù)處理過(guò)程。import tensorflow as tf

import numpy as np

from matplotlib import pyplot as plt

# 給定一張圖像,隨機(jī)調(diào)整圖像的色彩。因?yàn)檎{(diào)整亮度、對(duì)比度、飽和度和色相的順序會(huì)影

# 響最后得到的結(jié)果,所以可以定義多種不同的順序。具體使用哪一種順序可以在訓(xùn)練

# 數(shù)據(jù)預(yù)處理時(shí)隨機(jī)地選擇一種。這樣可以進(jìn)一步降低無(wú)關(guān)因素對(duì)模型的影響。

def distort_color(image, color_ordering=0):

if color_ordering == 0:

image = tf.image.random_brightness(image, max_delta=32. / 255.)

image = tf.image.random_saturation(image, lower=0.5, upper=1.5)

image = tf.image.random_hue(image, max_delta=0.2)

image = tf.image.random_contrast(image, lower=0.5, upper=1.5)

elif color_ordering == 1:

image = tf.image.random_saturation(image, lower=0.5, upper=1.5)

image = tf.image.random_brightness(image, max_delta=32. / 255.)

image = tf.image.random_contrast(image, lower=0.5, upper=1.5)

image = tf.image.random_hue(image, max_delta=0.2)

elif color_ordering == 2:

# 還可以定義其他的排列,但在這里就不再一一列出。

...

return tf.clip_by_value(image, 0.0, 1.0)

# 給定一張解碼后的圖像、目標(biāo)圖像的尺寸以及圖像上的標(biāo)注框,此函數(shù)可以對(duì)給出的圖像進(jìn)行預(yù)

# 處理。這個(gè)函數(shù)的輸入圖像時(shí)圖像識(shí)別問(wèn)題中原始的訓(xùn)練圖像,而輸出則是神經(jīng)網(wǎng)絡(luò)模型的輸入

# 層。注意這里只處理模型的訓(xùn)練數(shù)據(jù),對(duì)于預(yù)測(cè)的數(shù)據(jù),一般不需要隨機(jī)變換的步驟。

def preprocess_for_train(image, height, width, bbox):

# 如果沒(méi)有提供標(biāo)注框,則認(rèn)為整個(gè)圖像就是需要關(guān)注的部分。

if bbox is None:

bbox = tf.constant([0.0, 0.0, 1.0, 1.0], dtype=tf.float32, shape=[1, 1, 4])

# 轉(zhuǎn)換圖像張量的類型。

if image.dtype != tf.float32:

image = tf.image.convert_image_dtype(image, dtype=tf.float32)

# 隨機(jī)截取圖像,減少需要關(guān)注的物體大小對(duì)圖像識(shí)別算法的影響。

bbox_begin, bbox_size, _ = tf.image.sample_distorted_bounding_box(

tf.shape(image), bounding_boxes=bbox)

distorted_image = tf.slice(image, bbox_begin, bbox_size)

# 將隨機(jī)截取的圖像調(diào)整為神經(jīng)網(wǎng)絡(luò)輸入層的大小。大小調(diào)整的算法是隨機(jī)選擇的。

distorted_image = tf.image.resize_images(

distorted_image, [height, width], method=np.random.randint(2))

# 隨機(jī)左右翻轉(zhuǎn)圖像。

distorted_image = tf.image.random_flip_left_right(distorted_image)

# 使用一種隨機(jī)的順序調(diào)整圖像色彩。

distorted_image = distort_color(distorted_image, np.random.randint(2))

return distorted_image

image_raw_data = tf.gfile.FastGFile("timg.jpeg", "rb").read()

with tf.Session() as sess:

img_data = tf.image.decode_jpeg(image_raw_data)

boxes = tf.constant([[[0.05, 0.05, 0.9, 0.7], [0.35, 0.47, 0.5, 0.56]]])

# 運(yùn)行6次獲得6種不同的圖像

for i in range(6):

# 將圖像的尺寸調(diào)整為299*299

result = preprocess_for_train(img_data, 299, 299, boxes)

plt.imshow(result.eval())

plt.show()

總結(jié)

以上是生活随笔為你收集整理的python的窗口处理模块_python的图像处理模块的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。