《我的眼睛--圖靈識別》第三章:基礎:顏色識別

《我的眼睛–圖靈識別》第三章:基礎:顏色識別

在這裏插入圖片描述
七色彩虹

漂亮的彩虹是一種光學現象,使用三棱透鏡進行折射就能看到七色彩虹。它分別由紅、橙、黃、綠、青、藍、紫7種顏色組成。色彩按字面含義上理解可分爲色和彩,色是指人對進入眼睛的光並傳至大腦時所產生的感覺;彩則指多色的意思,是人對光變化的理解。

1、顏色描述

顏色是通過光射向物體產生了反射光,不同光的波長和強度對肉眼產生刺激,引起視覺神經和中樞神經反應,大腦接收到相應的信號後,通過日常文化認識作出語義上的定義。
自然界的色彩是十分複雜的,我們處在一個五彩斑斕的世界中,日常口語化中描述的顏色不足以準確表達出我們想要的顏色,例如紅色?要再亮一點?再深一點?這種模棱兩可的描述在編程中將會是一種災難問題,所以我們需要通過準確的術語來表示具體的一種顏色。
原色的一個概念性詞彙,指由不同的顏色(原色)組合形成更多顏色。在不同的場景中,原色的構成並不一樣。

光學三原色
在光學中,一般認爲紅色、綠色和藍色是一組原色,又稱爲光學三原色,是一種疊加型原色。這是由於人類擁有的三種視錐細胞對紅光、綠光和藍光最爲敏感。通過不同比例的紅綠藍顏色疊加,可以使人看到各種顏色。例如紅色與綠色混合產生黃色或橙色,綠色和藍色混合產生青色,藍色和紅色混合產生紫色或品紅色。當這三種顏色等比例疊加到一起時會變成灰色,如果將三種顏色飽和度均調至最大時則呈現白色。電視機、攝像機、計算機和手機顯示屏等都是運用了光學三原色原理。

在這裏插入圖片描述
(RGB)紅綠藍三原色

顏料三原色
在印刷、繪畫等情況下,一般認爲青色、洋紅色和黃色是一組原色,又稱爲美術三原色,是一種消減型原色。例如黃色和青色混合產生綠色,黃色和洋紅色混合產生紅色,洋紅色和青色混合產生藍色。當這三種等比例混合時呈現灰色,如果將飽和度調至最大,理論上會呈現黑色,但是實際上由於顏料的原因會呈現出濁褐色。因此,在印刷技術上加入了第四種原色——黑色,以彌補顏料三原色的不足。

在這裏插入圖片描述
(CMYK)紅黃藍三原色

其他原色
除了以上兩種常見的三原色外,還有一些其他的原色組,例如心理原色中採用藍色、黃色、紅色、綠色、橙色和紫色這六種心理原色加上黑白兩色,形成了色彩感知。再例如天然彩色相片技術中採用橙色、綠色、紫色爲三原色等。

2、色彩空間

隨着技術的發展,各種各樣的色彩空間被創造出來,有RGB、HSV(HSB)、HSL、CMYK等等。本書中只用到RGB和HSV色彩空間格式的顏色值。

RGB
光學三原色系統一般稱爲”RGB色彩空間“,也就是由紅(Red:0255)、綠(Green:0255)、藍(Blue:0~255)所組合呈現的色彩系統。它的幾何空間模型是一個正方體,由3個向量構成,空間中每一個點都表示一個顏色。在這個空間中,可以通過以下幾種不同的數值來準確描述一個點的顏色。

在這裏插入圖片描述
RGB色彩空間模型

RGB色彩總共能組合出約1678萬種色彩,即三個分量最大值進行相乘256×256×256=16777216。通常被簡稱爲1600萬色或千萬色,也稱爲24位色(2的24次方)。
雖然RGB色彩空間適合用在各種顯示屏上,但是它的色彩描述並不適合人類理解,因爲我們的眼睛無法識別出一個顏色中紅藍綠三者的比重大小。例如RGB色彩描述爲“BB5280”表示什麼顏色?一般只有通過查詢才能知道這個顏色長啥樣。

