在前面的數據標註文章中講述如何進行標註,而標註後會保留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.測試
爲使用方便,通常經常使用齊次座標與矩陣形式表示爲:ui
以上知識可能比較難懂,那麼可能真正對咱們有用的知識以下所示:3d
那麼座標系、行列、寬高的對應的關係以下所示:code
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的值,以下圖所示:
經過上面的示例,你們應該瞭解到圖片是如何用矩陣進行表示存儲的。日常你們看到的彩色圖片也都採用這種方式組成,圖片越大,則矩陣規模也越大。
一、對於灰度圖像,只有一個色彩維度,所以是單通道
二、對於RGB彩色圖像,有RGB三個色彩維度,所以是3通道
三、對於RGBA彩色圖像,有RGBA(A:alpha透明度)四個色彩維度,所以是4通道
單純從代碼角度來說,1維矩陣就是普通數組,3維矩陣就是3維數組,多維矩陣就是多維數組
示例代碼以下所示:
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的順序進行合併,就能夠恢復原始的圖片。若是不是按這個順序進行合併的話,會出現什麼的效果圖呢?能夠從上面最後一張圖片尋找答案。
在使用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,或掃描下面的二維碼添加關注: