本文總結(jié)了使用Python進(jìn)行機(jī)器視覺(jué)(圖像處理)編程時(shí)常用的數(shù)據(jù)結(jié)構(gòu),主要包括以下內(nèi)容:
數(shù)據(jù)結(jié)構(gòu)
序列操作:索引(indexing)、分片(slicing)、加(adding)、乘(multipying)等
列表:創(chuàng)建、list函數(shù)、基本操作:賦值、刪除、分片賦值、插入、排序等
元組:創(chuàng)建、tuple函數(shù)、基本操作
NumPy數(shù)組:創(chuàng)建數(shù)組、創(chuàng)建圖像、獲取形狀、維度、元素個(gè)數(shù)、元素類(lèi)型、訪(fǎng)問(wèn)像素、通道分離、使用mask
1. 數(shù)據(jù)結(jié)構(gòu)
數(shù)據(jù)結(jié)構(gòu)是通過(guò)某種方式(例如對(duì)元素進(jìn)行編號(hào))組織在一起的數(shù)據(jù)元素的集合,這些數(shù)據(jù)元素可以是數(shù)字或者字符,甚至可以是其他數(shù)據(jù)結(jié)構(gòu)。在Python中最基本的數(shù)據(jù)結(jié)構(gòu)是序列(sequence)。序列中每個(gè)元素被分配一個(gè)序號(hào)——即元素的位置,也稱(chēng)為索引(index),第一個(gè)元素的索引是0,第二個(gè)是1,以此類(lèi)推。
python包含6種內(nèi)建序列,最常用的兩種類(lèi)型是:列表和元組。列表和元組的主要區(qū)別在于列表可以修改,元組不可以修改。而用于處理圖像的基本數(shù)據(jù)結(jié)構(gòu)是數(shù)組,由于Python標(biāo)準(zhǔn)庫(kù)中的內(nèi)建數(shù)組只能處理一維數(shù)組并且提供的功能較少,因此做編程時(shí)常使用NumPy模塊的array()數(shù)組表示圖像,并進(jìn)行各類(lèi)處理。
2. 通用序列操作
所有序列都可以進(jìn)行某些特定操作,包括:索引(indexing)、分片(slicing)、加(adding)、乘(multipying)以及檢查某個(gè)元素是否屬于序列成員(成員資格),除此之外,python還有計(jì)算序列長(zhǎng)度、找出最大元素和最小元素的內(nèi)建函數(shù)。
(1)索引
序列中所有元素的編號(hào)都是從0開(kāi)始遞增。
>>>greeting = 'Hello'
>>>greeting[0]
'H'
>>>greeting[1]
'e'
所有序列都可以通過(guò)這種方式獲取元素。最后一個(gè)元素的編號(hào)是-1
>>>greeting[-1]
'o'
如果一個(gè)函數(shù)調(diào)用返回一個(gè)序列,則可以直接對(duì)返回序列進(jìn)行索引操作
>>>fourth = raw_input('Year: ')[3]
Year: 2016
>>>fourth
6
(2)分片
使用分片操作來(lái)方位一定范圍內(nèi)的元素。分片通過(guò)冒號(hào)隔開(kāi)兩個(gè)索引來(lái)實(shí)現(xiàn)。
>>>tag='Python web site'
>>>tag[9:30]
'"http://www.python.org '
>>>numbers=[1,2,3,4,5,6,7,8,9,10]
>>>numbers[3:6]
[4,5,6]
>>>numbers[0:1]
[1]
注意索引邊界:第1個(gè)索引的元素包含在分片內(nèi),第2個(gè)索引的元素不在分片內(nèi),如果要索引最后一個(gè)元素
>>>numbers[-3:]
[8,9,10]
>>>print numbers[-1:]
[10]
這種方法同樣適用于序列開(kāi)始的元素:
>>>numbers[:3]
[1,2,3]
如果需要復(fù)制整個(gè)序列,可以將兩個(gè)索引都置空:
>>>numbers[:]
[1,2,3,4,5,6,7,8,9,10]
我們還可以使用第三個(gè)參數(shù)設(shè)置分片的步長(zhǎng),下面代碼為從numbers序列中選出從0到10,步長(zhǎng)為2的元素
>>>numbers[0:10:2]
[1,3,5,7,9]
如果要將每4個(gè)元素中的第1個(gè)提取出來(lái)可以這樣寫(xiě)
>>>numbers[::4]
[1,5,9]
步長(zhǎng)為負(fù)數(shù)將向左提取元素,當(dāng)使用負(fù)數(shù)作為步長(zhǎng)時(shí)開(kāi)始的點(diǎn)的索引必須大于結(jié)束點(diǎn)的索引
>>>number[8:3:-1]
[9,8,7,6,5]
>>>numbers[10:0:-2]
[10, 8, 6, 4, 2]
(3)序列相加
使用+運(yùn)算符可以進(jìn)行序列的連接操作:
>>>[1,2,3] + [4,5,6]
[1,2,3,4,5,6]
>>>'Hello, ' + 'world!'
'Hello, world!'
注意同種類(lèi)型的序列才能連接到一起,列表和字符串是無(wú)法連接的。
(4)乘法
數(shù)字x乘以序列會(huì)生成新的序列。新序列中,原來(lái)的序列將被重復(fù)x次
>>>'pyhton' * 5
'pyhtonpyhtonpyhtonpyhtonpyhton'
>>>[42]*10
[42,42,42,42,42,42,42,42,42,42]
(5)None空列表和初始化
空列表可以通過(guò)兩個(gè)中括號(hào)中間什么都不寫(xiě)表示[]
如果想創(chuàng)建一個(gè)占用 10個(gè)元素空間,卻不包括任何有用內(nèi)容的列表,可以用:
>>>[0]*10
None是一個(gè)Python的內(nèi)建值,它的確切含義是這里什么都沒(méi)有。
>>>[None]*10
(6)成員資格in
為了檢查一個(gè)值是否在列表中,可以使用in運(yùn)算符,返回布爾值真或假:
>>>permission = 'rw'
>>>'w' in permission
True
>>>'x' in permission
False
下面的例子,檢查用戶(hù)名和PIN碼:
database = [
['albert', '1234'],
['dilbert','4242'],
['smith', '7524'],
['jones', '9843']
]
username = raw_input('User name: ')
pin = raw_input('PIN code: ')
if [username,pin] in database:
print 'Access granted'
運(yùn)行結(jié)果:
User name: jones
PIN code: 9843
Access granted
(7)長(zhǎng)度、最小值和最大值
內(nèi)建函數(shù)len,min,max
>>>numbers[100,34,678]
>>>len(numbers)
3
>>>max(numbers)
678
>>>min(numbers)
34
>>>max(2,3)
3
>>>min(2,3,4,5)
2
3. 列表
(1)list函數(shù)
因?yàn)樽址荒芟窳斜硪粯有薷?,所以有時(shí)候根據(jù)字符串創(chuàng)建列表很有用
>>>list('Hello')
['H','e','l','l','o']
list適用于所有類(lèi)型的序列,而不只是列表。
(2)列表基本操作
元素賦值
>>>x=[1,1,1]
>>>x[1]=2
>>>x
[1,2,1]
刪除元素
>>>x=[1,2,3]
>>>del x[1]
>>>x
[1,3]
del也可刪除其他元素,甚至是變量。
分片賦值
>>>name=list('Perl')
>>>name
['P','e','r','l']
>>>name[2:]=list('ar')
>>>name
['P','e','a','r']
通過(guò)分片賦值插入元素和刪除元素
>>>numbers=[1,5]
>>>numbers[1:1]=[2,3,4]
>>>numbers
[1,2,3,4,5]
>>>numbers[1:4]=[]
>>>numbers
[1,5]
(3)列表方法
列表方法的使用:對(duì)象.方法(參數(shù))
append 在列表末尾追加
>>>a = [1,2,3]
>>>a.append['4']
>>>a
[1,2,3,4]
count 統(tǒng)計(jì)某個(gè)元素在列表中出現(xiàn)的次數(shù)
>>>['to','go','will','be','to','not'].count('to')
2
extend 在列表末尾一次性追加另一個(gè)序列中的多個(gè)值
>>>a = [1,2,3]
>>>b = [4,5,6]
>>>a.extend(b)
>>>a
[1,2,3,4,5,6]
>>>c = [1,2,3]
>>>d = [4,5,6]
>>>c+d
[1,2,3,4,5,6]
>>>c
[1,2,3]
index 從列表中找出某個(gè)值第一個(gè)匹配項(xiàng)的索引位置
>>>slogen= ['we', 'are', 'the', 'champion']
>>>slogen.index('are')
1
>>> slogen[1]
'are'
insert 將對(duì)象插入到列表中
>>>numbers=[1,2,3,4,6]
>>>numbers.insert(4,'five')
>>>numbers
[1, 2, 3, 4, 'five', 6]
第1個(gè)參數(shù)為插入的位置,在此索引前插入;
第2個(gè)參數(shù)為插入的元素內(nèi)容
insert方法的操作也可用分片的方法實(shí)現(xiàn)元素插入
>>>numbers=[1,2,3,4,6]
>>>numbers[4:4]=['five']
>>>numbers
[1, 2, 3, 4, 'five', 6]
pop 移除列表中的一個(gè)元素
pop方法可實(shí)現(xiàn)一個(gè)常見(jiàn)的數(shù)據(jù)結(jié)構(gòu)——棧。棧的原理就像堆盤(pán)子,只能在頂部放一個(gè)盤(pán)子,同樣也只能從頂部拿走一個(gè)盤(pán)子。最后被放入堆棧的元素最先被移除。(此原則稱(chēng)為后進(jìn)先出,LIFO)。
pop()方法默認(rèn)移除列表中的最后一個(gè)元素,并返回該元素的值
>>>numbers=[1,2,3,4,5]
>>>numbers.pop()
5
>>> numbers
[1, 2, 3, 4]
如果想要移除列表中的第一個(gè)元素,可以用pop(0)
>>>numbers=[1,2,3,4,5]
>>>numbers.pop(0)
1
>>> numbers
[2, 3, 4, 5]
Python沒(méi)有入棧操作,可以用append方法代替。
如果想要實(shí)現(xiàn)一個(gè)先進(jìn)先出(FIFO)隊(duì)列,可以使用insert(0,...)來(lái)替代append方法。或者也可以使用append方法,但必須用pop(0)替代pop()。也可使用collection模塊中的deque對(duì)象。
remove 移除列表中的某個(gè)值的第一個(gè)匹配項(xiàng)
>>>x=['to','go','will','be','to','not']
>>>x.remove('to')
>>>x
['go','will','be','to','not']
reverse 將列表中的元素反向存放
>>>x=[1,2,3]
>>>x.reverse()
>>>x
[3,2,1]
sort 在原始位置對(duì)列表進(jìn)行排序
在原始位置排序?qū)⒏淖冊(cè)瓉?lái)的列表,從而讓其中的元素能按一定的順序重新排列,而不是簡(jiǎn)單的返回一個(gè)排序的列表副本。
>>>x=[3,1,2,6,4,5,7,9,8]
>>>x.sort()
>>>x
[1,2,3,4,5,6,7,8,9]
注意:sort方法只改變?cè)剂斜淼呐判?,并沒(méi)有返回值。如果需要一個(gè)重新排序的列表副本,應(yīng)該如下操作:
>>>x=[3,1,2,6,4,5,7,9,8]
>>>y=x[:] #不能直接y=x
>>>y.sort()
>>>y
[1,2,3,4,5,6,7,8,9]
>>>x
[3,1,2,6,4,5,7,9,8]
注意:y=x只是讓y和x指向同一個(gè)列表,而y=x[:]是復(fù)制整個(gè)x列表給y。
sorted 獲取排序列表的副本
>>>x=[3,1,2,6,4,5,7,9,8]
>>>y=sorted(x)
>>>y
[1,2,3,4,5,6,7,8,9]
>>>x
[3,1,2,6,4,5,7,9,8]
sort方法的高級(jí)排序
希望列表元素能按照特定的方式排序(而不是sort函數(shù)默認(rèn)的方式,即根據(jù)Python默認(rèn)排序規(guī)則按升序排列元素),可以通過(guò)compare(x,y)的形式自定義比較函數(shù)。compare(x,y)函數(shù)會(huì)在xy時(shí)返回正數(shù),如果x=y則返回0(根據(jù)自己定義)。定義好該函數(shù)后,可以提供給sort方法作為參數(shù)。內(nèi)建函數(shù)cmp提供了比較函數(shù)的默認(rèn)實(shí)現(xiàn)方式:
>>>cmp(16,12)
1
>>>cmp(10,12)
-1
>>>cmp(10,10)
0
>>>numbers=[1,4,2,9]
>>>numbers.sort(cmp)
>>>numbers
[1,2,4,9]
sort方法還有另外兩個(gè)參數(shù)可選,可以通過(guò)某個(gè)名字來(lái)指定該參數(shù)(關(guān)鍵字參數(shù)):
參數(shù):key
提供一個(gè)在排序中使用的函數(shù),該函數(shù)不是直接確定對(duì)象的大小,而是為每個(gè)元素創(chuàng)建一個(gè)鍵,然后所有元素根據(jù)鍵來(lái)排序。
>>>x=['nor','break','if','then','present']
>>>x.sort(key=len) # 按字符串長(zhǎng)度排序
>>>x
['if', 'nor', 'then', 'break', 'present']
參數(shù):reverse
另一個(gè)關(guān)鍵字參數(shù)reverse是簡(jiǎn)單的布爾值,用于指明是否要進(jìn)行反向排序
>>> x=[3,1,2,6,4,5,7,9,8]
>>> x.sort(reverse=True)
>>>x
[9, 8, 7, 6, 5, 4, 3, 2, 1]
注意:cmp,key,reverse參數(shù)都可用于sorted函數(shù)。
4. 元組
元組與列表一樣,也是一種序列,但元組是不可變列表,元組不能修改。
元組的作用
體現(xiàn)在映射(和集合的成員)中當(dāng)做鍵使用——列表不行
元組在很多內(nèi)建函數(shù)的返回值存在,也就是說(shuō)我們必須對(duì)元組進(jìn)行處理
(1)創(chuàng)建元組
創(chuàng)建一個(gè)元組
>>>1,2,3
(1,2,3)
元組大部時(shí)候通過(guò)圓括號(hào)括起來(lái)
>>>x=(1,2,3)
>>>x
(1,2,3)
創(chuàng)建一個(gè)空元組
空元組可以用沒(méi)有內(nèi)容的空括號(hào)括起來(lái)
>>>()
()
創(chuàng)建一個(gè)包含一個(gè)元素的元組
>>>(10,)
(10,)
是的,一個(gè)元素也需要用逗號(hào)。逗號(hào)很重要,看下面的例子
>>>2*(3+2)
10
>>>2*(3+2,)
(5, 5)
不加逗號(hào)為數(shù)字,加逗號(hào)就是元組。
(2)tuple函數(shù)
tuple函數(shù)以一個(gè)序列作為參數(shù)并轉(zhuǎn)換為元組,如果參數(shù)本身就是元組,則不發(fā)生變化。
>>>tuple([1,2,3])
(1,2,3)
>>>tuple(['a','b','c'])
('a','b','c')
>>>tuple((1,2,3))
(1,2,3)
(3)元組基本操作
元組除了創(chuàng)建和訪(fǎng)問(wèn)其元素外,沒(méi)有太多其他操作,元組操作與操作其他序列類(lèi)似。
>>>x=1,2,3
>>>x[1]
2
>>>x[0:2]
(1,2)
5. NumPy的array(數(shù)組)對(duì)象
NumPy模塊用于python計(jì)算機(jī)視覺(jué)編程時(shí)的向量、矩陣的表示與操作,是opencv for python的主要數(shù)據(jù)結(jié)構(gòu)模塊。NumPy中的數(shù)組對(duì)象array是多維的,可以用來(lái)表示向量、矩陣和圖像。一個(gè)數(shù)組對(duì)象很像一個(gè)列表(或者是列表的列表),但數(shù)組中的元素必須具有相同的數(shù)據(jù)類(lèi)型。除非創(chuàng)建數(shù)組對(duì)象時(shí)指定數(shù)據(jù)類(lèi)型,否則數(shù)據(jù)類(lèi)型會(huì)按照數(shù)據(jù)的類(lèi)型自動(dòng)確定。
本節(jié)代碼假定已經(jīng)以如下形式導(dǎo)入OpenCV和NumPy兩個(gè)庫(kù)
import cv2
import numpy as np
(1)np.array()創(chuàng)建數(shù)組
>>> a = np.array([1, 2, 3, 4])
>>> b = np.array((5, 6, 7, 8))
>>> c = np.array([[1, 2, 3, 4],[4, 5, 6, 7], [7, 8, 9, 10]])
>>> b
array([5, 6, 7, 8])
>>> c
array([[1, 2, 3, 4],
[4, 5, 6, 7],
[7, 8, 9, 10]])
>>> d = np.arange(15).reshape(3, 5)
>>> d
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
(2)np.array()創(chuàng)建黑白圖像
使用np.zeros()創(chuàng)建一幅圖像,dtype為元素?cái)?shù)據(jù)類(lèi)型,下文有具體分析,8位灰度圖像為uint8型。接著用np.ones()創(chuàng)建一幅圖像,通過(guò)賦值稱(chēng)為一幅白色圖像。
img1 = np.ones((100,200),dtype=np.uint8)
img2 = np.ones((100,200),dtype=np.uint8)
img2[:]=255;
cv2.imshow('img1',img1)
cv2.imshow('img2',img2)
cv2.waitKey(0)
?
彩色圖像的創(chuàng)建需要指定一個(gè)3維數(shù)組,具體方法請(qǐng)看下文。
(3)ndarray.shape屬性獲得/修改數(shù)組形狀
獲取數(shù)組 shape 屬性
數(shù)組的形狀可以通過(guò)其shape 屬性獲得,它是一個(gè)描述數(shù)組各個(gè)軸長(zhǎng)度的元組(tuple),看看上文定義的a,c數(shù)組的shape屬性:
>>> a.shape
(4,)
>>> c.shape
(3, 4)
數(shù)組a的shape 屬性只有一個(gè)元素,因此它是一維數(shù)組。而數(shù)組c的shape屬性有兩個(gè)元素,因此它是二維數(shù)組,其中第0軸的長(zhǎng)度為3,第1軸的長(zhǎng)度為4。
獲取圖像的寬高
圖像本質(zhì)是矩陣,因此可以使用shape屬性獲取圖像矩陣的行、列和通道數(shù),如果圖像是灰度圖,則沒(méi)有第3個(gè)參數(shù)。我們也可以用ndim方法判斷圖像通道數(shù):
img = cv2.imread('f:/images/cow.jpg')
rows,cols,channels = img.shape
print 'rows,cols,channels = ',rows,cols,channels
print 'demension = ',img.ndim
cv2.imshow('test',img)
cv2.waitKey(0)
運(yùn)行結(jié)果:
rows,cols,channels = 400 600 3
demension = 3
修改數(shù)組 shape 屬性
可以通過(guò)修改數(shù)組的shape 屬性,在保持?jǐn)?shù)組元素個(gè)數(shù)不變的情況下,改變數(shù)組每個(gè)軸的長(zhǎng)度。下面的例子將數(shù)組c的shape 屬性改為(4,3),注意:從(3,4)改為(4,3)并不是對(duì)數(shù)組進(jìn)行轉(zhuǎn)置,而只是改變每個(gè)軸的大小,數(shù)組元素在內(nèi)存中的位置并沒(méi)有改變。
>>> c = np.array([[1, 2, 3, 4],[4, 5, 6, 7], [7, 8, 9, 10]])
>>> c.shape = 4,3
>>> c
array([[ 1, 2, 3],
[ 4, 4, 5],
[ 6, 7, 7],
[ 8, 9, 10]])
當(dāng)設(shè)置某個(gè)軸的元素個(gè)數(shù)為-1 時(shí),將自動(dòng)計(jì)算此軸的長(zhǎng)度。由于數(shù)組c 中有12 個(gè)元素,因此下面的程序?qū)?shù)組c 的shape 屬性改為了(2,6):
>>> c.shape = 2,-1
>>> c
array([[ 1, 2, 3, 4, 4, 5],
[ 6, 7, 7, 8, 9, 10]])
使用數(shù)組的reshape()方法,可以創(chuàng)建指定形狀的新數(shù)組,而原數(shù)組的形狀保持不變
>>> a = np.array([1, 2, 3, 4])
>>> e = a.reshape((2,2)) # 也可以用a.reshape(2,2)
>>> e
array([[1, 2],
[3, 4]])
>>> a
array([1, 2, 3, 4])
注意:數(shù)組a 和e 其實(shí)共享數(shù)據(jù)存儲(chǔ)空間,因此修改其中任意一個(gè)數(shù)組的元素都會(huì)同時(shí)修改另外一個(gè)數(shù)組的內(nèi)容:
>>> a[1] = 100 # 將數(shù)組a 的第一個(gè)元素改為100
>>> e # 注意數(shù)組d 中的2 也被改為了100
array([[ 1, 100],
[3, 4]])
(4)ndarray.ndim屬性:數(shù)組維度
返回?cái)?shù)組的軸數(shù)量,即維度。在Python中維度稱(chēng)為rank
(5)ndarray.dtype屬性:數(shù)組元素類(lèi)型
數(shù)組的元素類(lèi)型可以通過(guò)dtype 屬性獲得。前面例子中,創(chuàng)建數(shù)組所用序列的元素都是整數(shù),因此所創(chuàng)建的數(shù)組的元素類(lèi)型是整型,并且是32bit 的長(zhǎng)整型:
>>> c.dtype
dtype('int32')
>>>print img1.dtype
uint8
NumPy 中的數(shù)據(jù)類(lèi)型都有幾種字符串表示方式,字符串和類(lèi)型之間的對(duì)應(yīng)關(guān)系都存儲(chǔ)在typeDict 字典中,例如'd'、'double'、'float64'都表示雙精度浮點(diǎn)類(lèi)型:
>>> np.typeDict["d"]
>>> np.typeDict["double"]
>>> np.typeDict["float64"]
完整的類(lèi)型列表可以通過(guò)下面的語(yǔ)句得到,它將typeDict字典中所有的值轉(zhuǎn)換為一個(gè)集合,從而去除其中的重復(fù)項(xiàng):
>>> print set(np.typeDict.values())
set([, ,
, ,
, ,
, ,
, ,
, ,
, ,
, ,
, ,
, ,
, ,
, ])
(6)ndarray.size屬性:數(shù)組元素個(gè)數(shù)
數(shù)組中所有元素的個(gè)數(shù)。這個(gè)參數(shù)等于shape屬性返回的參數(shù)的乘積。
>>>print img1.shape
(100,200)
>>>print img1.size
20000
(7)ndarray.itemsize屬性:?jiǎn)蝹€(gè)數(shù)組元素所占字節(jié)數(shù)
數(shù)組單個(gè)元素所占的字節(jié)數(shù)。例如,數(shù)組元素為float64型時(shí),其itemsize=8 (=64/8)。如果是復(fù)數(shù)complex32類(lèi)型,則itemsize 4 (=32/8)。
>>>print img1.itemsize
1
(8)ndarray.data屬性:實(shí)際數(shù)組元素的緩存
通常用不到這個(gè)屬性,因?yàn)榭梢酝ㄟ^(guò)下標(biāo)方位數(shù)組元素。
(9)訪(fǎng)問(wèn)像素/訪(fǎng)問(wèn)多維數(shù)組元素
NumPy的array數(shù)組對(duì)象與Python中的序列一樣,可以通過(guò)下標(biāo)、切片的方式訪(fǎng)問(wèn)。
多維數(shù)組的存取和一維數(shù)組類(lèi)似,因?yàn)槎嗑S數(shù)組有多個(gè)軸,因此它的下標(biāo)需要用多個(gè)值表示。NumPy 采用元組(tuple)作為數(shù)組的下標(biāo),元組中的每個(gè)元素和數(shù)組的每個(gè)軸對(duì)應(yīng)。下圖顯示了一個(gè)形狀為(6,6)的數(shù)組a,圖中用不同顏色和線(xiàn)型標(biāo)識(shí)出各個(gè)下標(biāo)對(duì)應(yīng)的選擇區(qū)域。
>>> a = np.arange(0, 60, 10).reshape(-1, 1) + np.arange(0, 6)
>>> a
array([[ 0, 1, 2, 3, 4, 5],
[10, 11, 12, 13, 14, 15],
[20, 21, 22, 23, 24, 25],
[30, 31, 32, 33, 34, 35],
[40, 41, 42, 43, 44, 45],
[50, 51, 52, 53, 54, 55]])
?
Python 的下標(biāo)語(yǔ)法(用[]存取序列中的元素)本身并不支持多維,但是由于可以使用任何對(duì)象作為下標(biāo),因此NumPy 使用元組作為下標(biāo)存取數(shù)組中的元素,使用元組可以很方便地表示多個(gè)軸的下標(biāo)。雖然在Python 程序中,經(jīng)常用圓括號(hào)將元組的元素括起來(lái),但其實(shí)元組的語(yǔ)法只需要用逗號(hào)隔開(kāi)元素即可,例如“x,y=y,x”就是用元組交換變量值的一個(gè)例子。因此a[1,2]和a[(1,2)]完全相同,都是使用元組(1,2)作為數(shù)組a 的下標(biāo)。
(10)np.array()創(chuàng)建彩色圖像
下面的例子通過(guò)創(chuàng)建一個(gè)3維數(shù)組作為3通道彩色圖像,并給不同通道賦值,創(chuàng)建兩幅不同的色彩圖像:
import cv2
import numpy as np
import random
# create a blue image
img3 = np.zeros((100,200,3),dtype=np.uint8)
img3[:,:,0]=255 # blue channel
# create a random color image
img4 = np.zeros((100,200,3),dtype=np.uint8)
seq = xrange(0,255)
ch0 = random.sample(seq,200)
ch1 = random.sample(seq,200)
ch2 = random.sample(seq,200)
img4[0:200,:,0] = ch0
img4[0:200,:,1] = ch1
img4[0:200,:,2] = ch2
# display image
cv2.imshow('img3',img3)
cv2.imshow('img4',img4)
cv2.waitKey(0)
cv2.destroyAllWindows()
?
(11)通道分離
下面的代碼實(shí)現(xiàn)BGR通道分離:
img = cv2.imread('f:/images/Lena.jpg')
b = np.zeros((img.shape[0],img.shape[1]), dtype=img.dtype)
g = np.zeros((img.shape[0],img.shape[1]), dtype=img.dtype)
r = np.zeros((img.shape[0],img.shape[1]), dtype=img.dtype)
b[:,:] = img[:,:,0]
g[:,:] = img[:,:,1]
r[:,:] = img[:,:,2]
cv2.imshow("Blue", r)
cv2.imshow("Red", g)
cv2.imshow("Green", b)
cv2.waitKey(0)
cv2.destroyAllWindows()
?
(12)設(shè)置mask屏蔽不感興趣區(qū)域
img = cv2.imread('f:/images/Lena.jpg',0)
mask = np.zeros((img.shape[0],img.shape[1]),dtype=img.dtype)
mask[img.shape[0]/4:3*img.shape[0]/4,img.shape[1]/4:3*img.shape[1]/4] = 255
img_mask = img.copy()
img_mask[mask==0]=0
cv2.imshow('mask',mask)
cv2.imshow('Lena_mask',img_mask)
cv2.imshow('Lena',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
讀取彩色或黑白圖像都可已使用上述代碼。讀取彩色圖像cv2.imread()的可選標(biāo)志為置1。
評(píng)論