创建和显示窗口相关函数
namedWindow()
功能 :创建一个显示图像的窗口。在调用 imshow() 之前,通常需要先用它创建一个窗口(如果不创建,imshow 会自动创建一个默认大小且不可调节的窗口)。
原型 :void namedWindow(const String& winname, int flags = WINDOW_AUTOSIZE);
-
parm1 (
winname) :String类型。窗口的名称(标识符)。后续的imshow、resizeWindow等函数都要通过这个名称来指定操作哪个窗口。 -
parm2 (
flags) :int类型。窗口的标志位,决定窗口的大小和显示方式。常用值:-
WINDOW_AUTOSIZE(默认):窗口大小自动适应图片大小,用户不能手动改变窗口大小。 -
WINDOW_NORMAL:用户可以自由拖动改变窗口大小(在调试大分辨率图片时非常有用)。 -
WINDOW_OPENGL:支持 OpenGL 渲染。
-
imread()
功能 :从指定的文件路径中加载图像。
原型 :Mat imread(const String& filename, int flags = IMREAD_COLOR);
-
parm1 (
filename) :String类型。要读取的图像文件的路径(包括文件名和后缀)。 -
parm2 (
flags) :int类型。读取图像的颜色模式。常用值:-
IMREAD_COLOR(默认值 1):始终将图像转换为 3 通道 BGR 彩色图像。 -
IMREAD_GRAYSCALE(值 0):始终将图像转换为单通道灰度图像。 -
IMREAD_UNCHANGED(值 -1):原样读取,保留 Alpha 透明通道。
-
-
返回值 :返回一个
Mat(矩阵)对象。如果读取失败(如路径错误、文件损坏),则返回一个空矩阵(Python 中为None)。
imshow()
功能 :在指定的窗口中显示图像。
原型 :void imshow(const String& winname, InputArray mat);
-
parm1 (
winname) :String类型。要显示图像的窗口的名称。如果该窗口尚未创建,OpenCV 会使用默认参数自动创建一个。 -
parm2 (
mat) :InputArray类型(通常传入cv::Mat)。要显示的图像数据矩阵。
waitKey()
功能 :等待用户按键。极其重要! 它是 OpenCV 刷新 GUI 窗口事件队列的"触发器"。必须放在 imshow() 之后调用。
原型 :int waitKey(int delay = 0);
-
parm1 (
delay) :int类型。等待按键的时间(单位:毫秒)。-
delay = 0:无限期等待,直到用户按下任意键。 -
delay > 0:等待指定毫秒数(如30表示约 30 FPS 的视频播放速度),如果期间没有按键则返回-1,继续执行后续代码。
-
返回值 :int 类型。返回按下按键的 ASCII 码(例如 ESC 键是 27)。如果超时未按键则返回 -1。
resizeWindow()
功能 :改变指定窗口的大小。通常配合 WINDOW_NORMAL 标志使用。
原型 :void resizeWindow(const String& winname, int width, int height);
-
parm1 (
winname) :String类型。要调整大小的窗口名称。 -
parm2 (
width,height) :int类型。这里其实包含两个参数:-
width:窗口的新宽度(像素)。 -
height:窗口的新高度(像素)。
-
imwrite()
功能 :将图像数据矩阵(Mat)保存为指定格式的图像文件。格式由文件名的后缀(如 .jpg, .png 等)决定。
原型 :bool imwrite(const String& filename, InputArray img, const std::vector<int>& params = std::vector<int>());
-
parm1 (
filename) :String类型。要保存的文件名(需包含扩展名,如"output.jpg")。 -
parm2 (
img) :InputArray类型(通常传入cv::Mat)。要保存的图像数据矩阵。 -
parm3 (
params) :const std::vector<int>&类型(可选)。特定格式的编码参数。通常不填。如果填,是一对对的键值对。例如保存为 JPEG 时,传入{cv::IMWRITE_JPEG_QUALITY, 90}表示压缩质量为 90%(0-100)。保存 PNG 时用IMWRITE_PNG_COMPRESSION(0-9)。 -
返回值 :
bool类型。保存成功返回true,失败返回false(例如路径不存在或权限不足)。
destroyAllWindows()
功能 :关闭所有由 OpenCV 创建的高层级 GUI 窗口(销毁并释放相关内存资源)。
原型 :void destroyAllWindows();
相关代码:
python
import cv2
import sys
# 1. 读取图像(替换为你自己的图片路径)
# 默认读取为彩色图 (cv2.IMREAD_COLOR)
img = cv2.imread('test.jpg')
# 检查图像是否读取成功
if img is None:
print("无法读取图像,请检查路径是否正确!")
sys.exit()
# 2. 创建窗口(自动适应图片大小)
cv2.namedWindow('new', cv2.WINDOW_AUTOSIZE)
# 3. 在窗口中显示图像
cv2.imshow('new', img)
# 4. 等待按键(0 表示无限期等待)
key = cv2.waitKey(0)
# 5. 判断按键(按 q 或 ESC 键退出)
# 注意:Python 中 waitKey 返回的是整数,需用 ord() 转换字符
if key == ord('q') or key == 27:
sys.exit(0)
# 6. 销毁所有窗口,释放资源
cv2.destroyAllWindows()
cv2.VideoCapture() ------ 捕获视频源
作用: 它的作用是"打开"一个视频来源,既可以是你电脑上的视频文件,也可以是插在电脑上的 USB 摄像头。
-
读取摄像头 :括号里填数字(通常
0代表默认摄像头,外接的可能是1或2)。cap = cv2.VideoCapture(0) -
读取视频文件:括号里填视频的路径。
cap = cv2.VideoCapture('my_video.mp4')
cap.read() ------ 读取一帧画面
作用: 从打开的视频源里,读取当前的一帧图像。视频本质上就是一张张快速播放的图片。
-
返回值:它返回两个东西。
-
ret(Boolean):布尔值,表示有没有成功读到画面(比如视频播完了,或者摄像头没连好,就会返回False)。 -
frame(NumPy数组):就是读到的这一帧图像。
ret, frame = cap.read()💡 关键提醒 :通常我们会把它放进一个
while循环里,这样就能不断读取,形成连续的视频流。如果ret是False,循环就可以结束了。 -
cap.release() ------ 释放资源作用: 关闭视频文件,或者断开与摄像头的连接。
为什么重要:如果不写这一句,摄像头可能会一直被程序"占用",导致你退出程序后,其他软件(甚至下次你自己再运行代码)打不开摄像头,只能重启电脑才能解决。
cap.release()
cv2.VideoWriter() ------ 创建视频写入器
作用: 创建一个对象,告诉程序"我要保存一个什么样的视频文件"。
-
参数要求:它通常需要 4 个必填参数(有时还有第 5 个控制彩色/灰度)。
-
文件名 :比如
'output.avi'或'output.mp4'。 -
编码格式(FourCC) :告诉电脑用什么格式压缩视频。最常见的是
cv2.VideoWriter_fourcc(*'XVID')或(*'MJPG')。 -
帧率(FPS) :每秒播放多少张画面,比如
20或30。 -
画面尺寸 :必须是一个元组
(width, height)。⚠️核心避坑点:这个尺寸必须和你后面write进去的每一帧画面的尺寸一模一样,否则视频保存出来是坏的(只有几KB或无法播放)。
-
python
# 设置编码器
fourcc = cv2.VideoWriter_fourcc(*'XVID')
# 创建写入器(保存为 output.avi,帧率 20,尺寸 640x480)
out = cv2.VideoWriter('output.avi', fourcc, 20.0, (640, 480))
out.write() ------ 写入一帧
作用: 把具体的画面(图像/帧)按顺序塞进刚才创建的视频文件里。
- 注意:它和文件操作里的
f.write()类似,你要把当前处理好的frame传进去。
python
out.write(frame) # frame 必须是一个 NumPy 数组(图像)
out.release() ------ 释放资源
作用: 关闭文件并确保所有数据都完整地写入到了硬盘上。
- 为什么重要:和摄像头一样,如果不写这句,视频文件可能只占用内存而没有真正写进硬盘,导致文件损坏或只有 0 字节。
python
out.release()
相关代码:
python
import cv2
# 1. 打开摄像头
cap = cv2.VideoCapture(0)
# 获取摄像头的实际分辨率(重要:防止尺寸不匹配导致保存失败)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 2. 设置视频写入器 (注意这里用的是实际获取的 width 和 height)
fourcc = cv2.VideoWriter_fourcc(*'mjpg')
out = cv2.VideoWriter('my_record.avi', fourcc, 20.0, (width, height))
while True:
# 读取一帧
ret, frame = cap.read()
if not ret:
break
# 显示出来
cv2.imshow('Recording...', frame)
# 3. 写入文件
out.write(frame)
# 按 ESC 退出
if cv2.waitKey(1) == 27:
break
# 4. 释放所有资源 (非常重要,顺序无所谓,但千万别漏)
cap.release()
out.release()
cv2.destroyAllWindows()
print("视频保存完毕!")
setMouseCallback()
功能 :为指定的窗口设置鼠标事件的回调函数。当用户在该窗口内进行鼠标操作(如点击、移动、双击等)时,OpenCV 会自动调用你设定的 callback 函数。
原型 :void setMouseCallback(const String& winname, MouseCallback onMouse, void* userdata = 0);
-
parm1 (
winname) :String类型。窗口的名称(必须与namedWindow创建的名称一致)。 -
parm2 (
callback) :MouseCallback类型。回调函数的函数名。必须符合特定的参数格式(见下方)。 -
parm3 (
userdata) :void*类型。传递给回调函数的用户自定义数据指针(默认传0或NULL即可,高级用法中可以传入结构体指针来共享数据)。
回调函数 callback() (自定义)
功能 :这是由开发者自己实现的一个函数。它不会主动运行,只有当鼠标在指定窗口发生动作时,才会被系统"回调"执行。
原型 :void onMouse(int event, int x, int y, int flags, void* userdata);
-
parm1 (
event) :int类型。鼠标事件的类型。常用值:-
EVENT_MOUSEMOVE(0):鼠标移动。 -
EVENT_LBUTTONDOWN(1):鼠标左键按下。 -
EVENT_RBUTTONDOWN(2):鼠标右键按下。 -
EVENT_LBUTTONUP(4):鼠标左键松开。 -
EVENT_LBUTTONDBLCLK(7):鼠标左键双击。
-
-
parm2 (
x) :int类型。鼠标当前在窗口图像坐标系中的 X 坐标(列)。 -
parm3 (
y) :int类型。鼠标当前在窗口图像坐标系中的 Y 坐标(行)。 -
parm4 (
flags) :int类型。鼠标事件的标志位,通常用于判断是否有组合键(如EVENT_FLAG_SHIFTKEY、EVENT_FLAG_CTRLKEY)或哪个按键被按下。 -
parm5 (
userdata) :void*类型。接收来自setMouseCallback传递进来的用户数据指针。
示例代码
python
import cv2
import numpy as np
# 全局变量记录点击坐标
pt = (-1, -1)
# 鼠标回调函数
def mouse_callback(event, x, y, flags, userdata):
global pt
# 如果发生左键按下事件
if event == cv2.EVENT_LBUTTONDOWN:
pt = (x, y)
print(f"点击坐标: {pt}, 传入的自定义数据: {userdata}")
# 创建窗口
cv2.namedWindow('mouse', cv2.WINDOW_NORMAL)
cv2.resizeWindow('mouse', 640, 360)
# 设置鼠标回调
cv2.setMouseCallback('mouse', mouse_callback, "123")
# 显示窗口和背景
img = np.zeros((360, 640, 3), np.uint8)
while True:
# 如果有点击过,在点击位置画一个红色的实心圆(起到可视化反馈的作用)
if pt != (-1, -1):
cv2.circle(img, pt, 10, (0, 0, 255), -1)
cv2.imshow('mouse', img)
key = cv2.waitKey(1) # 等待 1ms,用于刷新界面和监听键盘
# 补充退出逻辑:如果按下 ESC 键(ASCII 码为 27)则退出
if key == 27:
break
# 退出后销毁窗口
cv2.destroyAllWindows()
createTrackbar()
功能 :在指定的窗口上创建一个滑动条(滑块)。常用于实时调整算法参数(如二值化阈值、Canny 的高低阈值等),无需每次重新编译代码。
原型 :int createTrackbar(const String& trackbarname, const String& winname, int* value, int count, TrackbarCallback onChange = 0, void* userdata = 0);
-
parm1 (
trackbarname) :String类型。滑动条的名称(显示在滑块旁边)。 -
parm2 (
winname) :String类型。滑动条依附的窗口名称(必须与namedWindow创建的名称一致)。 -
parm3 (
value) :int*类型(指针)。极其重要! 这是一个指向整型变量的指针,滑块当前的数值会实时同步到这个变量里。(在 Python 中没有指针,通常传入一个初始值,并在回调函数中获取)。 -
parm4 (
count) :int类型。滑动条的最大值(最小值永远是 0)。 -
parm5 (
onChange) :TrackbarCallback类型(可选)。滑动条数值改变时触发的回调函数。如果设为0或None,则不会触发任何函数(Python 中必须传,否则无法获取实时值)。 -
parm6 (
userdata) :void*类型(可选)。传递给回调函数的用户数据指针。
getTrackbarPos()
功能 :获取指定窗口上指定滑动条的当前数值。
原型 :int getTrackbarPos(const String& trackbarname, const String& winname);
-
parm1 (
trackbarname) :String类型。要获取数值的滑动条名称。 -
parm2 (
winname) :String类型。滑动条所在的窗口名称。 -
返回值 :
int类型。返回当前滑块指示的数值。
示例代码:
python
import cv2
import numpy as np
def callback():
pass
cv2.namedWindow('trackbar', cv2.WINDOW_NORMAL)
cv2.createTrackbar('R', 'trackbar', 0, 255, callback)
cv2.createTrackbar('G', 'trackbar', 0, 255, callback)
cv2.createTrackbar('B', 'trackbar', 0, 255, callback)
img = np.zeros((480, 640, 3), np.uint8)
while True:
cv2.imshow('trackbar', img)
r = cv2.getTrackbarPos('R', 'trackbar')
g = cv2.getTrackbarPos('G', 'trackbar')
b = cv2.getTrackbarPos('B', 'trackbar')
img[:] = [b, g, r]
key = cv2.waitKey(10)
if key & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
色彩空间转换
cv2.cvtColor(src, code)
-
作用:把图像从一个色彩空间转换到另一个色彩空间。
-
src:输入图像(通常是 NumPy 数组)。 -
code:转换代码(就是你列表里的那些常量)。 -
注意:转换后的图像,通道数和数据类型可能会变。比如 BGR 转 GRAY(灰度),通道数会从 3 变成 1;BGR 转 HSV,通道数还是 3,但数值范围变了。
示例代码:
python
import cv2
def callback():
pass
cv2.namedWindow('color', cv2.WINDOW_NORMAL)
img = cv2.imread('./picture/rmb.jpg')
colorspaces = [cv2.COLOR_BGR2RGB, cv2.COLOR_BGR2GRAY,
cv2.COLOR_BGR2HSV, cv2.COLOR_BGR2YUV]
cv2.createTrackbar('curcolor', 'color', 0, 3, callback)
while True:
index = cv2.getTrackbarPos('curcolor', 'color')
#颜色空间转换API
cvt_img = cv2.cvtColor(img, colorspaces[index])
cv2.imshow('color', cvt_img)
key = cv2.waitKey(10)
print(key)
if key & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
numpy 创建特殊矩阵的操作
Array(通用数组)
-
概念:把一串普通的数字(或者嵌套的列表),按照你指定的行列结构,转换成一个可以进行数学运算的二维或多维矩阵。
-
在视觉中的意义 :这是图像在计算机里的真实面目。
-
当你用 OpenCV 读取一张图片时,它返回的就是一个巨大的 Array(数组)。
-
如果你手动输入一堆数字构成一个 Array,它就可以被当作一张小尺寸的图片来处理。
-
前几个(Zero, One, Full)都是自动批量生成 特定数值的 Array;而
Array函数是你手动填入具体数值来构建矩阵。
-
Zero(零矩阵/全零数组)
-
概念 :所有元素的值全是
0。 -
在视觉中的意义 :代表**"什么都没有"**。在图像里,0 通常代表纯黑色;在掩膜(Mask)里,0 代表遮罩、不显示。它是极其常用的"初始画布"。
One(全一矩阵/全一数组)
-
概念 :所有元素的值全是
1。 -
在视觉中的意义 :代表**"基础单位"** 或**"全亮"**。在数学里,它是计算的基础;在图像处理里,如果把它乘上 255,就会变成一张纯白色的图;它也常被用作滤波器(卷积核)的基础模板。
Full(自定义填充矩阵)
-
概念 :所有元素的值全是你指定的任意数值。
-
在视觉中的意义 :它是
Zero和One的升级版。如果你想要一张纯灰色的背景(填充 128),或者一张特定颜色的图片(比如每个像素的 BGR 都是 255, 0, 0),就用它来快速生成一张底色图。
Identity(单位矩阵)
-
概念 :一个正方形 的矩阵。它的特征是:从左上角到右下角的主对角线上全是
1,其余所有位置全是0。 -
在视觉中的意义 :数学里的"数字 1"。任何矩阵乘以它,都等于它本身。在图像处理中,它常代表**"原封不动"**(比如在坐标变换时,代表没有任何平移、缩放或旋转的初始状态)。
Eye(对角线矩阵)
-
概念 :它是
Identity的"灵活版"。它不仅也能生成主对角线为1的方阵,还能生成非正方形 的矩阵,或者让那一排1发生偏移(不在正中间,而是偏左上或偏右下)。 -
在视觉中的意义:主要用于更复杂的数学运算。比如你在做图像的特征提取、坐标映射时,需要用到带有偏移量的数学结构,它就能派上用场。
示例代码:
python
import cv2
# 1. 读取图片
img = cv2.imread('./picture/rmb.jpg')
if img is None:
print("图片读取失败,请检查路径!")
exit()
# 2. 读值:打印坐标 (100, 100) 处的 BGR 像素值
# 注意:OpenCV 的坐标是 [y, x](先行后列)
print("坐标 (100, 100) 的 BGR 值为:", img[100, 100])
# 3. 写值:修改矩阵中的像素
# 这里用你截图里的逻辑,但为了保证不管图片多大都不会报错,我们改画一个 100x100 的正方形
# 把这个区域全部赋值为 [0, 0, 255](纯红色)
img[0:100, 100:200] = [0, 0, 255]
# 4. 显示修改后的图片
cv2.imshow('img', img)
key = cv2.waitKey(0) # 无限等待,直到用户按键
if key & 0xFF == ord('q'):
cv2.destroyAllWindows()
numpy ROI
. 获取子矩阵(划出 ROI 区域)
-
概念:利用 NumPy 的切片功能,从原图中"框"出一个感兴趣的区域(Region of Interest)。
-
意义 :这是做图像处理的起点。你不需要处理整张图,只把注意力集中在局部(比如车牌、人脸、特定物体)。注意,它默认是视图,修改它会直接改变原图。
-
对应代码:
roi = img[100:400, 100:600]
2. 整个区域填充(涂色)
-
概念 :把当前矩阵(ROI)里的所有行(
:)、所有列(:)的像素,全部替换为指定的 BGR 颜色。 -
意义:常用于打码(隐私遮挡)、画实心图形,或者给某个特定区域换背景色。
这里的
[:, :]代表把这个子矩阵"掏空涂满"。 -
对应代码:
roi[:, :] = [0, 0, 255] # 把刚才切出来的长方形全涂成红色
3. 提取单个通道(切片进阶)
-
概念 :在已有的 ROI 矩阵基础上,通过第三个维度的索引(
0、1、2)单独提取某一个颜色通道。 -
意义:分离 B、G、R 通道,用来做颜色过滤、阈值分割,或者单独分析某个颜色的强度。
-
对应代码:
# 提取 roi 里的第一个通道(OpenCV里0代表Blue通道) blue_channel = roi[:, :, 0]
4. 局部嵌套切片(画中画)
-
概念 :在已切好的子矩阵
roi中,再次使用切片[y1:y2, x1:x2]划定一个更小的范围进行赋值。 -
意义:实现精准的局部修改,比如在一大块红色区域里,再画一个绿色的实心小方块。
-
对应代码:
# 在刚才的红底 ROI 里,再切出一块小正方形,涂成绿色 roi[10:200, 10:200] = [0, 255, 0]
示例代码:
python
import cv2
import numpy as np
# 1. 创建一张 600x800 的纯白画布作为底图 (代替你读取的图片,方便直接跑)
img = np.full((600, 800, 3), 255, dtype=np.uint8)
# ================= 核心代码区 =================
# ① 划出 ROI 区域:从 Y=100 到 400,X=100 到 600
roi = img[100:400, 100:600]
# ② 整体填充:把这块 ROI 全部涂成红色 (BGR: 0,0,255)
roi[:] = [0, 0, 255]
# ③ 嵌套涂色:在红色的 ROI 里面,再切出 Y=10到100,X=10到100 的小块,涂成绿色 (BGR: 0,255,0)
roi[10:100, 10:100] = [0, 255, 0]
# ④ 提取单通道:把整个大图的蓝色通道单独拿出来(验证切片原理,这步不改变图像,只是拿出来看)
blue_channel = img[:, :, 0]
# ================= 核心代码结束 =================
# 显示图像
cv2.namedWindow('Result', cv2.WINDOW_NORMAL)
cv2.imshow('Result', img) # 此时原图 img 上已经被画上了一大块红底绿方块!
key = cv2.waitKey(0)
if key & 0xFF == ord('q'):
cv2.destroyAllWindows()
MAT
为:OpenCV 的图像/矩阵容器,由「矩阵头 + 数据指针」组成。
好处:
-
自动内存管理:不用手动 malloc/free,引用计数自动释放。
-
浅拷贝高效 :
Mat B = A;只复制头、共享数据,不拷贝像素。 -
支持 ROI:可只引用图像局部区域,零拷贝。
-
函数传参快 :传
Mat不复制大数据。
需要独立副本时用 clone() 与 copyto() 深拷贝。


深浅拷贝: