淺談圖像基礎-格式/顏色模型/灰度與二值化處理

前言

前一陣對圖片處理感興趣,因而就學習起來,卻發現是個大坑:html

看看這幾本書,笑容逐漸變形。書裏用的是 matlab,大學用完以後都沒用過了。想在平時工做的 iOS 裏用上,還須要學一下 OpenCV,而 OpenCV 還須要... 算了,我不想了。ios

等坑填好估計我已經老了吧 : )git

目前先總結些圖像處理的基礎知識,記錄下來,分享須要的小夥伴們...固然大佬們就不用看了。github

圖像基礎知識

圖像格式

平常咱們看到圖片文件的後綴,就表明圖片格式,常見的存儲的格式有: jpeg,bmp,png,gif等等。圖片格式是計算機存儲圖片的格式。web

圖片分類

圖片能夠分爲位圖矢量圖兩類。objective-c

  • 位圖:也叫像素圖,是使用像素點陣列拼合的圖像。捕捉獲得的圖像如(拍攝、截圖)都是像素圖。像素圖放大到必定程度會出現模糊。常見的像素圖格式包括:JPEG、PSD、PNG、TIFF。算法

  • 矢量圖:是使用點線面構成的圖像。矢量圖每每是使用矢量軟件繪製獲得的。點線面都是數學化的,所以放大不會模糊。常見的矢量圖格式包括:AI、EPS、SVG。markdown

常見的幾種位圖格式

各類格式能夠參見維基百科中的 圖形文件格式比較 瞭解,對於 iOS 開發或者客戶端來講,重點關注的位圖格式,通常都是 .jpg / .png / .gif / .WebP 這 4 種,下面從 《移動端圖片格式調研》 (很是推薦你們去閱讀這篇文章)中摘錄說明一下優缺點:網絡

文件擴展名 誕生歷史 優勢 缺點
GIF 誕生於 1987 年,隨着初代互聯網流行開來 惟一的優點就是支持多幀動畫,憑藉這個特性,它得以從 Windows 1.0 時代流行至今,並且仍然大受歡迎。 它有不少缺點,好比一般狀況下只支持 256 種顏色、透明通道只有 1 bit、文件壓縮比不高。
JPEG 誕生於 1992 年,是一個很古老的格式 其壓縮算法能夠精確控制壓縮比,以圖像質量換得存儲空間。因爲它太過常見,以致於許多移動設備的 CPU 都支持針對它的硬編碼與硬解碼。 只支持有損壓縮
PNG 誕生在 1995 年,比 JPEG 晚幾年。它自己的設計目的是替代 GIF 格式,因此它與 GIF 有更多類似的地方。 相對於 JPEG 和 GIF 來講,它最大的優點在於支持完整的透明通道 PNG 只支持無損壓縮,因此它的壓縮比是有上限的。
WebP 是 Google 在 2010 年發佈的圖片格式,但願以更高的壓縮比替代 JPEG 用 VP8 視頻幀內編碼做爲其算法基礎,取得了不錯的壓縮效果。它支持有損和無損壓縮、支持完整的透明通道、也支持多幀動畫,而且沒有版權問題,是一種很是理想的圖片格式。 對於複雜的圖像(好比照片)來講,WebP 無損編碼表現並很差

JPEG 和 PNG 對比

上面表格能夠看到,JPEG 誕生的比 PNG 早,應用比較廣,但 JPEG 是不支持 alpha 通道的。app

這會產生什麼問題呢?例如,iOS 壓縮圖片時,若是圖片有地方是透明的,使用 JPEG 的方式,透明部分會得不到體現。使用 PNG 則能夠完整支持。

我寫了一個 demo 來實際驗證這個問題,具體代碼和效果能夠到演示工程中查看。

首先用的一張原圖是上半部分爲白色,而後豎直向下,漸變到透明:

而後對 imageView 進行截圖處理,分別採用 PNG 和 JPEG 兩種方式來壓縮生成新圖片。

