【c++】opencv实现在一个窗口中显示多张图片,全部代码和效果图在文章最后

前言

在Matlab中,可以很简单的实现在一个窗口中显示多张图像,在python的matplotlib库中,也有subplot方法能够简单实现该功能,opencv中并没有提供这个功能,在c++中需要手动实现,但好在c++具有充分的灵活性,可以自己写函数实现自己所期望的效果的功能。

思路

将多张图片的Mat的数据存放在vector容器中,然后构造一个新的Mat去集成这多张图片,最后将这个集成Mat展示出来即可。

1.函数定义
void imshowMany(string windowName, vector<Mat> images,int imgCols);

考虑到尽量和imshow函数具有相同的效果,传入的参数包括了窗口名,图像列表,一行显示多少张图片

2.修改图像为统一大小,方便显示
Size_(_Tp _width, _Tp _height);

注意:Size(width,height),即第一个参数是宽,第二个参数是高,这个和Mat的初始化过程是相反的(Mat的第一个参数是行,第二个参数是列)

此处为了简便,只定义了图片长和宽共同的最大像素,如有需要可以分别定义大小。

const int MAX_PIXEL = 400;//定义长度/宽度的最大像素值

定义每张图片之间的间隔

const int IMAGE_SPACE = 10;//定义图像之间的间距

定义一个用来接收修改后的图像的vector容器和标准化后的图像的大小

vector<Mat> imgsDst(images.size());
Size imgStdSize(MAX_PIXEL, MAX_PIXEL);

遍历每张图片,分别计算出图像的宽和高需要到达指定像素时的变化因子,然后用这两个因子调用resize方法标准化图像

for (int i = 0; i < images.size(); i++) {
	
		double widthProp = images[i].size().width < MAX_PIXEL ? (double)images[i].size().width / MAX_PIXEL : MAX_PIXEL / (double)images[i].size().width;
		double heightProp = images[i].size().height < MAX_PIXEL ? (double)images[i].size().height / MAX_PIXEL : MAX_PIXEL / (double)images[i].size().height;
		
		resize(images[i], imgsDst[i], imgStdSize, widthProp, heightProp,INTER_LINEAR);
	}

resize(input,output, fx,fy,interpolation):第一个参数表示输入图像,第二个参数表示输入图像,第三个参数是x轴变化因子(width),第四个参数是y轴变化因子(height),最后一个参数是插值方式(INTER_LINEAR表示线性插值)

3.构造集成Mat
Point2i location(0, 0);//初始坐标
	//构造窗口大小
	Mat imgWindow((imgStdSize.height + IMAGE_SPACE) * ((images.size() - 1) / imgCols + 1) - IMAGE_SPACE , (imgStdSize.width + IMAGE_SPACE) * imgCols - IMAGE_SPACE,images[0].type());
	for (int i = 0; i < images.size(); i++) {
		location.x = (i % imgCols) * imgStdSize.width + (i % imgCols)* IMAGE_SPACE;
		location.y = (i / imgCols) * imgStdSize.height + (i / imgCols) * IMAGE_SPACE;
		imgsDst[i].copyTo(imgWindow(Rect(location, imgStdSize)));
	}

先定义初始坐标,然后构造集成Mat的大小,最后将图像集合按规定的模式对集成Mat的值进行拷贝即可

4.显示结果
imshow(windowName, imgWindow);

代码

#include<opencv2/opencv.hpp>
#include<iostream>
#include <string>
#include <vector>
using namespace cv;
using namespace std;

const int MAX_PIXEL = 400;//定义长度/宽度的最大像素值
const int IMAGE_SPACE = 10;//定义图像之间的间距
void imshowMany(string windowName , vector<Mat> images,int imgCols) {
	//将图像修改为统一大小
	vector<Mat> imgsDst(images.size());
	Size imgStdSize(MAX_PIXEL, MAX_PIXEL);
	for (int i = 0; i < images.size(); i++) {
	
		double widthProp = images[i].size().width < MAX_PIXEL ? (double)images[i].size().width / MAX_PIXEL : MAX_PIXEL / (double)images[i].size().width;
		double heightProp = images[i].size().height < MAX_PIXEL ? (double)images[i].size().height / MAX_PIXEL : MAX_PIXEL / (double)images[i].size().height;
		
		resize(images[i], imgsDst[i], imgStdSize, widthProp, heightProp,INTER_NEAREST);
	}

	Point2i location(0, 0);//初始坐标
	//构造窗口大小
	Mat imgWindow((imgStdSize.height + IMAGE_SPACE) * ((images.size() - 1) / imgCols + 1) - IMAGE_SPACE , (imgStdSize.width + IMAGE_SPACE) * imgCols - IMAGE_SPACE,images[0].type());
	for (int i = 0; i < images.size(); i++) {
		location.x = (i % imgCols) * imgStdSize.width + (i % imgCols)* IMAGE_SPACE;
		location.y = (i / imgCols) * imgStdSize.height + (i / imgCols) * IMAGE_SPACE;
		imgsDst[i].copyTo(imgWindow(Rect(location, imgStdSize)));
	}
	
	//显示集合图像
	imshow(windowName, imgWindow);

}
int main() {
	String str = "timg.jpg"; // 注意文件路径和你所对应的图片
	Mat img1 = imread(str);
	Mat img2 = imread(str);
	Mat img3 = imread(str);
	Mat img4 = imread(str);
	vector<Mat> imgs{ img1,img2,img3,img4 };
	imshowMany("test",imgs,2);
	waitKey(0);
	return 0;
}

效果图

opencv在同一张图持续更新 opencv显示多张图片_opencv在同一张图持续更新