顏色互補色
色彩中的互補色有紅色與青色互補、藍色與黃色互補、綠色與品紅色互補等等。在光學三原色中指兩種顏色以適當的比例混合而能產生白色時,則這兩種顏色就稱爲“互爲補色”,比如:RGB(255,0,0)和RGB(0,255,255),就是說它們的每個分量值分別加起來後能夠等於255。

在這裏插入圖片描述
互補色

HSV(HSB)
由於RGB色彩空間描述不適合人類理解,我們看顏色一般是通過對顏色的色相、飽和度、明度來識別的,故在此基礎上引申出了另一種新的模型結構——HSV色彩空間,這種模型是採取圓柱座標系的方法進行構建。HSV即色相(Hue)、飽和度(Saturation)、明度(Value),又稱爲HSB,其中B的英文是Brightness。

在這裏插入圖片描述
HSV色彩空間模型

色相(H)是色彩的顏色描述,例如平時說的紅色、藍色等,取值0~360。
飽和度(S)是指色彩的純度,飽和度越高,顏色越鮮豔,飽和度變低時,顏色逐漸變暗淡,取值範圍是0~100%。
明度(V)是指顏色的亮度,越高越亮,越低越暗,取值範圍是0~100%。

顏色轉換
什麼時候需要進行顏色轉換?
一般情況下,通過RGB色彩空間來查找顏色是夠用的,但是當遇到一些顏色隨時間或天氣變化而產生一些不同,例如烏雲變濃變淡、白天變亮、夜晚變暗等,RGB色彩空間就顯得很侷限了,這時候就需要引入HSV色彩空間來解決這個問題。
HSV色彩空間可以通過肉眼直觀的描述來定義某一個顏色。比如一塊紅色的紙張,正常情況下看到的是標準的紅色;當白天被陽光照射後,看到的是粉紅色;到了夜晚光線變暗,看到的是棗紅色。

在這裏插入圖片描述
變化的紅色

VB6代碼:

調用例子:

Dim iHSV As HSV, iRGB As RGB
iHSV =RGB轉HSV(255, 0, 0)
MsgBox iHSV.Hue& "," &iHSV.Saturation & "," &iHSV.Value
 
iRGB =HSV轉RGB(0, 100, 100)
MsgBox iRGB.Red& "," &iRGB.Green& "," & iRGB.Blue

封裝函數:

Public Type HSV
    Hue As Integer
    Saturation As Integer
    Value As Integer
End Type
Public Type RGB
    Red As Integer
    Green As Integer
    Blue As Integer
End Type
 
Private Function Max(c1 As Single, c2 As Single) As Single
    If c1 > c2 Then
        Max = c1
    Else
        Max = c2
    End If
End Function
Private Function Min(c1 As Single, c2 As Single) As Single
    If c1 > c2 Then
        Min = c2
    Else
        Min = c1
    End If
End Function
 
 
'轉換RGB到HSV
Public Function RGB轉HSV(ByVal R As Integer, ByVal G As Integer, ByVal b As Integer) As HSV
Dim nH As Single, nS As Single, nV As Single
Dim nR As Single, nG As Single, nB As Single
Dim ndelR As Single, ndelG As Single, ndelB As Single
Dim nmax As Single, nmin As Single, ndelMax As Single
    nR = R / 255
    nG = G / 255
    nB = b / 255
    nmax = Max(Max(nR, nG), nB)
    nmin = Min(Min(nR, nG), nB)
    ndelMax = nmax - nmin
    nV = nmax
    If (ndelMax = 0) Then
        nH = 0
        nS = 0
    Else
        nS = ndelMax / nmax
        ndelR = (((nmax - nR) / 6) + (ndelMax / 2)) / ndelMax
        ndelG = (((nmax - nG) / 6) + (ndelMax / 2)) / ndelMax
        ndelB = (((nmax - nB) / 6) + (ndelMax / 2)) / ndelMax
        If (nR = nmax) Then
            nH = ndelB - ndelG
        ElseIf (nG = nmax) Then
            nH = (1 / 3) + ndelR - ndelB
        ElseIf (nB = nmax) Then
            nH = (2 / 3) + ndelG - ndelR
        End If
        If (nH < 0) Then nH = nH + 1
        If (nH > 1) Then nH = nH - 1
    End If
    RGB轉HSV.Hue = nH * 360
    RGB轉HSV.Saturation = nS * 100
    RGB轉HSV.Value = nV * 100