使用 PNG 格式壓縮後獲得的圖片:

使用 JPEG 格式壓縮後獲得的圖片:

經過對比,能夠發現:

  • JPEG 處理( JPEG 的壓縮比設置爲 0.9 )後,損失了原圖的透明部分,變成了白色。PNG 則能夠很好的支持透明通道。

  • JPEG 的圖片大小,這裏是 81 KB ,PNG 的則達到了 487 KB ,對同一張圖片,兩者大小的差距能夠達到 6 倍以上 .

因此 JPEG 和 PNG 的方式各有優劣,JPEG 在圖片大小上有巨大優點,可是圖片的呈現上 PNG 無疑更好,使用你們能夠根據場景去調整。

壓縮方式 - 有損壓縮/無損壓縮

上面說了 JPEG 和 PNG 的不一樣。那麼咱們再進一步探索,是什麼形成了 JPEG 和 PNG 在呈現上和大小上的不一樣呢?

那這裏就要提到壓縮方式

gif/png 使用的是無損壓縮,而 jpeg 是有損壓縮。WebP 則是兩種都有支持(WebP 露出勝利的笑容✌️)。

下面來講一下兩種壓縮方式:

  • 無損數據壓縮(Lossless Compression),是指資料通過壓縮後,信息不被破壞,還能徹底恢復到壓縮前的原樣。無損壓縮一般用在嚴格要求**「通過壓縮、解壓縮的資料必須與原始資料一致」**的場景。

    無損壓縮,舉個例子,原本一句話是:

    TimWang 說 TimZhang 是 TimWang 的兄弟。TimZhang 說 TimZhang 不是 TimWang 的兄弟。

    如今進行無損壓縮,先進行定義:

    Tim=a,Zhang=1,Wang=2,兄弟=b

    而後這句話變成:

    a2 說 a1 是 a2 的 b。a1 說 a1 不是 a2 的 b.

    那麼很容易看到,數據的長度明顯減小了(壓縮),根據事先定義,能把信息給徹底還原(無損),因此叫無損壓縮。

  • 有損數據壓縮(Lossy Compression),通過此方法壓縮、解壓的數據會與原始數據不一樣可是很是接近。藉由將次要的數據捨棄,犧牲一些質量來減小數據量、提升壓縮比。

    有損壓縮,一樣以一句話爲例子:

    TimWang 說 TimZhang 是 TimWang 的兄弟。TimZhang 說 TimZhang 不是 TimWang 的兄弟。

    進行有損壓縮,對咱們的數據進行處理,仍然不影響它的表達:

    TimWang 說是 TimZhang 兄弟。TimZhang 說不是 TimWang 兄弟。

    能夠看到,數據長度也被減小了(壓縮),經過丟掉「不重要」信息(有損),留下「關鍵信息」,來達到咱們的壓縮目的,只是沒法還原了,因此叫有損壓縮。

通過上面說明,已經對無損/有損的壓縮方式有大概的理解。這裏再也不贅述,傳統武術講究點到爲止,關於兩種壓縮方式想了解更多的同窗自行去入坑吧

位圖的顏色模型

上面有介紹到,位圖(Bitmap)是經過像素點陣列來表示的圖像。

位圖的像素都分配有特定的位置和顏色值,每一個像素的顏色信息由 RGB 組合或者灰度值表示。

從位圖圖片中,選擇最有表明性的若干種顏色(一般不超過256種)編製成顏色表,而後將圖片中原有顏色,用顏色表的索引來表示。

而這提到的 RGB 組合顏色表,就須要瞭解 顏色模型

什麼是顏色模型

顏色模型 是計算機中表示各類顏色的模型,是色彩的一種描述方式。

一個顏色一般由多個變量來標示,至關於 空間座標

而其實一個顏色是客觀的,固定的,只是不一樣的顏色模型是從不一樣的角度取描述它,就像 11 = 10 + 1,也能夠是 11 = 2 + 9。

