1. 高级显示技巧
图像缩放显示
cpp
// 适应屏幕显示
void showImageFit(const Mat& img, const std::string& winname, double max_width = 1200) {
double scale = 1.0;
if (img.cols > max_width) {
scale = max_width / img.cols;
}
Mat resized;
resize(img, resized, Size(), scale, scale);
imshow(winname, resized);
}
cpp
// 保持宽高比显示
void showImageKeepRatio(const Mat& img, const std::string& winname, int max_dim = 800) {
double scale = 1.0;
int max_side = std::max(img.cols, img.rows);
if (max_side > max_dim) {
scale = (double)max_dim / max_side;
}
Mat resized;
resize(img, resized, Size(), scale, scale, INTER_LANCZOS4);
imshow(winname, resized);
}
多窗口管理
cpp
// 窗口管理器类
class WindowManager {
private:
std::vector<std::string> window_names;
public:
void createWindow(const std::string& name, int flags = WINDOW_AUTOSIZE) {
namedWindow(name, flags);
window_names.push_back(name);
}
void showImage(const std::string& name, const Mat& img) {
imshow(name, img);
}
void closeAll() {
for (const auto& name : window_names) {
destroyWindow(name);
}
window_names.clear();
}
void waitAndClose() {
waitKey(0);
closeAll();
}
};
// 使用示例
WindowManager wm;
wm.createWindow("窗口1");
wm.createWindow("窗口2", WINDOW_NORMAL);
wm.showImage("窗口1", image1);
wm.showImage("窗口2", image2);
wm.waitAndClose();
图像比较显示
cpp
// 并排比较
void compareImagesSideBySide(const Mat& img1, const Mat& img2, const std::string& title) {
Mat combined;
if (img1.size() == img2.size()) {
hconcat(img1, img2, combined);
} else {
// 调整到相同大小
Mat resized2;
resize(img2, resized2, img1.size());
hconcat(img1, resized2, combined);
}
// 添加分割线
line(combined, Point(img1.cols, 0), Point(img1.cols, img1.rows), Scalar(0,255,0), 2);
imshow(title, combined);
}
2. 常见问题解决
中文路径问题
cpp
// 解决中文路径读取问题
#ifdef _WIN32
Mat readImageChinese(const std::string& filename) {
std::ifstream file(filename, std::ios::binary);
if (!file) return Mat();
file.seekg(0, std::ios::end);
int length = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<char> buffer(length);
file.read(buffer.data(), length);
return imdecode(Mat(1, length, CV_8U, buffer.data()), IMREAD_COLOR);
}
#else
// Linux/Mac 通常直接支持
#endif
大图像显示优化
cpp
// 超大图像分块显示
void showLargeImage(const Mat& large_img, const std::string& winname) {
if (large_img.cols <= 1920 && large_img.rows <= 1080) {
imshow(winname, large_img);
return;
}
// 创建滑动窗口
namedWindow(winname, WINDOW_NORMAL);
resizeWindow(winname, 1200, 800);
// 实现滚动条回调(需要自定义实现)
// ...
}
内存管理
cpp
// 及时释放内存
void processAndShow() {
Mat img = imread("large_image.jpg");
if (img.empty()) return;
// 处理图像
Mat processed;
cvtColor(img, processed, COLOR_BGR2GRAY);
// 显示后立即释放
imshow("结果", processed);
waitKey(0);
// 手动释放内存(可选,析构函数会自动调用)
img.release();
processed.release();
destroyAllWindows();
}
3. 完整示例
cpp
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
using namespace cv;
using namespace std;
void mouseHandler(int event, int x, int y, int flags, void* userdata) {
if (event == EVENT_LBUTTONDOWN) {
cout << "左键点击: (" << x << ", " << y << ")" << endl;
} else if (event == EVENT_RBUTTONDOWN) {
cout << "右键点击: (" << x << ", " << y << ")" << endl;
}
}
int main() {
// 读取图像
Mat image = imread("test.jpg", IMREAD_COLOR);
if (image.empty()) {
cout << "无法读取图像文件!" << endl;
return -1;
}
// 显示基本信息
cout << "图像信息:" << endl;
cout << " 尺寸: " << image.cols << " x " << image.rows << endl;
cout << " 通道数: " << image.channels() << endl;
cout << " 数据类型: " << image.type() << endl;
// 创建窗口
namedWindow("原始图像", WINDOW_AUTOSIZE);
namedWindow("灰度图像", WINDOW_NORMAL);
// 设置窗口位置
moveWindow("原始图像", 100, 100);
moveWindow("灰度图像", image.cols + 120, 100);
// 处理图像
Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
// 显示图像
imshow("原始图像", image);
imshow("灰度图像", gray);
// 设置鼠标回调
setMouseCallback("原始图像", mouseHandler, &image);
// 键盘交互
cout << "按 ESC 退出,按 's' 保存灰度图" << endl;
while (true) {
int key = waitKey(0);
if (key == 27) { // ESC
break;
} else if (key == 's') {
imwrite("gray_image.jpg", gray);
cout << "灰度图已保存" << endl;
} else if (key == 'i') {
cout << "图像信息: " << image.cols << "x" << image.rows << endl;
}
}
// 清理资源
destroyAllWindows();
return 0;
}
这个完整的图像读取和显示框架包含了错误处理、交互功能和最佳实践,可以作为开发的基础模板。