End Function


按鍵精靈2014腳本:

調用例子:

//色相(H)、飽和度(S)、明度(V)
//下面這句是把16進制顏色("0000FF")轉換分解到10進制(H, S, V)分量中
Call Plugin.TULING.RGBtoHSV("0000FF",H,S,V)
MessageBox H & "," & S & "," &V
 
hColor=Plugin.TULING.HSVtoRGB(0,100,100)
MessageBox hColor

3、獲取顏色

屏幕座標系
在生活中,我們要去某一個地方,需要知道詳細的地址,例如人民路168號1棟608房間。而在我們屏幕中,如果要知道某一個點的具體位置時,就可以利用座標這個概念來描述。
屏幕座標就是表示一個點在固定分辨率屏幕上的位置數值。當一個屏幕的分辨率是1920*1080大小時,屏幕座標最左上角的點座標就是(0,0),屏幕最右下角的座標就是(1919,1079),因爲0到1919一共有1920個數字,正好對應1920個點,垂直方向也一樣。屏幕上任意一個點都有唯一的座標,所以我們就通過座標來表達某個點所在的位置。
屏幕座標系是以屏幕最左上角爲起點的座標系,從左往右爲X軸方向(範圍在01919),從上往下爲Y軸方向(範圍在01079),凡超出這個範圍值的爲越界,用戶在屏幕上就無法看到。這就跟我們數學中的十字座標系非常相似,兩者唯一區別是y軸的方向是相反的。

在這裏插入圖片描述
屏幕座標系

獲取指定座標點顏色
屏幕上顯示着各種各樣的顏色,這對我們寫條件時經常要用到的顏色判斷,要想知道屏幕上的某個位置顏色是否發生變化,就需要對指定位置的顏色進行獲取,之後才能對獲取的顏色值進行相應的判斷操作。
直接通過“魚魚抓點抓色“工具(或者其他第三方工具)進行獲取當前鼠標下座標點的顏色或者輸入指定屏幕座標來獲取顏色。當然也可以調用微軟API的GetPixel函數對指定屏幕座標進行顏色的獲取。

在這裏插入圖片描述
鼠標位置顏色

在這裏插入圖片描述
指定座標顏色

你們有沒有這樣的懷疑過,取色判斷跟圖像識別應該沒有任何關係的吧?
其實,在日常生活中大家都是有體驗過的,對吧?沒有嗎?

在這裏插入圖片描述
紅綠燈

日常生活中最容易見到的就是“紅綠燈”啦,開車的看到紅燈就會停車,對吧?
你看到的這些根據人眼判斷的就是一種識別,只是你沒有意識到而已,對不對?這個就是根據一種顏色來判斷,一種最簡單的識別方法。
那麼我們可以說,顏色判斷就是一種最最基礎的圖像識別方法。
但是,有的時候,我們無法單純的只靠一種顏色來識別,因爲這樣會很容易出現識別錯誤,比如:看到紅色的廣告牌就認爲是紅燈嗎?此時就需要大範圍內的多種顏色一起進行判斷,就是我們經常說的多點找色(多點找色也是找圖的一種形態,詳情查閱:04基礎:圖片識別)。

VB6代碼:

調用例子:

Dim 顏色 As String
顏色 = 來源_獲取屏幕位置顏色(100, 200)
MsgBox 顏色

封裝函數:

