目錄
- 影像坐標系
- 影像數字化
- 矩陣
- 矩陣與影像
- 通道概念
- 使用OpenCV讀取RGB通道圖片
影像坐標系
? ? 在前面的資料標注文章中講述如何進行標注,而標注后會保留4個坐標點,那么這些坐標點如何表示在圖片中的位置?要表示一個點或圖形的位置,就需要涉及到坐標系的概念,今天就來了解一下影像的坐標系,一般大家首先接觸到的坐標系應該是的笛卡爾坐標系,如下所示:

? ? 如下圖所示,是以影像左上角為原點建立的以像素為單位的直角坐標系u-v,其橫坐標u與縱坐標v分別是在其影像陣列中所在的列數和行數,

以上坐標在OpenCV中,u對應 x , v對應 y
? ? 由于(u,v)只代表像素的列數與行數,而像素在影像中的位置并沒有用物理單位表示出來,所以還要建立以物理單位(如毫米)表示的影像坐標系x-y,將相機光軸與影像平面的交點(一般位于影像平面的中心處,也稱為影像的主點(principal point)定義為該坐標系的原點O1,且x軸與u軸平行,y軸與v軸平行,假設(u0,v0)代表O1在u-v坐標系下的坐標,dx與dy分別表示每個像素在橫軸x和縱軸y上的物理尺寸,則影像中的每個像素在u-v坐標系中的坐標和在x-y坐標系中的坐標之間都存在如下的關系:

上述公式中我們假設物理坐標系統中的單位為mm,則dx的單位為mm/px,而x/dx的單位則是px.
? ? 為使用方便,一般常用齊次坐標與矩陣形式表示為:

? ? 以上知識可能比較難懂,那么可能真正對我們有用的知識如下所示:

那么坐標系、行列、寬高的對應的關系如下所示:
row=height=y
col=width=x
使用OpenCV獲取影像的大小
? ? 以上面的示例圖為例,原始圖片大小為:

? ? 示例代碼如下所示:
import cv2
import numpy as np
import os
def GetImgFile(path,imgExtName=(".png",".bmp",".jpg",".jpeg",".gif")):
imgFileList=[ imgFile for r,s,fs in os.walk(imgPath) for imgFile in fs
if os.path.isfile(os.path.join(r,imgFile)) and
os.path.splitext(os.path.join(r,imgFile))[-1].lower() in imgExtName ]
return imgFileList
def GetImgHeightAndWidth(path,imgList):
tempDict={}
for item in imgList:
imgFullPath=path+"\\"+item
img=cv2.imdecode(np.fromfile(imgFullPath,dtype=np.uint8),cv2.IMREAD_COLOR)
imgHeight,imgWidth,_=img.shape
tempDict[item]={"Height":imgHeight,"Width":imgWidth}
return tempDict
if __name__ == "__main__":
imgPath=r"F:\編程資料\編程工程\AI學習筆記\03影像知識\測驗圖片"
imgShape=GetImgHeightAndWidth(imgPath,GetImgFile(imgPath))
print(imgShape)
輸出結果如下所示:
{'TestImage.jpg': {'Height': 604, 'Width': 403}}
影像數字化
? ? 影像數字化簡單來講,就是如何將影像保存為計算機能夠識別和還原的物件,數字化后的影像其本質上就是一個多維矩陣,例如常見的RGB影像其實可以理解為3個二維矩陣的疊加,矩陣中每個值對應顏色通道上的值(0~255),灰度圖則是1個二維矩陣,如下所示:

如上圖所示,該圖片大小為604*403,因此有3個604*403的矩陣,
在CV領域,矩陣的概念用得非常多,下面簡單介紹一下相關的概念,不做深究,
矩陣
? ? 在數學概念中,矩陣(Matrix)是一個按照陣列形式排列的實數或復數的集合,如下圖所示:

這是一個(m+1)*(n+1)矩陣,行列索引從0開始
使用代碼創建矩陣
? ? 在Python中常用于numpy模塊創建和處理矩陣,示例代碼如下所示:
import numpy as np
mat=np.array(range(10,35)).reshape(5,5)
print(mat)
輸出的二維矩陣如下所示,從編程的角度來理解,就是一個二維的陣列,
[[10 11 12 13 14]
[15 16 17 18 19]
[20 21 22 23 24]
[25 26 27 28 29]
[30 31 32 33 34]]
矩陣與影像
? ? 從前面已經可以大致猜到矩陣與影像的關系了,既然影像可以用多個矩陣來表示,那也就是意味著,我們可以自己通過代碼來創建影像,示例如下所示:
import cv2
import numpy as np
mat=np.array([
[[255,0,0],[0,255,0],[0,0,255]],
[[123,145,239],[10,100,134],[0,235,252]],
[[23,45,12],[56,12,78],[128,150,12]]
],dtype=np.uint8)
cv2.namedWindow("Create Img",cv2.WINDOW_NORMAL)
cv2.imshow("Create Img",mat)
cv2.waitKey()
生成的圖片效果片如下所示:

在上面3*3矩陣中,mat[m][n]分別代表BGR的值,如下圖所示:

? ? 通過上面的示例,大家應該了解到圖片是如何用矩陣進行表示存盤的,平常大家看到的彩色圖片也都采用這種方式組成,圖片越大,則矩陣規模也越大,
通道概念
- 通道就是每個擁有的色彩維度
1、對于灰度影像,只有一個色彩維度,因此是單通道
2、對于RGB彩色影像,有RGB三個色彩維度,因此是3通道
3、對于RGBA彩色影像,有RGBA(A:alpha透明度)四個色彩維度,因此是4通道
- 大部分影像都可以用3維矩陣來表示
單純從代碼角度來講,1維矩陣就是普通陣列,3維矩陣就是3維陣列,多維矩陣就是多維陣列
使用OpenCV讀取RGB通道圖片
示例代碼如下所示:
import cv2
import numpy as np
import os
def GetImgFile(path,imgExtName=(".png",".bmp",".jpg",".jpeg",".gif")):
imgFileList=[ imgFile for r,s,fs in os.walk(imgPath) for imgFile in fs
if os.path.isfile(os.path.join(r,imgFile)) and
os.path.splitext(os.path.join(r,imgFile))[-1].lower() in imgExtName ]
return imgFileList
def GetBGRInfo(path,imgList):
for item in imgList:
imgFullPath=path+"\\"+item
img=cv2.imdecode(np.fromfile(imgFullPath,dtype=np.uint8),cv2.IMREAD_COLOR)
ShowImg(img,winName="Source IMG")
# 分享BGR的通道資訊
b,g,r=cv2.split(img)
# 創建與img相同大小的零矩陣
zerosArray=np.zeros(img.shape[:2],dtype="uint8")
# 顯示(B,0,0)影像
ShowImg(cv2.merge([b,zerosArray,zerosArray]),"Blue Channel")
# 顯示(0,G,0)影像
ShowImg(cv2.merge([zerosArray,g,zerosArray]),"Green Channel")
# 顯示(0,0,R)影像
ShowImg(cv2.merge([zerosArray,zerosArray,r]),"Red Channel")
# 顯示代碼合成的BGR影像
ShowImg(cv2.merge([b,g,r]),"Merge Img-BGR")
# 顯示代碼合成的RGB影像
ShowImg(cv2.merge([r, g, b]), "Merge Img-RGB")
def ShowImg(obj,winName="ImgShow"):
cv2.imshow(winName,obj)
if cv2.waitKey(0) == ord("q") or cv2.waitKey(0) == ord("Q"):
cv2.destroyAllWindows()
if __name__ == "__main__":
imgPath=r"F:\測驗圖片"
imgFileList=GetImgFile(imgPath)
GetBGRInfo(imgPath,imgFileList)
- 顯示BGR單獨通道資訊的效果圖如下所示:

- 顯示原始圖片、BGR合成圖片、RGB合成的圖片效果如下所示:

既然能分離出BGR的通道資訊,再按BGR的順序進行合并,就可以恢復原始的圖片,如果不是按這個順序進行合并的話,會出現什么的效果圖呢?可以從上面最后一張圖片尋找答案,
- 注意事項
在使用cv2.split(img)分離通道資訊直接使用如下代碼進行顯示:
b,g,r=cv2.split(img)
ShowImg(b,"Blue Channel")
ShowImg(g,"Green Channel")
ShowImg(r,"Red Channel")
如果按照以上方式進行顯示,只是會得到三張不同的灰度圖:

上面已經分離出BGR三個通道,為什么不是三張BGR的影像?原因如下所示:
當呼叫imshow(b)時,是把影像的BGR三個通道值都變為b的值,所以傳遞的三個通道值均為(b,b,b),在前一篇講過,如果三個通道的值一樣,則為灰度圖,當使用cv2.merge方法將某個通道與零矩陣進行合并,則形成(b,0,0)從而只顯示某一通道的色彩資訊,
本文同步在微信訂閱號上發布,如各位小伙伴們喜歡我的文章,也可以關注我的微信訂閱號:woaitest,或掃描下面的二維碼添加關注:

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/60187.html
標籤:其他
