OpenCV4入门教程016:单窗口显示多幅图像

索引地址:系列索引

imshow行数一次只能显示一个Mat对象,一个Mat对象对应一张图片,如果需要显示多张图片,就需要一些操作。最常用的操作是将图片缩小然后利用roi原理移至对应的位置,这样就是在一个Mat中有多个Mat数据,再用imshow显示这一个Mat。

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;

void showManyImages(const std::vector<cv::Mat> &srcImages,
cv::Size imgSize)
{
int nNumImages = srcImages.size();
cv::Size nSizeWindows;
if (nNumImages > 12)
{
std::cout << " Not more than 12 images!" << std::endl;
return;
}
// 根据图片序列数量来确定分割小窗口形态
switch (nNumImages)
{
case 1:
nSizeWindows = cv::Size(1, 1);
break;
case 2:
nSizeWindows = cv::Size(2, 1);
break;
case 3:
case 4:
nSizeWindows = cv::Size(2, 2);
break;
case 5:
case 6:
nSizeWindows = cv::Size(3, 2);
break;
case 7:
case 8:
nSizeWindows = cv::Size(4, 2);
break;
case 9:
nSizeWindows = cv::Size(3, 3);
break;
default:
nSizeWindows = cv::Size(4, 3);
break;
}
// 设置小图像尺寸,间隙,边界
int nShowImageSize = 200;
int nSplitLineSize = 15;
int nAroundLineSize = 50;
// 创建输出图像,图像大小根据输入源确定
const int imagesHeight = nShowImageSize * nSizeWindows.width +
nAroundLineSize + (nSizeWindows.width - 1) * nSplitLineSize;
const int imagesWidth = nShowImageSize * nSizeWindows.height +
nAroundLineSize + (nSizeWindows.height - 1) * nSplitLineSize;
std::cout << imagesWidth << " " << imagesHeight << std::endl;
cv::Mat showWindowImages(imagesWidth, imagesHeight,
CV_8UC3, cv::Scalar(0, 0, 0));
// 提取对应小图像的左上角坐标X,Y
int posX = (showWindowImages.cols - (nShowImageSize *
nSizeWindows.width +
(nSizeWindows.width - 1) *
nSplitLineSize)) /
2;
int posY = (showWindowImages.rows - (nShowImageSize *
nSizeWindows.height +
(nSizeWindows.height - 1) *
nSplitLineSize)) /
2;
std::cout << posX << " " << posY << std::endl;
int tempPosX = posX;
int tempPosY = posY;
// 将每一小幅图像整合大图像
for (int i = 0; i < nNumImages; i++)
{
// 小图像坐标转换
if ((i % nSizeWindows.width == 0) && (tempPosX != posX))
{
tempPosX = posX;
tempPosY += (nSplitLineSize + nShowImageSize);
}
// 利用Rect区域将小图像置于大图像相应区域
cv::Mat tempImage = showWindowImages(cv::Rect(tempPosX,
tempPosY, nShowImageSize, nShowImageSize));
// 利用resize函数实现图像缩放
resize(srcImages[i], tempImage,
cv::Size(nShowImageSize, nShowImageSize));
tempPosX += (nSplitLineSize + nShowImageSize);
}
cv::imshow("show Images", showWindowImages);
imwrite("result.jpg",showWindowImages);
}

int main()
{
// 图像源输入
std::vector<cv::Mat> srcImages(9);
srcImages[0] = cv::imread("lenna.jpg");
srcImages[1] = cv::imread("lenna.jpg");
srcImages[2] = cv::imread("lenna.jpg");
srcImages[3] = cv::imread("lenna.jpg");
srcImages[4] = cv::imread("lenna.jpg");
srcImages[5] = cv::imread("lenna.jpg");
srcImages[6] = cv::imread("lenna.jpg");
srcImages[7] = cv::imread("lenna.jpg");
srcImages[8] = cv::imread("lenna.jpg");
// 判断当前vector读入的正确性
for (int i = 0; i < srcImages.size(); i++)
{
if (!srcImages[i].data)
{
std::cout << "read error!" << std::endl;
return -1;
}
}
// 调用单窗口显示图像
showManyImages(srcImages, cv::Size(512, 400));
cv::waitKey(0);
return 0;
}

运行结果:

multi


OpenCV4入门教程016:单窗口显示多幅图像
https://blog.jackeylea.com/opencv/opencv-display-multiple-images-in-single-window/
作者
JackeyLea
发布于
2020年11月10日
许可协议