Public Function 來源_獲取屏幕位置顏色(x As Long, y As Long) As String
Dim WindowDC As Long, 顏色 As String
    On Error GoTo ErrLine
    WindowDC = GetDC(0)    '獲取全屏幕場景
    顏色 = GetPixel(WindowDC, x, y)    '取場景中(x, y)座標的顏色
    ReleaseDC 0, WindowDC    '釋放場景
    來源_獲取屏幕位置顏色 = Right("000000" & UCase(Hex(顏色)), 6)
    Exit Function
ErrLine:
    來源_獲取屏幕位置顏色 = ""
End Function

按鍵精靈2014腳本:

調用例子:

顏色 = Plugin.TULING.GetPixelColor(100, 200)
TracePrint 顏色

獲取屏幕像素
僅僅通過一個個指定座標點來獲取屏幕上的所有顏色,遍歷效率那是超級的慢,簡直是在浪費生命,我們希望的是能夠一次性的快速獲取屏幕上的所有顏色。使用微軟API提供的BitBlt和GetDIBits函數,就能夠很輕鬆的一次性獲取屏幕指定區域範圍內的所有像素點的顏色數據。

VB6代碼:

調用例子:

Dim 圖像數據() As Byte
Call 來源_獲取屏幕像素(0, 0, 200, 100, 圖像數據)

封裝函數:

Public Sub 來源_獲取屏幕像素(As Long,As Long,As Long,As Long, 返回圖像數據() As Byte)
Dim Temp圖像數據() As Byte, bi24BitInfo As BitMapInfo
DimAs Long,As Long=-+ 1    '圖像寬度=-+ 1    '圖像高度
    ReDim Temp圖像數據(3,- 1,- 1) As Byte
    With bi24BitInfo.bmiHeader
        .biBitCount = Bits
        .biCompression = 0&
        .biPlanes = 1
        .biSize = Len(bi24BitInfo.bmiHeader)
        .biWidth = 寬
        .biHeight = -'顯示正常圖像
    End With
    ……略…
    返回圖像數據 = Temp圖像數據
End Sub

按鍵精靈2014腳本:

調用例子:

Call Plugin.TULING.Pixel_FromScreen(0,0,200,100)
//顯示獲取的圖像
Call Plugin.TULING.Pixel_Preview()

4、顏色的查找識別

考慮到不同的電腦分辨率大小就會有所不同,需要找的目標(顏色)出現的位置可能會不一樣,我們並不知道它在屏幕上是在具體的哪個位置,如果要想找到它,可以通過對屏幕上的顏色數據進行一一遍歷和判斷,這樣就能知道所要找的目標顏色在屏幕上的位置是哪個座標值,進而找到它。
下面舉個例子,如何利用顏色找到電腦桌面上的“計算機”圖標?

在這裏插入圖片描述
(Win7)計算機

首先,打開魚魚抓色工具,勾選或按熱鍵【Alt+~】啓動取色功能,把鼠標移動到“我的電腦”圖標的淡綠色點上(其實選擇其它任意顏色點也是可以的)。

在這裏插入圖片描述
啓動取色功能

然後,按下熱鍵【Alt+~】停止取色。這樣,就完成了“計算機”圖標的顏色獲取。

在這裏插入圖片描述
抓取到顏色值

接下來,就能夠在屏幕區域(左邊:0, 上邊:0, 右邊:1919, 下邊:1079)範圍內使用16進制的顏色值“00FF6B”進行查找,最終返回找到的顏色在屏幕上的具體座標值。
需要特別注意的是,要查找的顏色必須在指定的區域範圍內。

在這裏插入圖片描述
在屏幕上的具體座標值

顏色查找方向

在指定區域範圍內查找顏色時,一般默認的情況下是從左上到右下的方式進行遍歷,如果你要找的顏色剛好在右下角時,還用這種方向進行遍歷就會浪費很多時間,這個時候你就可以對查找方向的參數進行設置,使其爲從右下到左上的方式進行遍歷。以下提供了8種遍歷方式。

在這裏插入圖片描述
顏色查找方向

在這裏插入圖片描述
問題:
如何進行多個顏色(紅、黃、藍)查找識別,並返回每個顏色的座標?