顏色模型決定一個顏色根據什麼樣的「規則」來進行表達。

色彩模型有不少,下面 6 種是經常使用的模型:

  • RGB
  • YUV
  • HSV
  • HSL
  • CMY/CMYK
  • LAB

又可分爲兩類:

  • 面向硬件設備的,如彩色顯示器,打印機等,RGB(彩色攝像機/彩色攝像機),CMYK/CMY(彩色打印機),YUV(電視系統)
  • 面向彩色處理等,如爲動畫建立的彩圖,HSL/HSV/LAB。

文章的篇幅有限,下面只對 RGB 和 HSV 2 種色彩模型進行簡略說明。

RGB

RGB 又叫 三原色光模式RGB color model),是一種加色模型 :

將紅 (Red)/綠(Green)/藍(Blue)三原色的色光以不一樣的比例相加,以合成產生各類色彩效果。

至於三原色爲何是紅/綠/藍,而不是其它的顏色組成,維基百科中對於 選擇紅綠藍的生理緣由 的解釋是:

三原色的原理不是出於物理緣由,而是因爲生理緣由形成的。

人的眼睛內有幾種辨別顏色的錐形感光細胞,分別對黃綠色/綠色/藍紫色的光最敏感:若是辨別黃綠色的細胞受到的刺激略大於辨別綠色的細胞,人的感受是黃色;若是辨別黃綠色的細胞受到的刺激大大高於辨別綠色的細胞,人的感受是紅色

雖然三種細胞並非分別對紅色/綠色/藍色最敏感,但這三種光能夠分別對三種錐形細胞產生刺激。

因此,咱們能夠認爲 :

紅光+綠光 產生的視覺效果等於黃光,而不是等於變成了黃光自己

就像鹽水和純淨水,都是透明的液體,視覺效果上是同樣的,實際上並不是同一事物。

RGB 顏色空間是一種均勻性較差的顏色空間,RGB 顏色空間適合於顯示系統,卻並不適合於圖像處理。

iOS 上能直接使用增長了 Alpha 通道的 RGBA 模型表示顏色:

UIColor *color = [UIColor colorWithRed:39/255.0 green:45/255.0 blue:51/255.0 alpha:0];
複製代碼
HSV

HSV 顏色模型在圖像處理中有大量的應用,它由三個部分組成:

  • H: Hue,色調值
  • S: Saturation,飽和度值
  • V: Value,亮度值

Hue 用角度表達,取值範圍是 0-360°,表示色彩的信息。

Saturation 用百分比表達,取值範圍 0~1。飽和度減少,就是往光譜色中添加白色,光譜色所佔的比例也在減少。飽和度爲0,表示光譜色所佔的比例爲0,致使整個顏色呈現白色

Value 用百分比表達,取值範圍 0~1。明度減少,就是往光譜色中添加黑色,光譜色所佔的比例也在減少,明度爲0,表示光譜色所佔的比例爲0,致使整個顏色呈現黑色

HSV 與人的視覺特性比較接近,具備較強的感知度。HSV 目前普遍應用於計算機圖形學,科學計算可視化等領域。與 RGB 不一樣的是,它是一個均勻顏色空間。HSV 由於更近於人對顏色的主觀感覺,很適合基於顏色的圖像類似度比較。

iOS 中也能夠直接使用 HSV 表示顏色:

UIColor *hsvColor = [UIColor colorWithHue:0.10 saturation:0.79 brightness:0.53 alpha:1.00];
複製代碼

note:

各類色彩模型都是同一物理量的不一樣表達,所以有能夠互相轉化的關係。

例如 RGB/HSV ,都是能夠經過公式,互相轉化成對應座標的。如 OpenCV 等也有提供封裝好的函數去轉換。

顏色模型和顏色空間的關係

前面說到顏色模型,你們也看到,模型都是創建在三維空間的,因此它和顏色空間也是密不可分的。

那顏色模型和顏色空間的關係究竟是什麼呢?

