文章目录
一、使用cv::namedWindow()创建一个窗口
cv::namedWindow() 是 OpenCV 中用于创建一个显示窗口的函数,它通常与 cv::imshow() 一起使用,用于显示图像或视频帧。它属于 HighGUI 模块,是 OpenCV 提供的最基本 GUI 接口之一。
函数原型:
cpp
void cv::namedWindow(const std::string& winname, int flags = cv::WINDOW_AUTOSIZE);
参数说明:

窗口模式(flags):

注意:只有在 WINDOW_NORMAL 模式下,用户才能手动改变窗口大小。其他模式如 AUTOSIZE 下,窗口会随图像大小自动变化。
使用示例
示例 1:创建并显示图像窗口
cpp
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat img = imread("test.jpg");
if (img.empty()) {
printf("图片加载失败!\n");
return -1;
}
// 创建一个自动适应图像大小的窗口
namedWindow("My Window", WINDOW_AUTOSIZE);
// 在窗口中显示图像
imshow("My Window", img);
// 等待按键
waitKey(0);
return 0;
}
示例 2:创建一个可调整大小的窗口
cpp
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat img = imread("test.jpg");
if (img.empty()) return -1;
// 创建一个可缩放的窗口
namedWindow("Resizable Window", WINDOW_NORMAL);
imshow("Resizable Window", img);
waitKey(0);
return 0;
}
此时你可以拖动窗口边缘改变大小。
示例 3:与滑动条结合使用
cpp
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat img = imread("test.jpg");
if (img.empty()) return -1;
namedWindow("Brightness Control", WINDOW_NORMAL);
int alpha = 50;
createTrackbar("Brightness", "Brightness Control", &alpha, 100);
while (true)
{
Mat adjusted;
img.convertTo(adjusted, -1, 1, alpha - 50);
imshow("Brightness Control", adjusted);
if (waitKey(30) == 27) break; // 按下 ESC 退出
}
return 0;
}
二、通过cv::imshow()显示图像
cv::imshow() 是 OpenCV 中最常用的图像显示函数之一,用于在一个窗口中显示图像。
它通常与 cv::namedWindow() 和 cv::waitKey() 搭配使用。
在语言模型中,编码器和解码器都是由一个个的 Transformer 组件拼接在一起形成的。
函数原型:
cpp
void cv::imshow(const std::string& winname, cv::InputArray mat);
参数说明:

函数作用:
- 在指定名称的窗口中显示一张图像。
- 如果窗口不存在,OpenCV 会自动创建一个 WINDOW_AUTOSIZE 类型的窗口。
- 显示内容会一直保留,直到:显示新的内容(再次调用 imshow()),或者窗口被关闭(cv::destroyWindow())。
基本使用示例
示例 1:显示一张图片
cpp
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat img = imread("test.jpg"); // 读取图片
if (img.empty()) {
printf("无法读取图像!\n");
return -1;
}
imshow("显示窗口", img); // 显示图像
waitKey(0); // 等待按键(0 表示无限等待)
return 0;
}
waitKey() 是必须的,否则窗口会一闪而过。waitKey() 会触发窗口事件处理(刷新显示、响应鼠标等)。
示例 2:手动创建可缩放窗口
cpp
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat img = imread("test.jpg");
if (img.empty()) return -1;
namedWindow("可调整大小窗口", WINDOW_NORMAL); // 可缩放窗口
imshow("可调整大小窗口", img);
waitKey(0);
return 0;
}
示例 3:显示灰度图
cpp
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat gray = imread("test.jpg", IMREAD_GRAYSCALE); // 灰度读取
imshow("灰度图", gray);
waitKey(0);
return 0;
}
示例 4:显示处理过程中的多张图像
cpp
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat img = imread("test.jpg");
if (img.empty()) return -1;
Mat gray, edges;
cvtColor(img, gray, COLOR_BGR2GRAY);
Canny(gray, edges, 100, 200);
imshow("原图", img);
imshow("灰度图", gray);
imshow("边缘检测", edges);
waitKey(0);
return 0;
}
示例 5:实时显示视频帧(如摄像头)
cpp
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
VideoCapture cap(0); // 打开摄像头
if (!cap.isOpened()) {
printf("无法打开摄像头!\n");
return -1;
}
while (true)
{
Mat frame;
cap >> frame;
if (frame.empty()) break;
imshow("摄像头实时画面", frame);
// 按下 ESC 键退出
if (waitKey(30) == 27) break;
}
return 0;
}
示例6:在窗口上实时更新图像
cpp
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat img = imread("test.jpg");
if (img.empty()) return -1;
namedWindow("动态显示", WINDOW_AUTOSIZE);
for (int i = 0; i < 100; i++)
{
Mat bright;
img.convertTo(bright, -1, 1, i - 50); // 动态调节亮度
imshow("动态显示", bright);
if (waitKey(30) == 27) break; // ESC 退出
}
return 0;
}
三、鼠标事件的使用
OpenCV 的鼠标事件(Mouse Events)是图像交互中非常实用的一部分。通过它,你可以在显示窗口中响应鼠标点击、拖拽、移动等操作,从而实现图像标注、ROI选区、目标跟踪等功能。
函数原型:
cpp
void cv::setMouseCallback(
const std::string& winname,
cv::MouseCallback onMouse,
void* userdata = nullptr
);
参数说明:

回调函数类型定义:
cpp
typedef void (*MouseCallback)(
int event, // 鼠标事件类型
int x, // 鼠标x坐标
int y, // 鼠标y坐标
int flags, // 组合键标志(如Ctrl/Shift等)
void* userdata // 用户数据指针
);
常用鼠标事件类型(event):

