初识opencv01——基本api操作
文章目录
- 前言
- 一、计算机中的图像
- 1.1 环境安装
- 1.2 计算机中的图像构成
- 1.3 计算机中的图像存储
- 二、基本图像操作
- 2.1 图像读取
- 2.2 图像创建与保存
- 2.3 图形绘制
- 2.4 图像修改尺寸
- 2.5 读取视频
- 总结
前言
OpenCV(开放源代码计算机视觉库)是一个开源的计算机视觉和机器学习软件库。由一系列 C++ 类和函数构成,用于图像处理、计算机视觉领域的算法实现。本文主要讲解的是OpenCV-Python的使用。
一、计算机中的图像
1.1 环境安装
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python
或者
conda install opencv
1.2 计算机中的图像构成
在人眼中,以下图片是一只猫咪高举着前爪,好奇地注视着上方。而计算机并没有“猫咪”之类的存在于客观现实世界的概念。在计算机中,图像不过是像素点的有序集合。

而像素是图像的基本单元,每个像素存储着图像的颜色、亮度和其他特征。一系列像素组合到一起就形成了完整的图像,在计算机中,图像以像素的形式存在并采用二进制格式进行存储。根据图像的颜色不同,每个像素可以用不同的二进制数表示。
1.3 计算机中的图像存储
计算机采用0/1编码的系统,数字图像也是利用0/1来记录信息,我们平常接触的图像都是8位数图像。opencv中常用的是8位图像,大多数彩色和灰度图像使用8位表示每个通道的像素值,范围从0到255,其中0,代表最黑,1,表示最白。
- 通道
日常生活中常见的图像是RGB三原色图。RGB图上的每个点都是由红(R)、绿(G)、蓝(B)三个颜色按照一定比例混合而成的,几乎所有颜色都可以通过这三种颜色按照不同比例调配而成。在计算机中,RGB三种颜色被称为RGB三通道,每个通道的取值都是0-255,根据这三个通道存储的像素值,来对应不同的颜色。
图像的每个通道都可看作一张独立的图像,将所有通道混合在一起即可合成原始图像
蓝色通道(B) | 绿色通道(G) | 红色通道(R) |
---|---|---|
![]() | ![]() | ![]() |
- 尺寸
在OpenCV中,无论是读取还是创建图像,结果都是一个NumPy数组。其中二维图像是二维数组,彩色图像是三维数组。而图像的尺寸(形状)由其高、宽和通道数决定。 - 像素
- 单通道图像(灰度图像):每个像素由一个数值表示,代表该点的亮度。值越接近0,颜色越暗;值越接近255,颜色越亮。
- 多通道图像(彩色图像):
在OpenCV中,默认情况下,彩色图像是以BGR(蓝-绿-红)顺序存储
二、基本图像操作
2.1 图像读取
这里给出一份示例代码:
import cv2 as cv# 读取一张图片
img = cv.imread('path/to/your/image.jpg')# 创建一个名为 "Resizable" 的窗口,允许用户调整大小
cv.namedWindow('Resizable', cv.WINDOW_NORMAL)# 创建一个名为 "Fixed Size" 的窗口,大小固定为图像尺寸
cv.namedWindow('Fixed Size', cv.WINDOW_AUTOSIZE)# 将同一张图片显示在两个不同的窗口中
cv.imshow('Resizable', img)
cv.imshow('Fixed Size', img)# 等待按键
cv.waitKey(0)
cv.destroyAllWindows()
其中用到的api有:
- cv2.namedWindow(winname [,窗口属性])
使用cv2.namedWindow()
方法创建一个新的窗口。你可以为这个窗口指定一个名称,并且可以选择窗口的属性。
winname为窗口名,窗口属性是一个可选属性,常用值有
cv2.WINDOW_AUTOSIZE
(默认,窗口会根据加载的图像自动调整到合适的大小)、cv2.WINDOW_NORMAL
(窗口大小是可自由调整的)等。
- cv2.imread(path [,读取方式])
path为文件路径,字符串类型;读取方式为可选参数,接收参数可为整数或标志Flags
常用标志
- cv2.IMREAD_COLOR 或 1: 以彩色模式读取图像,忽略透明度。这是默认值 。无论原图是 JPG、PNG 还是其他格式,都会返回一个 3 通道 (BGR) 的数组。
- cv2.IMREAD_GRAYSCALE 或 0: 以灰度模式读取图像。返回一个 单通道 的二维数组。
- cv2.IMREAD_UNCHANGED 或 -1: 以包含透明度(Alpha 通道)的方式读取图像。如果原图是 PNG 等支持透明度的格式,则返回一个 4 通道 (BGRA) 的数组。
- cv2.imshow(winname,img)
winname为窗口名称,类型为字符串,窗口名称必须是唯一的,否则会覆盖之前的窗口。如果窗口名称未提前通过 cv2.namedWindow() 声明,则 imshow() 会自动创建一个窗口。
img为 要显示的图像数据,类型为NumPy 数组 (ndarray),数据类型通常是 uint8,表示每个像素值范围为 [0, 255]。
cv2.imshow() 不返回任何值,其主要功能是将图像显示在窗口中。
- cv.waitKey(n)
在调用显示图像的API后,要调用cv2.waitKey(0)给图像绘制留下时间,否则窗口会出现无响应情况,并且图像无法显示出来。
- cv.waitKey(0):表示无限期地等待任何键盘按键。这种用法常见于图像显示窗口中,确保图像在窗口中显示直到用户决定关闭它。
- cv.waitKey(n):n>0,意味着程序将等待n毫秒,即当前窗口显示n毫秒。这种方式常用于视频播放或实时摄像头捕获场景,以便控制每一帧停留的时间,同时允许用户通过按键来中断循环或发出命令。
- cv2.destroyAllWindows([winname])
会在当前程序执行到该语句时立即销毁指定的窗口,并释放与这些窗口相关的资源。若参数为空则销毁所有打开的窗口,并释放资源。
2.2 图像创建与保存
这里给出一份示例代码:
import cv2 as cv
import numpy as np# 1. 创建一个空白图像
# 创建一个 600x400 像素的白色背景图像 (BGR 格式)
height, width = 600, 400
image = np.zeros((height, width, 3), dtype=np.uint8) + 255 # 白色背景# 2. 在图像上添加文本
text = "Hello, OpenCV!"
font = cv.FONT_HERSHEY_SIMPLEX
font_scale = 1.5
color = (0, 0, 255) # BGR 颜色:红色
thickness = 2
position = (50, 200) # 文本位置 (x, y)cv.putText(image, text, position, font, font_scale, color, thickness)# 3. 显示图像
cv.imshow("Created Image", image)
cv.waitKey(0)
cv.destroyAllWindows()# 4. 保存图像到文件
output_path = "./output_image.png"
cv.imwrite(output_path, image)print(f"Image saved successfully at: {output_path}")
其中用到的api有:
-
numpy.zeros((height,width,channels),dtype=np. uint8)
会得到一个值全0的numpy数组,若作图片显示则为一张全黑图像,可修改其像素的颜色值。 -
cv2.putText(img,text,station,font,Fontscale,color,thickness,cv2.LINE_AA)
用于在图片中插入文字,参数:- img:要添加文字的图像
- text:要写入的文本数据
- station:文本的放置位置
- font:字体样式
- Fontscale:字体大小
- thickness:字体线条宽度
- cv2.LINE_AA:使用反走样技术绘制文本边框,可选
反走样是一种提高图形质量的技术,通过混合颜色和像素边缘来减少锯齿状效果,使文本看起来更加平滑、清晰。
这个方法不支持中文,如果使用中文文本会显示??
- cv2.imwrite(path,img)
path为指定保存图像的路径和文件名,包括文件扩展名,类型为字符串。img要保存的图像数据,类型为NumPy 数组 (ndarray)。
2.3 图形绘制
这里给出一份示例代码:
import cv2 as cv
import numpy as np# 1. 创建一个空白的黑色图像作为画布 (高度=400, 宽度=600, 3个通道)
canvas = np.zeros((400, 600, 3), dtype=np.uint8)# --- 绘制直线 (line) ---
# 在画布上从点 (50, 50) 到点 (200, 100) 画一条绿色的线,线宽为 3 像素。
# 注意:OpenCV 使用 BGR 颜色,所以 (0, 255, 0) 是绿色。
start_point = (50, 50)
end_point = (200, 100)
color_green = (0, 255, 0)
thickness_line = 3
cv.line(canvas, start_point, end_point, color_green, thickness_line)# --- 绘制圆形 (circle) ---
# 在画布上以点 (300, 200) 为圆心,半径为 50 像素,画一个蓝色的圆,线宽为 2 像素。
# 如果将 thickness 设置为 -1,则会填充整个圆形。
center_point = (300, 200)
radius = 50
color_blue = (255, 0, 0) # BGR: 蓝色
thickness_circle = 2
cv.circle(canvas, center_point, radius, color_blue, thickness_circle)# --- 绘制矩形 (rectangle) ---
# 在画布上从左上角点 (400, 100) 到右下角点 (550, 250) 画一个红色的矩形,线宽为 4 像素。
left_upper = (400, 100)
right_down = (550, 250)
color_red = (0, 0, 255) # BGR: 红色
thickness_rect = 4
cv.rectangle(canvas, left_upper, right_down, color_red, thickness_rect)# --- 显示结果 ---
cv.imshow('Drawing Shapes', canvas)
cv.waitKey(0) # 等待按键
cv.destroyAllWindows() # 关闭所有窗口
其中用到的api有:
- cv2.line(img,sart,end,color,thickness)
用于绘制直线,参数:
- img:要绘制直线的图像
- start、end:直线的起点和终点
- color:直线的颜色(对于彩色图像,使用 BGR 格式指定颜色)
- thickness:线条宽度
- cv2.circle(img,centerpoint,r,color,thickness)
用于绘制圆形,参数:
- img:要绘制圆形的图片
- centerpoint、r:圆心和半径
- color:线条颜色
- tnickness:线条宽度,为-1时生成闭合图案并填充颜色
- cv2.rectangle(img,leftupper,rightdown,color,thickness)
用于绘制矩形,参数:
- img:要绘制矩形的图像
- leftupper、rightdown:矩形的左上角和右下角坐标
- color:线条的颜色
- thickness:线条的宽度
2.4 图像修改尺寸
这里给出一份示例代码:
import cv2 as cv# 1. 读取一张图片
image = cv.imread('./path/to/your/image.jpg') # 请将路径替换为你的图片路径# 检查图片是否成功加载
if image is None:print("Error: Could not load image.")exit()# --- 图像切片 (Image Slicing) ---
# 示例1: 提取图像左上角的一个 200x200 的区域
roi_top_left = image[0:200, 0:200] # 从第0行到第199行,第0列到第199列# 示例2: 提取图像中间的一个矩形区域
height, width = image.shape[:2] # 获取图像的高度和宽度
center_y, center_x = height // 2, width // 2
half_size = 150
roi_center = image[center_y-half_size:center_y+half_size,center_x-half_size:center_x+half_size]# 示例3: 只提取蓝色通道 (BGR中的B, 索引为0)
blue_channel = image[:, :, 0] # :,: 表示所有行和所有列
# 注意:这会返回一个单通道的灰度图。要保留颜色,需要像之前那样用全黑背景复制。# --- 使用 cv2.resize() 调整图像大小 ---
# 方法1: 指定目标尺寸 (dsize)
# 将图像缩小到 300x300 像素
resized_small = cv.resize(image, (300, 300)) # dsize 参数是 (width, height)# 方法2: 指定缩放因子 (fx, fy)
# 将图像宽度和高度都放大到原来的 2 倍
resized_large = cv.resize(image, None, fx=2, fy=2)# --- 显示结果 ---
cv.imshow('Original', image)
cv.imshow('Top Left ROI', roi_top_left)
cv.imshow('Center ROI', roi_center)
cv.imshow('Blue Channel', blue_channel)
cv.imshow('Resized Small', resized_small)
cv.imshow('Resized Large', resized_large)cv.waitKey(0)
cv.destroyAllWindows()
其中使用的到的api有:
- 图像切片:
切片语法: image[起始行:结束行, 起始列:结束列],确保(y,x)
和(y+h,x+w)
都在图像的边界内,否则会出现索引越界错误。img
通常是numpy.ndarray
类型,切片操作返回的也是numpy.ndarray
类型。
OpenCV 中图像是按 [行, 列, 通道] 存储的,所以 y 坐标在前,x 坐标在后。
- cv2.resize(src, dsize, fx=None, fy=None)
用于调整图像大小的函数,在图像处理中很常用,参数:
- src: 输入的源图像。
- dsize: 输出图像的大小,格式为 (width, height) 元组。如果指定了 dsize,则 fx 和 fy 会被忽略。
- fx, fy: 在 X 轴和 Y 轴方向上的缩放因子。如果 dsize 是 None,则使用 fx 和 fy 来计算新的尺寸。
2.5 读取视频
这里给出一份示例代码:
import cv2 as cv# 创建一个 VideoCapture 对象,参数是视频文件的路径
video_path = './path/to/your/video.mp4' # 请将路径替换为你的视频文件路径
cap = cv.VideoCapture(video_path)# --- 主循环:逐帧读取和显示 ---
while True:# 从视频流中读取一帧ret, frame = cap.read()# `ret` 是一个布尔值,表示是否成功读取了帧# `frame` 是包含图像数据的 NumPy 数组if not ret:print("End of video or cannot receive frame. Exiting...")break# 显示当前帧cv.imshow('Video Playback', frame)# 等待按键。如果按 'q' 键,则退出循环# cv.waitKey(25) 表示每帧显示25毫秒(约40fps),这与许多视频的帧率匹配key = cv.waitKey(25) & 0xFF if key == ord('q'):break# --- 清理资源 ---
# 释放 VideoCapture 对象,关闭所有窗口
cap.release()
cv.destroyAllWindows()
其中使用的到的api有:
- cap = cv2.VideoCapture(path)
用于获取视频文件。path为视频流资源路径,若设置为0,代表从默认摄像头捕获视频流。 - ret,frame = cap.read()
用于读取视频文件,返回值为一个布尔值和一帧图像,布尔值表示是否成功读取到帧,如果为False,可能是因为视频结束或读取失败,如果为True,则frame是当前帧的图像数据。
总结
本博客“简要地介绍OpenCV的基础api。文章探讨了计算机中图像的构成与存储原理,聚焦于OpenCV最常用的基本API操作。