什么是像素
图像坐标系在OpenCV中的工作方式
如何访问/获取图像中的单个像素值
如何设置/更新图像中的像素
如何使用数组切片来捕获图像区域
在本教程结束时,您将对如何使用OpenCV访问和操纵图像中的像素有深入的了解
像素是图像的原始构建块。每个图像都由一组像素组成。没有比像素更好的粒度。
通常,像素被认为是出现在图像中给定位置的光的“颜色”或“强度”。
如果我们将图像视为网格,则网格中的每个正方形都包含一个像素。首先放一张高清我老婆图片,让我们看一下图片像素:
大多数像素以两种方式表示:
但是,彩色像素通常在RGB颜色空间中表示-红色分量的一个值,绿色分量的一个值,蓝色分量的一个值,导致每个像素总共3个值:
图3: RGB立方体。
还存在其他色彩空间(HSV(色相,饱和度,值),L * a * b *等),但让我们从基础知识开始,然后从那里开始。
红色,绿色和蓝色这三种颜色中的每一种都由一个介于0到255之间的整数表示,该整数表示颜色的“多少”。假设像素值仅需要在[0,255]范围内,我们通常使用8位无符号整数表示每种颜色强度。
然后,我们将这些值组合成以下形式的RGB元组 (红色,绿色,蓝色)。这个元组代表我们的颜色。
要构造白色,我们将完全填充每个红色,绿色和蓝色水桶,如下所示: (255 ,255 ,255 ) —因为白色是所有颜色的存在。
然后,要创建黑色,我们将完全清空每个存储桶: (0 ,0 ,0 ) -因为黑色是没有颜色。
要创建纯红色,我们将完全填充红色桶(并且仅填充红色桶): (255 ,0 ,0 )。
您开始看到图案了吗?
请看下面的图片,以使这个概念更加清楚:
图4:在这里,我们有四个颜色示例,分别代表红色,绿色和蓝色分量的每个颜色和“桶”数量。
在左上角的示例中,我们将颜色设置为白色-红色,绿色和蓝色桶中的每个桶均已完全填充以形成白色。
在右上角,我们有黑色-红色,绿色和蓝色的水桶现在完全空了。
同样,要在左下角形成红色,我们只需要完全填充“红色”桶,而将其他绿色和蓝色桶完全清空即可。
最后,如右下图所示,通过仅填充“蓝色”桶来形成蓝色。
供您参考,以下是一些常见的颜色,以RGB元组表示:
正如我在图1中提到的,图像表示为像素网格。想象我们的网格就像一张方格纸。使用这种方格纸,点(0,0)对应于左上角的图像(即,角原点)。随着我们不断下降,并到右,无论是X和Y ^ -值增加。
让我们看一下图5中的图像,使这一点更加清楚:
图5:在OpenCV中,像素通过其(x,y)坐标进行访问。原点(0,0)位于图像的左上方。OpenCV的图像被零索引,其中的x值去左到右(列号)和ÿ -值去顶部至底部(行数)。
在这里,我们在一张方格纸上有字母“ I”。我们看到我们有一个8 x 8的网格,总像素为64。
在点(0,0)对应于左上在我们的图像像素,而点(7,7)对应于右下角。
重要的是要注意,我们是从零开始计数,而不是从1开始计数。Python语言是零索引的,这意味着我们总是从零开始计数。请记住这一点,以后您将避免很多混乱。
最后,请记住,我们是从零开始计数,而不是从1开始计数,右边的第4列像素和向下的5行像素由点(3,4)索引。
在开始查看代码之前,让我们回顾一下我们的项目目录结构:
我们今天有一个Python脚本可供审查, opencv_getting_setting.py,这将使我们能够访问和操作图像中的图像像素 adrian.png。
让我们学习如何使用OpenCV获取和设置像素。
打开 opencv_getting_setting.py 文件放在您的项目目录结构中,让我们开始工作:
第2行和第3行导入了我们所需的Python包。我们只需要argparse 对于我们的命令行参数 cv2 用于我们的OpenCV绑定。
这 - 图像命令行参数指向我们要操作的映像,该映像位于磁盘上。默认情况下,- 图像 命令行参数设置为 adrian.png。
第13-15行加载了我们的输入图像 从磁盘上,抓住它的宽度和高度,然后将图像显示到我们的屏幕上:
图7:从磁盘加载我们的输入图像,并使用OpenCV显示它。
OpenCV中的图像由NumPy数组表示。要访问特定的图像像素,我们要做的就是将(x,y)坐标传递为图片[ y,x ]:
第19行访问位于像素(0,0) ,这是左上的图像的角落。作为回报,我们依次接收到蓝色,绿色和红色强度(BGR)。
最大的问题是:
为什么OpenCV用BGR通道顺序而不是标准RGB表示图像?
答案是,当最初开发OpenCV时,BGR订购是标准!直到后来才采用RGB顺序。BGR排序在OpenCV中是标准的,因此请习惯于看它。
第23行然后使用的数组索引访问位于x = 50,y = 20的像素图像[ 20 ,50 ]。
可是等等 。。。那不落后吗?应该不是吗图像[ 50 ,20 ]因为x = 50和y = 20?
没那么快!
让我们备份一个步骤,并考虑图像只是具有宽度(列数)和高度(行数)的矩阵。如果要访问该矩阵中的单个位置,则将其表示为X 值(列号)和 ÿ 值(行号)。
因此,要访问位于x = 50,y = 20的像素,请先传递y-值(行号),然后传递x-值(列号),结果是图片[ y,x ]。
注意:我发现使用语法访问单个像素的概念图片[ y,x ]吸引了很多学生。花点时间说服自己图片[ y,x ] 是基于x值是您的列号(即,宽度),而y值是您的行号(即,高度)这一事实的正确语法。
第27和28行更新位于x = 50,y = 20的像素,将其设置为红色,即(0 ,0 ,255 )在BGR订购中。第29行然后将更新的像素值打印到我们的终端,从而表明它已被更新。
接下来,让我们学习如何使用NumPy数组切片从图像中获取感兴趣的大块/区域:
在第33行,我们计算图像的中心(x,y)坐标。这是通过简单地将宽度和高度除以二,并确保整数转换(因为我们无法访问“小数像素”位置)来实现的。
然后,在第38行,我们使用简单的NumPy数组切片来提取[ 0 ,cX ) 和 [ 0 ,cY )图片的区域。事实上,这一区域对应于左上角图像的角落!为了捕获图像的大块,NumPy期望我们提供四个索引:
起始y:第一个值是起始y坐标。这是我们的数组切片将从y轴开始的位置。在上面的示例中,我们的分片从y = 0开始。
结束y:正如我们提供了起始y值一样,我们也必须提供结束y值。当y = cY时,我们的切片沿y轴停止。
起始x:我们必须提供的第三个值是切片的起始x坐标。为了获取图像的左上角区域,我们从x = 0开始。
End x:最后,我们需要提供x轴值以使切片停止。当x = cX时,我们停止。
一旦我们提取的左上的图像角,39行显示了裁剪结果。请注意我们的形象如何只是左上角我们的原始图像的角落:
让我们进一步扩展该示例,以便我们可以使用NumPy数组切片从图像中提取区域进行一些练习:
以类似的方式,以上述例子中,线44提取右上角的图像的角落里,线路45提取右下拐角,以及线46的左下角。
最后,图像的所有四个角都显示在第47-49行的屏幕上,如下所示:
图9:使用数组切片通过OpenCV提取图像的四个角。
了解NumPy数组切片是一项非常重要的技能,您将一次又一次地用作计算机视觉从业人员。如果您不熟悉NumPy数组切片,我建议您花几分钟时间去了解,以了解NumPy索引,数组和切片的基础知识。
我们要做的最后一个任务是使用数组切片更改像素区域的颜色:
在52号线,你可以看到,我们再次访问该左上角的图像角; 但是,这一次,我们将这个区域的值设置为(0 ,255 ,0 ) (绿色)。
然后,第55和56行显示了我们的工作结果:
图10:设置左上的图像角是“绿色”。
现在让我们学习如何使用OpenCV获取和设置单个像素值!
确保已使用本教程的“下载”部分来访问源代码和示例图像。
从那里,您可以执行以下命令:
一旦脚本开始运行,您应该会看到一些输出打印到控制台。
输出的第一行告诉我们,位于(0,0)的像素的值为R = 233,G = 240和B = 246。所有三个通道的桶都接近白色,表明像素非常亮。
输出的后两行显示我们已经成功地将(50,20)处的像素更改为红色而不是(几乎)白色。
链接: 源代码下载.