图像的基础知识
作者:ZackSock
1、计算机中的图像
在计算机中,图像是以二进制形式存储的。但是我们通常不会以二进制方式操作图像,在处理图像时我们更乐意把图像看作是一个点集。这个集合是以二维的方式分布的,每个点都有自己的颜色,每个点都不可再分割。这样的点我们称它为【像素】。比如下面这张图片:
我们可以把它看作是一个5*5的图像,其中每个点都是黑色的。
早期的计算机只能显示简单的图像,比如【二值图像】。这种图像非黑即白,不容许第三种颜色存在。比如下面:
对于这种图片,我们每个像素只需要一位二进制(0,1)就可以表示。但是这种图像不能满足人的需求,于是又有了细节更加丰富,但依旧没有颜色的图像,也就是我们后面会接触到的【灰度图像】。比如下面:
上面的图像保留了真实场景中的大多数细节。如果再用一位二进制表示灰度图的像素就显得有些不足了,因此灰度图需要用8位二进制来表示,也就是0-255。因为现在硬盘不再是稀缺资源,所以二值图像我们通常也用8位二进制表示。用0表示0(黑色),用255表示1(白色)。
如果要表示彩色图像就更加复杂了,下面是一直图片的RGB图像:
所谓的RGB图像就是一张像素由三个值来表示的图片。三个值分别表示红、绿、蓝三种颜色的程度。比如如果一个像素的红色程度是255,其它两个颜色程度是0,那么这个像素在我们看来就是红色的。通过这三种颜色的搭配,我们可以配出4294967296种不同的颜色。
当然,我们生活种的图像还要丰富得多,比如透明图像、动态图像等。这里就不再详细说了。
2、OpenCV中的图像
在上面说到的对不同图像的理解在OpenCV中是一样适用的。
在OpenCV中,图像以ndarray类型存储。ndarray是numpy中的数组,它具有多个维度,它可以表示图像的完整信息。包括图片的宽高、像素的值等。我们可以尝试看看下面这张图片的ndarray数组:
因为比较长,我们截取一部分查看,下面是输出结果:
[[[245 225 190] [245 225 190] [245 225 190] ... [214 195 184] [214 195 184] [214 195 184]] [[245 225 190] [245 225 190] [245 225 190] 复制代码
现阶段我们还不需要太在意数组的内容,OpenCV提供了简单的API供我们获取图片的关键信息。下面我们来简单看一下。
3、获取图像信息
在获取图像信息之前,我们需要使用imread函数读取图片。我们看下面这段代码:
import cv2 im = cv2.imread('xscn.jpg') print("图像的形状:", im.shape) print("图像的大小:", im.size) print("图像的数据类型:", im.dtype) 复制代码
我们先看一下输出的结果,
图像的形状: (1080, 1920, 3) 图像的大小: 6220800 图像的数据类型: uint8 复制代码
再来解释一下各个参数:
- shape:图片的形状,包含高、宽、图层数的信息
- size:高*宽*图层数的值
- dtype:每个数据的类型。对于灰度图,一个数据就是一个像素。对于RGB图像,一个数据就是一个像素中一种颜色的值。unit8表示8位二进制的正整数(0-255)
其中图层数表示一个像素由几个数据组成。比如灰度图的图层数是1,而RGB图像的图层数是3。
4、图像坐标
为了方便,我们可以为图像构建一个坐标系,这个坐标系不需要实际构造,而只是为了方便我们理解。
我们来看下面这张图片:
我们构建了一个坐标系,然后把图片的左上角对应原点。这样我们可以用(x,y)形式定义一个像素点,比如图中的点A的坐标为(500,300)。
5、获取像素值
获取像素值同样需要先读取图像,然后我们可以通过下面的方式来访问指定位置的像素:
im[y][x] 复制代码
其中im是我们的图片对象。x、y对应坐标中的x、y。比如下面这段代码:
import cv2 im = cv2.imread('xscn.jpg') pixel = im[0][0] print(pixel) 复制代码
输出结果如下:
[245 225 190] 复制代码
因为读取的是RGB图像,所以单个像素由三个数据组成。我们还可以进一步获取某个颜色的值,比如我想获取坐标为(100,100)的像素中红色的值,我们可以这样获取:
red = im[100][100][0] 复制代码
但是其实这样是错误的。因为在OpenCV中,图像默认表示为GBR模式,而上面我们获取的应该是绿色的值。正确获取红色的操作应该如下:
red = im[100][100][2] 复制代码
6、修改像素值
像素值的修改非常简单,我们只需要找到某个像素,然后对其赋值即可。比如我们对下面这张图片进行操作:
上面为了方便观看,把一张3*3的图片放大后的效果。我们用代码对图片像素进行修改:
import numpy as np im = np.zeros((3, 3, 1), dtype=np.uint8) im[0][2] = 255 复制代码
其中np.zeros的作用是创建一个多维数组。我们直接把它理解为创建了上面的图像,后续我们会有更详细的讲解。
创建图像后我们把(2,0)处的像素修改为255,下面是修改后的图片:
可以看到指定像素被修改了。