组合键标志(flags):

示例代码
打印鼠标坐标:
cpp
#include <opencv2/opencv.hpp>
using namespace cv;
// 鼠标回调函数
void onMouse(int event, int x, int y, int flags, void* userdata)
{
if (event == EVENT_MOUSEMOVE)
{
printf("鼠标移动到 (%d, %d)\n", x, y);
}
else if (event == EVENT_LBUTTONDOWN)
{
printf("左键按下: (%d, %d)\n", x, y);
}
else if (event == EVENT_RBUTTONDOWN)
{
printf("右键按下: (%d, %d)\n", x, y);
}
}
int main()
{
Mat img = Mat::zeros(400, 600, CV_8UC3);
namedWindow("鼠标演示", WINDOW_AUTOSIZE);
// 绑定鼠标事件
setMouseCallback("鼠标演示", onMouse, nullptr);
imshow("鼠标演示", img);
waitKey(0);
return 0;
}
鼠标绘制矩形(ROI选择):
cpp
#include <opencv2/opencv.hpp>
using namespace cv;
struct RectData {
Point start, end;
bool drawing = false;
};
void onMouse(int event, int x, int y, int flags, void* userdata)
{
RectData* data = reinterpret_cast<RectData*>(userdata);
if (event == EVENT_LBUTTONDOWN) {
data->drawing = true;
data->start = Point(x, y);
}
else if (event == EVENT_MOUSEMOVE && data->drawing) {
data->end = Point(x, y);
}
else if (event == EVENT_LBUTTONUP) {
data->drawing = false;
data->end = Point(x, y);
printf("选取区域:(%d,%d) - (%d,%d)\n", data->start.x, data->start.y, data->end.x, data->end.y);
}
}
int main()
{
Mat img = Mat::zeros(400, 600, CV_8UC3);
Mat temp;
RectData data;
namedWindow("ROI绘制", WINDOW_AUTOSIZE);
setMouseCallback("ROI绘制", onMouse, &data);
while (true)
{
img.copyTo(temp);
if (data.drawing)
rectangle(temp, data.start, data.end, Scalar(0, 255, 0), 2);
imshow("ROI绘制", temp);
if (waitKey(30) == 27) break; // 按ESC退出
}
return 0;
}
四、键盘事件的使用
在 OpenCV 中确实有按键事件(Keyboard Events),不过它不像鼠标事件那样需要回调函数,而是通过函数 cv::waitKey() 实现的。
核心函数:cv::waitKey()
函数原型:
cpp
int cv::waitKey(int delay = 0);
参数说明:

返回值:
- 如果用户按下某个键,则 waitKey() 返回该键的 ASCII 码值。
- 如果在 delay 毫秒内未检测到按键,则返回 -1。
原理说明
cv::waitKey() 其实有两个功能:
- 处理窗口刷新事件(否则 imshow() 的内容不会更新)
- 监听键盘输入事件
也就是说,不调用 waitKey(),图像窗口不会响应任何事件,包括显示更新和鼠标交互!
基本使用示例
示例 1:等待按键退出
cpp
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat img = imread("test.jpg");
imshow("图像窗口", img);
// 等待任意按键
waitKey(0);
return 0;
}
当你按任意键时,程序才会退出。
示例 2:定时刷新 + 检测按键
cpp
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
VideoCapture cap(0);
if (!cap.isOpened()) return -1;
while (true)
{
Mat frame;
cap >> frame;
imshow("摄像头", frame);
int key = waitKey(30); // 等待30ms
if (key == 27) break; // ESC退出
}
return 0;
}
每隔 30ms 刷新一次图像,并检查用户是否按下 ESC 键。这是典型的 OpenCV 实时显示循环写法。
常见按键值(ASCII码)

示例:按键控制显示行为
cpp
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat img = imread("test.jpg");
if (img.empty()) return -1;
imshow("按键控制", img);
while (true)
{
int key = waitKey(0);
if (key == 27) // ESC
break;
else if (key == 's' || key == 'S')
{
imwrite("output.jpg", img);
printf("图片已保存!\n");
}
else if (key == 'g' || key == 'G')
{
Mat gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
imshow("按键控制", gray);
printf("切换为灰度图\n");
}
}
return 0;
}
五、滑动条的使用
在 OpenCV 中,滑动条其实就是一个 GUI 控件,可以用来实时调节参数(例如阈值、亮度、对比度、滤波半径等),而"滚动条"和"开关"在 OpenCV 中是通过滑动条或按钮模拟实现的。
函数原型:
cpp
int cv::createTrackbar(
const std::string &trackbarname,
const std::string &winname,
int *value,
int count,
TrackbarCallback onChange = 0,
void *userdata = 0
);
参数说明:

回调函数类型:
cpp
typedef void (*TrackbarCallback)(int pos, void* userdata);
- pos:当前滑动条位置
- userdata:用户自定义数据
滑动条基本示例:
cpp
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void onTrack(int pos, void* userdata)
{
Mat* img = reinterpret_cast<Mat*>(userdata);
Mat dst;
img->convertTo(dst, -1, 1, pos - 50); // 调整亮度
imshow("滑动条示例", dst);
}
int main()
{
Mat img = imread("test.jpg");
if (img.empty()) return -1;
namedWindow("滑动条示例", WINDOW_AUTOSIZE);
int slider = 50; // 初始值
createTrackbar("Brightness", "滑动条示例", &slider, 100, onTrack, &img);
imshow("滑动条示例", img);
waitKey(0);
return 0;
}