若是開發經歷稍微豐富的同窗,平常確定會發現一件事:

當咱們使用某個顏色模型,一樣的值 xxxx 表達一個顏色,卻可能在不一樣的設備(例如模擬器/真機)上存在顯示差別

而形成差別的緣由,就在於使用的顏色空間不一樣。在不一樣的顏色空間上,對於顏色的呈現是不同的。

一個色彩模型下能夠有不一樣的色彩空間,根據排列條件不一樣,有不一樣色域(所能表示色彩的範圍)和含義。

色彩模型具體到一種色彩空間上纔有實用性,之前面提到的 RGB 模型爲例,就存在sRGB/AdobeRGB/AppleRGB 等顏色空間,它們大多也與圖像外設是相關的。

AdobeRGB 與 sRGB 最爲常見,下面演示一下兩種色彩空間(演示資料來自網絡):

⬆️ sRGB

⬆️ AdobeRGB

從面積來看,AdobeRGB 是要比 sRGB 更大的,也就是說能表示的色彩範圍更大。

日常設計稿當中的 RGB 顏色空間,大多使用的是sRGB,有時不免會形成顏色差別的小問題。

下次再碰到設備顯示顏色不一致問題,就能夠和設計師對一對所用的色彩空間。

位圖存儲

通過以前的一些瞭解,如今看看位圖的存儲。

圖片使用 RGB 顏色模型,則每一個像素都使用 RGB 表達,來組成像素矩陣:

在實際開發中, RGBA 的存儲也不少,增長了 Aplha 通道,例如 PNG 格式圖片。

通常來講,若是一個通道存儲須要 8 位,那一個像素佔的位數:RGB 是 3x8=24 位,RGBA 是 4x8=32 位。

雖然上面我們看到的是一個矩陣,其實到了內存中,只能一維的存儲:

按行排列,將像素從上往下或從下往上的放入。

值得注意的是,RGB 或者 RGBA 的存儲順序可能也是不一樣的,如圖:

通常來講有 RGB、BGR、RGBA、BGRA 的排列,大部分是 BGR\BGRA 排列。

位圖深度

上面說到了位圖的存儲,具體到 1 個像素所佔的位數,就是位圖深度。它又叫色彩深度,或者說色彩位數。

色彩位數表示在位圖中儲存每一像素所用的位數,經常使用單位爲位 /像素(bpp--bits per pixel)。

要用多少個二進制位來表示每一個點的顏色,是分辨率的一個重要指標:

色彩位數 越高,可用的顏色就越多 -- 色彩深度是 n 位, 那就有 2 n 2^n 種顏色來選擇。

位深度爲 1 的像素位圖,只有2( 2 1 2^1 )個可能的值(黑色和白色),因此又稱爲二值位圖

位深度爲 8 的圖像,有 256( 2 8 2^8 ) 個可能的值(或256種灰度等級)。

而若是色彩位數達到了24位,則可稱之爲真彩色,它能組合成2的24次冪種顏色,即:16777216種顏色 ( 或稱千萬種顏色 ),超過了人眼可以分辨的顏色數量。

色彩位數經常使用有1位(單色),2位(4色,CGA),4位(16色,VGA),8位(256色),16位(加強色),24位和32位等。

位圖大小計算

顏色就越多,顏色表現就越逼真,可是每 1 個像素佔用的位數也多了,相應的數據量越大。

因此色彩位數也決定了圖片的大小,計算公式爲:圖片大小(單位bit) = 長x寬x色彩位數

例如一個 100*100 的圖片,色彩位數爲 32,那大小就爲:100X100X32 = 320000 bits-> 40000 bytes。

另外關於 高動態範圍影像(High Dynamic Range Image),也就是 iPhone 手機上的 HDR 模式。

它最主要是分別使用三種圖片(欠曝、正常曝光、過曝),最後合成一張圖。不管是光位仍是暗位的細節都獲得體現。

