第二章:图像处理基础
第二章:圖像處理基礎操作
- 一、圖像的基本表示方法:
- 1. 二值圖像:
- 2. 灰度圖像:
- 3. 彩色圖像:
- 二、像素處理:
- 1. 二值圖像及灰度圖像:
- 2.彩色圖像:
- 3. 使用numpy.array訪問像素:
- 三、感興趣區域(ROI):
- 四、通道操作:
- 1. 通道拆分:
- 2. 通道合并:
- 五、獲取圖像屬性:
本章主要介紹:
- 圖像的基本表示方法
- 像素的訪問和操作
- 感興趣區域的處理
- 通道處理
等知識點。需要注意的是,使用面向Python的OpenCV必須熟練掌握Numpy庫,尤其是Numpy.array庫,Numpy.array庫是python處理圖像的基礎。
一、圖像的基本表示方法:
圖像的基本表示方法有:
- 二值圖像
- 灰度圖像
- 彩色圖像
1. 二值圖像:
二值圖像是指僅包含黑色和白色兩種顏色的圖像。
計算機中,通過矩陣來表示和處理圖像。例如下圖一個A的圖像,計算機在處理該圖像時,會首先將其劃分為一個個的小方塊,即像素點,每一個像素點都是一個獨立的處理單元。然后,將其中白色的像素點置為1,黑色的像素點置為0,用于后續的存儲和處理操作。
2. 灰度圖像:
二值圖像表示起來簡單方便,但是因為其僅有黑白兩種顏色,所表示的圖像不夠細膩。如果需要表示更多的細節,就需要使用更多的顏色。
例如,下圖的灰度圖像:
通常,計算機會將灰度處理為256個灰度級,用區間[0, 255]來表示。其中255表示純白色,0表示純黑色,其余的數值表示從純白色到純黑色之間前不同級別的灰度。
用于表示256個灰度級的數值0-255,正好可以用一個字節(8個2進制位)來表示。如下圖是部分二進制值所對應的十進制值:
有些情況下,也會使用8位二進制來表示一幅二值圖像。這種情況下,255表示白色,0表示黑色,圖像中只存在255和0。
3. 彩色圖像:
? 相比二值圖像和灰度圖像,彩色圖像是更常見的一類圖像。神經生理學實驗發現,在視網膜上存在三種不同的顏色感受器,能夠感受三種不同的顏色:紅色、綠色和藍色,即三基色。自然界中常見的各種色光都可以通過將三基色按照一定的比例混合構成。除此之外,從光學角度出發,可以將顏色解析為主波長、純度、明度等。從心理學和視覺角度出發,可以將顏色解析為色調、飽和度、亮度等。通常,我們將上述方式采用不同的方式來表述顏色的模式稱為色彩空間,或者顏色空間、顏色模式。
? 雖然,不同的色彩空間具有不同的表示方式,但是各種色彩空間之間可以根據相應的公式進行轉換。
? 例如,在RGB色彩空間中,存在R通道、G通道、B通道,共三個通道。每個色彩通道值的方位都在[0, 255]之間。因此,通常用一個三維數組來表示一幅RGB色彩空間的彩色圖像。注意,在OpenCV中,通道的順序是B-G-R。
二、像素處理:
像素是圖像構成的基本單位,像素處理是圖像處理的基本操作,可以通過位置索引的形式對圖像內的元素鏡像訪問、處理。
1. 二值圖像及灰度圖像:
? 在OpenCV中,最小的數據類型是無符號的8位數。因此,在OpenCV中實際是并沒有二值圖像這種數據類型,二值圖像經常是通過處理得到的特殊的灰度圖像,使用0表示黑色,使用255表示白色。
? 通過前面的分析可知,在計算機中,圖像就是一個由像素點組成的矩陣。在面向Python 的OpenCV中,圖像就是Numpy中的數組。一個OpenCV灰度圖像就是一個二維數組,可以使用表達式訪問其中的像素值。例如:可以使用image[0, 0]訪問圖像image第0行第0列未知上的像素點。
示例: 讀取一個灰度圖像,并對其像素進行訪問、修改:
import cv2 img = cv2.imread('lena.bmp', 0) cv2.imshow('before', img) for i in range(10, 100):for j in range(80, 100):img[i, j] = 255 cv2.imshow('after', img) cv2.waitKey() cv2.destroyAllWindows()2.彩色圖像:
RGB模式的彩色圖像在讀入到OpenCV中進行處理時,會按照行方向依次讀取該RGB圖像的 B通道、G通道、R通道的像素點,并將像素點以行為單位存儲在ndarray的列中。例如,有一幅大小為R行×C列的原始RGB圖像,其在OpenCV內衣BGR模式的三維數組形式存儲。
可以使用表達式訪問數組內的值。例如,可以使用image[0, 0, 0] 訪問圖像image第0行第0列像素點的B通道。
- 第1個索引表示第0行
- 第2個索引表示第0列
- 第3個索引表示第0個顏色通道
示例: 讀取一幅彩色圖像,并對其像素進行訪問、修改。
import cv2 img = cv2.imread('lena512color.tiff') cv2.imshow('before', img) # 白色 for i in range(0, 50):for j in range(0, 100):for k in range(0, 3):img[i, j, k] = 255 # 灰色 for i in range(50, 100):for j in range(0, 100):img[i, j] = [128, 128, 128] # 黑色 for i in range(100, 150):for j in range(0, 100):img[i, j] = 0 cv2.imshow('after', img) cv2.waitKey() cv2.destroyAllWindows()3. 使用numpy.array訪問像素:
numpy.array提供了item()和itemset()行數來訪問和修改像素值,而且這兩個函數都是經過優化處理的,能夠大幅度提高處理效率。在訪問和修改像素點的值時,利用numpy.array提供的函數要比直接使用索引快得多,同時這兩個函數的可讀性也更好。
-
二值圖像及灰度圖像:
可以將二值圖像理解為特殊的灰度圖像。- item():訪問像素點,語法:item(行,列)
- item():修改像素值,語法:itemset(索引值,新值)
示例: 讀取一幅灰度圖像,并對其進行像素值訪問及修改。
import cv2 img = cv2.imread('../lena.bmp', 0) print('讀取像素點img.item(3, 2)=', img.item(3, 2)) img.itemset((3, 2), 255) print('修改后像素點img.item(3, 2)=', img.item(3, 2)) cv2.imshow('before', img) for i in range(10, 200):for j in range(80, 300):img.itemset((i, j), 255) cv2.imshow('after', img) cv2.waitKey() cv2.destroyAllWindows()
-
彩色圖像:
-
同樣可以使用item()函數和itemset()函數來訪問和修改彩色圖像的像素值,過程與操作灰度圖像 相似。不同的是需要補充通道信息。
-
item():訪問EGB模式圖像的像素值。語法:item(行,列, 通道)
-
itemset():修改RGB模式圖像像素值。語法:itemset(三元組索引值,新值)
需要注意,針對RGB圖像的訪問,必須同時指定行、列以及通道,例如img.item(a, b, c)。僅指定行和列是不可以的。
示例: 讀取已否彩色圖像,并對其進行像素訪問、修改
import cv2 img = cv2.imread('lena512color.tiff') cv2.imshow('before', img) print('訪問img.item(0, 0, 0) = ', img.item(0, 0, 0)) # 白色 for i in range(0, 50):for j in range(0, 100):for k in range(0, 3):img.itemset((i, j, k), 255) cv2.imshow('after', img) print('修改后端img.item(0, 0, 0) = ', img.item(0, 0, 0)) cv2.waitKey() cv2.destroyAllWindows() -
在這里插入圖片描述
訪問img.item(0, 0, 0) = 125
修改后端img.item(0, 0, 0) = 255
三、感興趣區域(ROI):
在圖像處理過程中,我們可能會對圖像的摸一個特定區域感興趣,該區域被稱為感興趣區域(ROI)。在設定感興趣區域ROI后,就可以對該區域進行整體操作。例如,將一個感興趣區域A賦值給變量B后,可以將該變量B賦值給另外一個區域C,從而達到在區域C內復制區域A的目的。
示例1: 假設當前圖像名稱為img,圖中的數字分別表示行號和列號。那么,圖像中的黑色ROI可以表示為img[200:400, 200:400],
通過一下語句,能夠將圖中黑色ROI復制到該區域右側:
a = img[200:400, 200:400]
img[200:400, 600:800] = a
示例2: 獲取圖像lena的臉部信息,并將其顯示出來。
import cv2 a = cv2.imread('lena512color.tiff', cv2.IMREAD_UNCHANGED) face = a[220: 400, 250: 350] cv2.imshow('original', a) cv2.imshow('face', face) cv2.waitKey() cv2.destroyAllWindows()示例3: 對lena圖像臉部進行打碼
import cv2 import numpy as np a = cv2.imread('../lena512color.tiff', cv2.IMREAD_UNCHANGED) cv2.imshow('original', a) face = np.random.randint(0, 256, (180, 100, 3)) a[220: 400, 250: 350] = face cv2.imshow('result', a) cv2.waitKey() cv2.destroyAllWindows()四、通道操作:
在RGB圖像中,圖像由R通道、G通道、B通道三個通道構成的。需要注意的是,在OpenCV中,通道是按照B通道-G通道-R通道的順序存儲的。在圖像處理過程中,可以根據需要對圖像進行通道拆分和通道合并。
1. 通道拆分:
針對RGB圖像,可以分別拆分出其R通道、G通道、B通道。在OpenCV中,即可以通過索引的方式拆分通道,也可以通過函數的方式拆分通道。
-
通過索引拆分通道:
通過索引的方式,可以直接將各個通道從圖像內提取出來。如:針對OpneCV中的BGR圖像img
- b = img[ : , : , 0]
- g = img[ : , : , 1]
- r = img[ : , : , 2]
示例: 編寫程序,演示圖像通道才分及通道值變換對彩色圖像的影響。
import cv2 lena = cv2.imread('lena512color.tiff') cv2.imshow('lena1', lena) b = lena[:, :, 0] g = lena[:, :, 1] r = lena[:, :, 2] cv2.imshow('b', b) cv2.imshow('g', g) cv2.imshow('r', r) lena[:, :, 0] = 0 cv2.imshow('lenab0', lena) lena[:, :, 1] = 0 cv2.imshow('lenabogo', lena) cv2.waitKey() cv2.destroyAllWindows()
-
通過函數拆分通道:
函數cv2.split()能夠拆分圖像的通道。如,可以使用以下語句拆分彩色BGR圖像img,得到圖像的B,G,R通道。
-
b, g, r = cv2.split(img)
b = cv2.split(img)[0]
g = cv2.split(img)[1]
r = cv2.split(img)[2]
示例: 使用函數cv2.split()拆分圖像通道
import cv2 lena = cv2.imread('../lena512color.tiff') b, g, r = cv2.split(lena) cv2.imshow('B', b) cv2.imshow('G', g) cv2.imshow('R', r) cv2.waitKey() cv2.destroyAllWindows() -
2. 通道合并:
通道合并是通道拆分的逆過程,通過合并通道可以將三個通道的灰度圖像構成一幅彩色圖像。函數cv2.merge()可以實現圖像通道的合并,如有B, G, R三個通道圖像,使用函數cv2.merge()將其合并為一幅BGR三通道的彩色圖像。其實現語句為:bgr_img = cv2.merge([b, g, r])
示例: 使用函數cv2.merge()合并通道。
import cv2 lena = cv2.imread('../lena512color.tiff') b, g, r = cv2.split(lena) bgr = cv2.merge([b, g, r]) rgb = cv2.merge([r, g, b]) cv2.imshow('lena', lena) cv2.imshow('bar', bgr) cv2.imshow('rgb', rgb) cv2.waitKey() cv2.destroyAllWindows()五、獲取圖像屬性:
在圖像處理過程中,經常需要獲取圖像的屬性,如圖像的大小、類型等。這里介紹幾個常用的屬性
- shape:如果是彩色圖像,則返回包含行數、列數、通道數的數組;如果是二值圖像或者灰度圖像,則僅返回行數和列數。通過該屬性的返回值是否包含通道數,可以判斷圖像是灰度圖像還是彩色圖像。
- size:返回圖像的像素數目。其值為"行數×列數×通道數",灰度圖像揮著二值圖像通道數為1
- dtype:返回圖像的數據類型
示例:
import cv2 gray = cv2.imread('../lena.bmp', 0) color = cv2.imread('../lena512color.tiff') print('圖像gray屬性') print('gray.shape=', gray.shape) print('gray.size=', gray.size) print('gray.dtype=', gray.dtype) print('圖像color屬性') print('color.shape=', color.shape) print('color.size=', color.size) print('color.dtype=', color.dtype)-
終端輸出:
圖像gray屬性
gray.shape= (512, 512)
gray.size= 262144
gray.dtype= uint8
圖像color屬性
color.shape= (512, 512, 3)
color.size= 786432
color.dtype= uint8
該文章內容參考總結自《OpenCV輕松入門》這本書,詳細內容可以參考這本書。
總結
以上是生活随笔為你收集整理的第二章:图像处理基础的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux的SWAP分区空间不够用的情况
- 下一篇: 有一个测试微信删除软件叫wool,微信自