一、计算机眼中的图像
像素
像素是图像的基本单元,每个像素存储着图像的颜色、亮度和其他特征。一系列像素组合到一起就形成 了完整的图像,在计算机中,图像以像素的形式存在并采用二进制格式进行存储。根据图像的颜色不 同,每个像素可以用不同的二进制数表示。
日常生活中常见的图像是RGB三原色图。RGB图上的每个点都是由红(R)、绿(G)、蓝(B)三个颜 色按照一定比例混合而成的,几乎所有颜色都可以通过这三种颜色按照不同比例调配而成。在计算机 中,RGB三种颜色被称为RGB三通道,根据这三个通道存储的像素值,来对应不同的颜色。例如,在使 用“画图”软件进行自定义调色时,其数值单位就是像素。
二、RGB颜色
三、计算机中图像的存储
在计算机中,图像都是以数组的形式存在的。一个RGB图像放到内存中就是一个 三维数组,其中第一维表示图像的宽度,第二维表示图像的高度,第三维则是图 像中每一个像素点的RGB三个像素值,但是在OpenCV中像素值的存储顺序是 BGR而不是RGB。
计算机处理图像本质上就是对三维数组中的像素值进行操作。
四、opencv安装
官方网址
OpenCV - Open Computer Vision Library
五、图形绘画
主要功能是生成一个700x700的图像,其上绘制了网格线和交叉的红色方块,并分别提取了该图像的RGB通道。最后,使用Matplotlib库显示了整个图像和各个分离的通道。
5.1、导入模块
python">import cv2 # 导入OpenCV库,用于图像处理
import numpy as np # 导入NumPy库,用于数组和矩阵操作
from matplotlib import pyplot as plt # 导入Matplotlib库,用于绘图
5.2、创建图像
创建一个空白的 700x700 彩色图像
python"># 创建一个700x700的黑色图像,包含三个颜色通道(RGB)
image = np.zeros((700, 700, 3), dtype=np.uint8)
5.3、为图像添加色彩
python"># 使用双层循环在图像上绘制网格和交叉的红色方块
for i in range(0, 700, 100): # 外层循环,步长为100,从0到600 for j in range(0, 700, 100): # 内层循环,同样步长为100 # 绘制水平网格线 image[i, :, :] = (255, 255, 255) # 将第i行的所有像素设为白色 # 绘制垂直网格线 image[:, j, :] = (255, 255, 255) # 将第j列的所有像素设为白色 # 绘制交叉的红色方块 if i != 0 and j != 0 and i != 600 and j != 600 and (i == j or i + j == 600): image[i:i+100, j:j+100, :] = (0, 0, 255) # 将指定区域设为红色
另一种方式
python">for i in range(0, 700, 100):for j in range(0, 700, 100):top_left=(j,i)botton_right=(j+99,i+99)if i!=0 and i!=600 and (i==j or i+j==600):cv2.rectangle(image,top_left,botton_right,(0,0,255),-1)else:cv2.rectangle(image,top_left,botton_right,(255,255,255),1)
5.4、将BGR转化为RGB
python"># 将BGR格式的图像转换为RGB格式,以便正确显示
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
5.5、分割RGB通道
python"># 分离图像的红、绿、蓝通道
r, g, b = cv2.split(image_rgb)
5.6、对三通道进行操作
python"># 创建三个单独的通道图像,初始为全零(黑色)
blue_channel = np.zeros((700, 700, 3), dtype=np.uint8) # 蓝色通道
green_channel = np.zeros((700, 700, 3), dtype=np.uint8) # 绿色通道
red_channel = np.zeros((700, 700, 3), dtype=np.uint8) # 红色通道 # 将分离出的通道放入对应的通道图像中
blue_channel[:, :, 0] = b # 将蓝色通道的值放入蓝色通道图像的第一个通道
green_channel[:, :, 1] = g # 将绿色通道的值放入绿色通道图像的第二个通道
red_channel[:, :, 2] = r # 将红色通道的值放入红色通道图像的第三个通道 # 将单独的通道图像转换为RGB格式
blue_channel_rgb = cv2.cvtColor(blue_channel, cv2.COLOR_BGR2RGB)
green_channel_rgb = cv2.cvtColor(green_channel, cv2.COLOR_BGR2RGB)
red_channel_rgb = cv2.cvtColor(red_channel, cv2.COLOR_BGR2RGB)
5.7、通过matplotlib显示图像
python">plt.subplot(232) # 在2行3列的网格中,放置第2个子图(1-indexed)
plt.imshow(image_rgb) # 显示原始的RGB图像
plt.axis('off') # 关闭坐标轴 plt.subplot(234) # 在2行3列的网格中,放置第4个子图
plt.imshow(blue_channel_rgb) # 显示蓝色通道图像
plt.axis('off') # 关闭坐标轴 plt.subplot(235) # 在2行3列的网格中,放置第5个子图
plt.imshow(green_channel_rgb) # 显示绿色通道图像
plt.axis('off') # 关闭坐标轴 plt.subplot(236) # 在2行3列的网格中,放置第6个子图
plt.imshow(red_channel_rgb) # 显示红色通道图像
plt.axis('off') # 关闭坐标轴 plt.tight_layout() # 自动调整子图参数,以便给子图留出更合适的空间
plt.show() # 显示所有绘制的图像
5.8、通过cv显示图像
python">cv2.imshow('image_rgb', image) cv2.waitKey(0) # 等待用户按键
5.9、完整代码
python">import cv2 # 导入OpenCV库,用于图像处理
import numpy as np # 导入NumPy库,用于数组和矩阵操作
from matplotlib import pyplot as plt # 导入Matplotlib库,用于绘图 # 创建一个700x700的黑色图像,包含三个颜色通道(RGB)
image = np.zeros((700, 700, 3), dtype=np.uint8) # 使用双层循环在图像上绘制网格和交叉的红色方块
for i in range(0, 700, 100): # 外层循环,步长为100,从0到600 for j in range(0, 700, 100): # 内层循环,同样步长为100 # 绘制水平网格线 image[i, :, :] = (255, 255, 255) # 将第i行的所有像素设为白色 # 绘制垂直网格线 image[:, j, :] = (255, 255, 255) # 将第j列的所有像素设为白色 # 绘制交叉的红色方块 if i != 0 and j != 0 and i != 600 and j != 600 and (i == j or i + j == 600): image[i:i+100, j:j+100, :] = (0, 0, 255) # 将指定区域设为红色 # 将BGR格式的图像转换为RGB格式,以便正确显示
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # 分离图像的红、绿、蓝通道
r, g, b = cv2.split(image_rgb) # 创建三个单独的通道图像,初始为全零(黑色)
blue_channel = np.zeros((700, 700, 3), dtype=np.uint8) # 蓝色通道
green_channel = np.zeros((700, 700, 3), dtype=np.uint8) # 绿色通道
red_channel = np.zeros((700, 700, 3), dtype=np.uint8) # 红色通道 # 将分离出的通道放入对应的通道图像中
blue_channel[:, :, 0] = b # 将蓝色通道的值放入蓝色通道图像的第一个通道
green_channel[:, :, 1] = g # 将绿色通道的值放入绿色通道图像的第二个通道
red_channel[:, :, 2] = r # 将红色通道的值放入红色通道图像的第三个通道 # 将单独的通道图像转换为RGB格式
blue_channel_rgb = cv2.cvtColor(blue_channel, cv2.COLOR_BGR2RGB)
green_channel_rgb = cv2.cvtColor(green_channel, cv2.COLOR_BGR2RGB)
red_channel_rgb = cv2.cvtColor(red_channel, cv2.COLOR_BGR2RGB) # 使用Matplotlib绘制图像
plt.subplot(232) # 在2行3列的网格中,放置第2个子图(1-indexed)
plt.imshow(image_rgb) # 显示原始的RGB图像
plt.axis('off') # 关闭坐标轴 plt.subplot(234) # 在2行3列的网格中,放置第4个子图
plt.imshow(blue_channel_rgb) # 显示蓝色通道图像
plt.axis('off') # 关闭坐标轴 plt.subplot(235) # 在2行3列的网格中,放置第5个子图
plt.imshow(green_channel_rgb) # 显示绿色通道图像
plt.axis('off') # 关闭坐标轴 plt.subplot(236) # 在2行3列的网格中,放置第6个子图
plt.imshow(red_channel_rgb) # 显示红色通道图像
plt.axis('off') # 关闭坐标轴 plt.tight_layout() # 自动调整子图参数,以便给子图留出更合适的空间
plt.show() # 显示所有绘制的图像 # 使用OpenCV显示原始图像(BGR格式)
cv2.imshow('image_rgb', image) cv2.waitKey(0) # 等待用户按键
六、库函数
6.1、cvtColor()
将图像从一个色彩空间转换为另一个色彩空间。
该函数将输入图像从一个色彩空间转换为另一个色彩空间。在从 RGB 色彩空间转换的情况下,应明确指定通道的顺序(RGB 或 BGR)。请注意,OpenCV 中的默认颜色格式通常称为 RGB,但实际上是 BGR(字节是相反的)。因此,标准 (24 位) 彩色图像中的第一个字节将是 8 位蓝色分量,第二个字节将是绿色,第三个字节将是红色。然后,第 4 个、第 5 个和第 6 个字节将是第二个像素(蓝色、绿色、红色),依此类推。
R、G 和 B 通道值的常规范围为:
- 0 到 255 表示CV_8U图像
- 0 到 65535(CV_16U图像
- 0 到 1 表示CV_32F图像
python">cv.cvtColor( src, code[, dst[, dstCn[, hint]]] ) -> dst
函数 | 描述 |
---|---|
src | 输入图像:8 位无符号、16 位无符号 ( CV_16UC... ) 或单精度浮点。 |
dst | 输出图像的大小和深度与 src 相同。 |
code | 色彩空间转换代码 |
dstCn | 目标图像中的通道数;如果参数为 0,则 Channels 的数量会自动从 src 和 code 中得出。 |
hint | 实现修改标志 |
6.2、 拆分和合并图像通道
有时,您需要单独处理图像的 B、G、R 通道。在这种情况下,您需要将 BGR 图像拆分为单个通道。在其他情况下,您可能需要加入这些单独的通道以创建 BGR 图像。您可以简单地通过以下方式执行此作:
python">>>> b,g,r = cv.split(img)
>>> img = cv.merge((b,g,r))
假设您要将所有红色像素设置为零 - 您无需先拆分通道。Numpy 索引更快:
python">>>> img[:,:,2] = 0
6.3、imshow()
在指定窗口中显示图像。
函数 imshow 在指定窗口中显示图像。如果窗口是使用 cv::WINDOW_AUTOSIZE 标志创建的,则图像将以其原始大小显示,但它仍受屏幕分辨率的限制。否则,将缩放图像以适合窗口。
python">cv.imshow( winname, mat ) -> None
函数 | 描述 |
---|---|
winname | 窗口的名称 |
mat | 要显示的图像。 |
注意
此函数后应调用 cv::waitKey 或 cv::p ollKey 来执行 GUI 内务处理任务,这些任务是实际显示给定图像并使窗口响应鼠标和键盘事件所必需的。否则,它不会显示图像,并且窗口可能会锁定。例如,waitKey(0) 将无限显示窗口,直到任意一个键(适合图像显示)。waitKey(25) 将显示一个帧,并等待大约 25 ms 的按键作(适用于逐帧显示视频)。要删除窗口,请使用 cv::d estroyWindow。
[仅限 Windows 后端]按 Ctrl+C 会将图像复制到剪贴板。按 Ctrl+S 将显示一个对话框以保存图像。
[仅限 Wayland 后端]支持格式已扩展。
- 如果图像是 8 位签名的,则像素将偏移 128。也就是说,值范围 [-128,127] 映射到 [0,255]。
- 如果图像是 16 位签名的,则像素将除以 256 并偏移 128。也就是说,值范围 [-32768,32767] 映射到 [0,255]。
6.4、waitKey()
等待按下的键。
函数 waitKey 无限等待 key 事件(当delay < 0)或 delay 毫秒数(当它为正数时)。由于作系统在切换线程之间有最短时间,因此该函数不会完全等待延迟毫秒,它至少会等待延迟毫秒,具体取决于当时计算机上正在运行的其他内容。它返回所按下的键的代码,如果在指定时间过去之前没有按下任何键则返回 -1。要检查是否按下了某个键但不等待它,请使用 polKey。
python">cv.waitKey([, delay]) ->retval
函数 | 描述 |
---|---|
delay | 延迟(以毫秒为单位)。0 是表示 “永远” 的特殊值。 |
注意
函数 waitKey 和 pollKey 是 HighGUI 中唯一可以获取和处理 GUI 事件的方法,因此需要定期调用其中一个函数以进行正常的事件处理,除非在负责事件处理的环境中使用 HighGUI。
仅当至少创建了一个 HighGUI 窗口并且该窗口处于活动状态时,该功能才有效。如果有多个 HighGUI 窗口,则其中任何一个窗口都可以处于活动状态。
6.5、rectangle()
python">cv.rectangle( img, pt1, pt2, color[, thickness[, lineType[, shift]]] ) -> img
cv.rectangle( img, rec, color[, thickness[, lineType[, shift]]] ) -> img
函数 | 描述 |
---|---|
img | 图像。 |
pt1 | 矩形的顶点。 |
pt2 | 与 pt1 相对的矩形的顶点。 |
color | 矩形颜色或亮度(灰度图像)。 |
thickness | 构成矩形的线条的粗细。负值(如 FILLED)表示函数必须绘制填充矩形 |
lineType | 线路的类型。 |
shift | 点坐标中的小数位数。 |