HDR 使用超過通常的 32 位色階來儲存影像。一般來講每一個像素會分配到 32+32+32 個 bit 來儲存顏色信息,每一個原色都使用一個 32 bit 來儲存,也就是 說它能表現的顏色數量達到了 2 的 32 次冪。豐富的色彩,這也是支撐它表現細節的一個關鍵。

圖片灰度

上面在說顏色空間時有提到:

位圖像素分配有特定的位置和顏色值,每一個像素的顏色信息由 RGB 組合或灰度值表示。

什麼是灰度

灰度也能夠認爲是亮度,簡單說就是色彩的深淺程度

說到亮度,最亮的就是白色,最不亮的就是黑色,黑白之間存在灰色地帶,因此就叫作灰度

RGB 位圖的灰度

單通道圖像只能顯示灰度圖,RGB 三通道圖像也能顯示灰度圖。

只不過單通道灰度圖每一個像素值是8位,而三通道每一個像素值是24位。上面說過了,一樣寬高下,像素位數決定了存儲大小,因此單通道圖像比三通道圖像的存儲量要小。

下面進一步畫圖來表示 RGB 的灰度級,以R/G/B爲軸創建座標系,黑(0,0,0)爲原點,不一樣的座標表明不一樣的顏色。

其中,在(0,0,0)與(1,1,1)的對角線上的顏色是不一樣層次的灰度級

經過圖片裏的對角線,按三維座標來計算 RGB 灰度的話,便是 R=G=B.

灰度級

圖片的灰度級,是代表圖像中不一樣灰度的最大數量

灰度級越大,圖像的亮度範圍越大。

圖片可以展示的灰度數量越多,意味着能實現更強的色彩層次,色彩更豐富,例如 RGB 位圖爲 16級灰度,能顯示的顏色就是 16×16×16 = 4096 色。

一張圖片的灰度級,和位圖深度有關:

若是位圖深度是 n 位,位圖灰度級 = 2 n 2^n

目前來講,位圖大都是 256級(RGB 單個通道用 8 位存儲,2 的 8 次冪)灰度 。

灰度圖

灰度圖每一個像素只有一個採樣顏色,用從黑到白之間的灰度值來表示,例如灰度圖的每一個像素用8位,則像素點的灰度值是黑白間的256種灰度級中的一種 (0~255)。

而圖像的灰度化,就是讓像素點矩陣中的每個像素點都知足關係:

R=G=B,此時的這個值叫作灰度值

如 :RGB(100,100,100) 就表明灰度值爲 100, RGB(50,50,50) 表明灰度值爲 50。

灰度值越大表示越亮。灰度值最高的時候顯示是白色,反之,像素越暗,灰度值越低,灰度值爲 0 顯示是黑色。

經過灰度值的不一樣,令像素呈現不一樣程度的灰色,展示了不一樣的灰度層次,灰度圖也就展示出來了。

圖片灰度化處理

在許多場合下,灰度圖像是彩色圖像的一種簡化表示,反應彩色圖像的明亮度。

圖像灰度化處理可做爲圖像處理預處理步驟,爲圖像分割/圖像識別/圖像分析等上層操做作準備。

通常灰度化處理的方法有 4 種 :份量法/最大值法/平均值法/加權平均法

下面選取一張楊超越的圖片:

分別利用上述 4 種方式處理,來獲得不一樣灰度圖像,看一下效果。

加權平均法

將三個份量以不一樣的權值進行加權平均。

人眼對綠色的敏感最高,對藍色敏感最低,所以,按下式對RGB三份量進行加權平均能獲得較合理的灰度圖像:

Gray = Gx0.59+Rx0.3+Bx0.11

平均值法

彩色圖像中的三份量亮度求平均獲得一個灰度值。

Gray =(R+G+B)/3

最大值法

彩色圖像中的三份量亮度的最大值做爲灰度圖的灰度值。

Gray = Max(Max(R,G),B)

份量法