在這裏插入圖片描述
(作業)多個顏色查找

VB6代碼:

調用例子:

Dim FoundX As Long, FoundY As Long, 顏色 As String
顏色 = "0000FF"
Call 查找_屏幕區域找單色(0, 0, 1024, 768, 顏色, 0, 1, FoundX, FoundY)
Debug.Print FoundX, FoundY    '輸出找到的座標

封裝函數:

'Call 查找_屏幕區域找單色(
'       區域左邊:長整數,
'       區域上邊:長整數,
'       區域右邊:長整數,
'       區域下邊:長整數,
'       查找顏色:字符串,
'       查找方向:整數[0-從左上往右下;1-從左下往右上;2-從右上往左下;3-從右下往左上,4-從上左往下右;5-從上右往下左;6-從下左往上右;7-從下右往上左],
'       顏色相似度:單精度[0.5到1之間;1爲精確匹配],
'       輸出找到的x座標:整型變量,
'       輸出找到的y座標:整型變量
'               )
Public Sub 查找_屏幕區域找單色(As Long,As Long,As Long,As Long, 顏色值 As String, 查找方向 As Integer, 相似度 As Single, FoundX As Long, FoundY As Long)
Dim 結果x As Long, 結果y As Long
    結果x = -1
    結果y = -1
    'On Error GoTo 結束
    '1.截取屏幕圖片信息
    Dim 屏幕像素數據() As Byte
    Call 來源_獲取屏幕像素(,,,, 屏幕像素數據)
    '2.相似度計算
    Dim 顏色相似度 As Long, flag As Boolean
    顏色相似度 = (1 - 相似度) * 255
    '3.拆解顏色值分量
    Dim 顏色 As Long, Red As Byte, Green As Byte, Blue As Byte
    顏色 = CLng("&H" & 顏色值)
    Red = 顏色 Mod 256: Green = (顏色 \ 256) Mod 256: Blue = 顏色 \ 256 \ 256
    '4.顏色的查找識別
    Dim x As Long, y As Long,As Long,As Long=-- 1=-- 1
    flag = False
    Select Case 查找方向
    Case 0    '從左到右,從上到下.順序
        For y = 0 To: For x = 0 ToIf 顏色相似度 = 0 Then
                    If 屏幕像素數據(2, x, y) = Red And 屏幕像素數據(1, x, y) = Green And 屏幕像素數據(0, x, y) = Blue Then
                        flag = True: GoTo 結束
                    End If
                Else
                    If 顏色相似度判斷(屏幕像素數據(2, x, y), 屏幕像素數據(1, x, y), 屏幕像素數據(0, x, y), _
                            Red, Green, Blue, 顏色相似度) = True Then
                        flag = True: GoTo 結束
                    End If
                End If
            Next: Next
    Case 1    '從左到右,從下到上.順序
        For y =To 0 Step -1: For x = 0 ToIf 顏色相似度 = 0 Then
                    If 屏幕像素數據(2, x, y) = Red And 屏幕像素數據(1, x, y) = Green And 屏幕像素數據(0, x, y) = Blue Then
                        flag = True: GoTo 結束
                    End If
                Else
                    If 顏色相似度判斷(屏幕像素數據(2, x, y), 屏幕像素數據(1, x, y), 屏幕像素數據(0, x, y), _
                            Red, Green, Blue, 顏色相似度) = True Then
                        flag = True: GoTo 結束
                    End If
                End If
            Next: Next
    Case 2    '從右到左,從上到下.順序
        For y = 0 To: For x =To 0 Step -1
                If 顏色相似度 = 0 Then
                    If 屏幕像素數據(2, x, y) = Red And 屏幕像素數據(1, x, y) = Green And 屏幕像素數據(0, x, y) = Blue Then
                        flag = True: GoTo 結束
                    End If
                Else
                    If 顏色相似度判斷(屏幕像素數據(2, x, y), 屏幕像素數據(1, x, y), 屏幕像素數據(0, x, y), _
                            Red, Green, Blue, 顏色相似度) = True Then
                        flag = True: GoTo 結束
                    End If
                End If
            Next: Next
    Case 3    '從右到左,從下到上.順序
        For y =To 0 Step -1: For x =To 0 Step -1
                If 顏色相似度 = 0 Then
                    If 屏幕像素數據(2, x, y) = Red And 屏幕像素數據(1, x, y) = Green And 屏幕像素數據(0, x, y) = Blue Then
                        flag = True: GoTo 結束
                    End If
                Else
                    If 顏色相似度判斷(屏幕像素數據(2, x, y), 屏幕像素數據(1, x, y), 屏幕像素數據(0, x, y), _
                            Red, Green, Blue, 顏色相似度) = True Then
                        flag = True: GoTo 結束
                    End If
                End If
            Next: Next
    Case 4    '從上到下,從左到右.順序
        For x = 0 To: For y = 0 ToIf 顏色相似度 = 0 Then
                    If 屏幕像素數據(2, x, y) = Red And 屏幕像素數據(1, x, y) = Green And 屏幕像素數據(0, x, y) = Blue Then
                        flag = True: GoTo 結束
                    End If
                Else
                    If 顏色相似度判斷(屏幕像素數據(2, x, y), 屏幕像素數據(1, x, y), 屏幕像素數據(0, x, y), _
                            Red, Green, Blue, 顏色相似度) = True Then
                        flag = True: GoTo 結束
                    End If
                End If
            Next: Next
    Case 5    '從上到下,從右到左.順序
        For x =To 0 Step -1: For y = 0 ToIf 顏色相似度 = 0 Then
                    If 屏幕像素數據(2, x, y) = Red And 屏幕像素數據(1, x, y) = Green And 屏幕像素數據(0, x, y) = Blue Then
                        flag = True: GoTo 結束
                    End If
                Else
                    If 顏色相似度判斷(屏幕像素數據(2, x, y), 屏幕像素數據(1, x, y), 屏幕像素數據(0, x, y), _
                            Red, Green, Blue, 顏色相似度) = True Then
                        flag = True: GoTo 結束
                    End If
                End If
            Next: Next
    Case 6    '從下到上,從左到右.順序
        For x = 0 To: For y =To 0 Step -1
                If 顏色相似度 = 0 Then
                    If 屏幕像素數據(2, x, y) = Red And 屏幕像素數據(1, x, y) = Green And 屏幕像素數據(0, x, y) = Blue Then
                        flag = True: GoTo 結束
                    End If
                Else
                    If 顏色相似度判斷(屏幕像素數據(2, x, y), 屏幕像素數據(1, x, y), 屏幕像素數據(0, x, y), _
                            Red, Green, Blue, 顏色相似度) = True Then
                        flag = True: GoTo 結束
                    End If
                End If
            Next: Next
    Case 7    '從下到上,從右到左.順序
        For x =To 0 Step -1: For y =To 0 Step -1
                If 顏色相似度 = 0 Then
                    If 屏幕像素數據(2, x, y) = Red And 屏幕像素數據(1, x, y) = Green And 屏幕像素數據(0, x, y) = Blue Then
                        flag = True: GoTo 結束
                    End If
                Else
                    If 顏色相似度判斷(屏幕像素數據(2, x, y), 屏幕像素數據(1, x, y), 屏幕像素數據(0, x, y), _
                            Red, Green, Blue, 顏色相似度) = True Then
                        flag = True: GoTo 結束
                    End If
                End If
            Next: Next
    End Select
結束:
    If flag = True Then
        結果x = x + 左
        結果y = y +End If
    FoundX = 結果x
    FoundY = 結果y
End Sub
 

按鍵精靈2014腳本:

調用例子:

Dim x, y, 顏色
顏色 = "0000FF"
Call Plugin.TULING.FindColor(0, 0, 1024, 768, 顏色, 0, 1, x, y)
TracePrint x & "," & y    //輸出找到的座標

未完待續……

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章