图像坐标系

    在前面的数据标注文章中讲述如何进行标注,而标注后会保留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,或扫描下面的二维码添加关注:

AI-图像基础知识-02的更多相关文章

  1. MongoDB基础知识 02

    MongoDB基础知识 02 6 数据类型 6.1 null : 表示空值或者不存在的字段 {"x":null} 6.2 布尔型 : 布尔类型只有两个值true和false {&q ...

  2. day03-MySQL基础知识02

    MySQL基础知识02 4.CRUD 数据库CRUD语句:增(create).删(delete).改(update).查(Retrieve) Insert 语句 (添加数据) Update 语句(更新 ...

  3. AI工程师基础知识100题

    100道AI基础面试题 1.协方差和相关性有什么区别? 解析: 相关性是协方差的标准化格式.协方差本身很难做比较.例如:如果我们计算工资($)和年龄(岁)的协方差,因为这两个变量有不同的度量,所以我们 ...

  4. 极化SAR图像基础知识(1)

    从今天开始学习极化SAR图像,记录于此. 极化散射矩阵S是用来表示单个像素散射特性的一种简便办法,它包含了目标的全部极化信息.

  5. 图像基础知识之YUV

     一.YUV常用格式 YUV是编译true-color颜色空间(color space)的种类,Y'UV, YUV, YCbCr,YPbPr等专有名词都可以称为YUV,彼此有重叠.“Y”表示明亮度(L ...

  6. matlab图像基础知识

    1.MATLAB支持的几种图像文件格式: ⑴JPEG(Joint Photogyaphic Expeyts Group):一种称为联合图像专家组的图像压缩格式. ⑵BMP(Windows Bitmap ...

  7. .NET基础知识(02)-拆箱与装箱

    装箱和拆箱几乎是所有面试题中必考之一,看上去简单,就往往容易被忽视.其实它一点都不简单的,一个简单的问题也可以从多个层次来解读. 常见面试题目: 1.什么是拆箱和装箱? 2.什么是箱子? 3.箱子放在 ...

  8. 3-15 JS基础知识02

    一.For循环: For (var i = 0;  i <= 10;  i++){ 循环体: } 注意:For循环中的表达式是可以省略的,省略以后是个死循环. odd:奇数   even : 偶 ...

  9. 极化SAR图像基础知识(2)

    本篇主要关注物理含义 1.极化 电磁波在传播时,传播的方向和电场.磁场相互垂直,我们把电波的电场方向叫电波的极化.(i.e.依据电场E的方向来定义电磁波的极化). 如果电场矢量端点随时间变化的轨迹是一 ...

随机推荐

  1. Maven的Scope区别笔记

    依赖的Scopescope定义了类包在项目的使用阶段.项目阶段包括: 编译,运行,测试和发布. 分类说明compile 默认scope为compile,表示为当前依赖参与项目的编译.测试和运行阶段,属 ...

  2. Linux学习笔记-第6天 - 问题的根本

    这些知识其实看起来很简单,之前不管是在学习C语言还是bat批处理,类似结构早已熟知. 但其实运用起来并不算好,可能真正的原因还 是在于得多练习吧.希望明年的今天自己不要再纠结与这些基础性的知识.

  3. [RN] React Native 错误 Module does not exist in the module map

    React Native 错误 Module does not exist in the module map 代码如下: import Login from 'login' import Index ...

  4. mission3--dp

    A---母牛的故事 题目大意:第一年有一头母牛,每年年初母牛生小母牛,小母牛第四个年头可以开始生小牛. 问第n年有多少头牛. 题解: (1)列出前几项来找规律(2)第i年牛的数量=第i-1年牛的数量+ ...

  5. CF1178F Short/Long Colorful Strip(DP)

    说起来,这题好像也不难-- 先考虑 F1 怎么做. 既然别的方法都不行不如试试\(f_{i,j}\) 表示在刚刚准备开始涂 \([i,j]\) 中最小编号的颜色之前,整个区间是同色的,且最后能做到 \ ...

  6. [LeetCode] 24. Swap Nodes in Pairs 成对交换节点

    Given a linked list, swap every two adjacent nodes and return its head. You may not modify the value ...

  7. Harmonious Army

    Harmonious Army Now, Bob is playing an interesting game in which he is a general of a harmonious arm ...

  8. vue router 常用操作

    1.  普通路由 const routes = [ { path: '/index', component: index } ] 2. 重定向 redirect const routes = [ { ...

  9. c#多个按钮执行同一类事件-按钮按下和弹起

    首先在Winform中添加一个Button控件,在属性里面为控件添加鼠标按下和弹起事件(不要双击按钮,在属性里面添加) 再添加其他几个按钮控件,在控件的属性里面为鼠标按下和弹起添加已定义好处理函数(M ...

  10. from import语句

    *)假如导入出现了问题,那么一定是导入的文件里的语法问题或者其他问题 参考链接:http://www.cnblogs.com/hwf-73/p/5493328.html 1)导入时重命名 as fro ...