根據彩色圖像中的三份量的亮度,做爲三個灰度圖像的灰度值,造成三個新圖像。再選取一種須要的灰度圖像

Gray = R

Gray = G

Gray = B

生成上面的幾種圖片代碼,均以上傳到 GitHub ,爲裏面的 [UIImage grayForImage:forType:] 方法。

圖片二值化

在前面有提到說圖像灰度化是圖像分割的一個前置操做。作完灰度化後,經常要作的,就是進一步把圖片二值化

什麼是圖片二值化

二值化就是讓圖像的像素點矩陣中的每一個像素點的灰度值爲黑色和白色,讓整個圖像呈現只有黑和白的效果。

例如在灰度級爲 256 時,在二值化後的圖像中的灰度值,只有 0 或 255 。

圖片二值化的做用

二值圖像在數字圖像處理佔有很是重要的地位,圖像的二值化相對於彩色圖像來講,運算量小不少,圖像中數據量大爲減小。

而進行圖片二值化操做,通常都是想從圖像中提取出目標物體。

如何進行灰度圖像二值化處理

通常來講,要進行二值化處理,先進行灰度化,再根據灰度值判斷,進行黑白轉化。

那麼一個像素點在灰度化以後,它的灰度值怎麼轉化黑或者白?

好比灰度值爲188,那二值化後是黑仍是白?這就涉及到取一個閾值的問題。

這裏有 3 種比較基本的方法:

一、中間值法

例如取閾值爲127(0~255的中數),灰度值小於等於127的爲黑色,大於127的變爲白色。優點在於計算量小速度快,缺點是閾值在不一樣的圖片中均爲127。不一樣的圖片,顏色分佈差異很大,因此用127作閾值一刀切,效果確定是很差的。

二、全部像素點的灰度值的平均值

先求取一個像素點平均值:

像素點平均值 = (像素點1灰度值+...+像素點n灰度值)/ n 。

而後將 像素點平均值 做爲閾值。這樣作比 中間值法 好一些。

三、直方圖方法(也叫雙峯法)。

直方圖是圖像的重要特質。直方圖方法認爲圖像由前景和背景組成,在灰度直方圖上,前景和背景都造成高峯,在雙峯之間的最低谷處就是閾值所在

要說明的是,這 3 種方式並不是通用的萬能方法,算是比較粗糙的處理方式。

二值化處理有不少針對不一樣狀況的算法,感興趣的建議本身深刻了解。

灰度直方圖

這裏說明一下灰度直方圖,它的橫軸是灰度級,豎軸則是各灰度級的像素個數。

從灰度直方圖,咱們能夠很直觀的看到個灰度級像素的比較,灰度分佈狀況是圖像的一個重要特徵。

二值化處理演示

仍然取一個楊超越的圖片來作演示:

二值化的閾值爲了便於計算,直接按比例從 0~1 之中取一個。

先將彩色圖片像素灰度化(加權平均),而後大於閾值爲白色,小於閾值爲黑色。

閾值 = 0.4

閾值 = 0.5

閾值 = 0.6

相關代碼也已經上傳到 GitHub ,放在 [UIImage covertToBinaryzation:] 方法。

二值化處理,最關鍵的地方就在於 取閾值。用什麼樣的值,在哪裏的範圍用,決定了二值化的效果。

這裏只是很是簡單的演示。

圖片二值化的具體應用有不少,我目前想到在客戶端,就有二維碼掃描,提取圖片簽名/印章,轉化商家彩色圖標等等。

如有不正確理解的地方,歡迎你們指正 。

參考

移動端圖片格式調研

RGB、HSV和HSL顏色空間

色彩模型與色彩空間

圖像處理的一些基礎

iOS Storyboard 和 UIColor 建立出來的顏色顯示效果不一樣

圖像原理 jpg png tga bmp 存儲格式

ios 圖片灰度處理的三種方法

圖像處理:圖像灰度化

OpenCV--圖像二值化(Binary Image)

相關文章
相關標籤/搜索