目录
1.实验原理
2.实验代码
3.运行结果
1.实验原理
在Opencv中,我们可以综合利用坐标变换与Rect区域提取来实现单窗口显示多幅图像。首先根据输入图像个数与尺寸确定输入源图像小窗口的构成形态,然后设定每个图像小窗口的具体构成,包括边界、间隙等,最后根据小窗口确定输出图像的尺寸,利用缩放图像函数resize进行图像缩放,完成单窗口下多幅图像的显示。
Resizes an image.
void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR );
参数说明:
src:输入图像,通常为cv::Mat类型。
dst:输出图像,与输入图像具有相同的类型。
size:目标图像的尺寸,表示为(width, height)。
fx:沿水平轴的缩放因子,默认为0,表示不进行水平缩放。如果 fx 大于 1,则图像会被放大;如果小于 1,则图像会被缩小。
fy:沿垂直轴的缩放因子,默认为0,表示不进行垂直缩放。
interpolation:插值方法,有以下几种可选:默认方法是 INTER_LINEAR,即双线性插值。
cv::INTER_NEAREST:最近邻插值,速度最快,但质量最差。
cv::INTER_LINEAR:线性插值,速度较快,质量较好。
cv::INTER_AREA:区域插值,适用于图像缩小,速度较慢,质量最好。
cv::INTER_CUBIC:三次样条插值,速度适中,质量较好。
cv::INTER_LANCZOS4:Lanczos插值,速度适中,质量较好。
2.实验代码
// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <opencv2/highgui/highgui_c.h>
#include <opencv2\opencv.hpp>
//#pragma comment(lib, "opencv_world450d.lib") //引用引入库
using namespace cv;
#include<iostream>
using namespace std;
void showManyImages(const vector<Mat>&srcImages, Size imageSize)
{
int nNumImages = srcImages.size();
Size nSizeWindows;
if (nNumImages > 12)
{
cout << "no more tha 12 images" << endl;
return;
}
//根据图片序列数量来确定分割小窗口的形态
switch (nNumImages){
case 1:nSizeWindows = Size(1, 1); break;
case 2:nSizeWindows = Size(2, 1); break;
case 3:
case 4:nSizeWindows = Size(2, 2); break;
case 5:
case 6:nSizeWindows = Size(3, 2); break;
case 7:
case 8:nSizeWindows = Size(4, 2); break;
case 9:nSizeWindows = Size(3, 3); break;
default:nSizeWindows = Size(4, 3);
}
//设置小图像尺寸,间隙,边界
int nShowImageSize = 200; //图片宽度 高度都为200
int nSplitLineSize = 15; //图片之间间隙
int nAroundLineSize = 50; //图片与窗口之间间隙
//创建输出图像,图像大小根据输入源来确定
const int imagesWidth = nShowImageSize*nSizeWindows.width + nAroundLineSize +(nSizeWindows.width - 1)*nSplitLineSize; //新窗口宽度
const int imagesHeight = nShowImageSize*nSizeWindows.height + nAroundLineSize +(nSizeWindows.height - 1)*nSplitLineSize;//新窗口高度
cout << imagesWidth << " " << imagesHeight << endl;
Mat showWindowsImages(imagesWidth, imagesHeight, CV_8UC3, Scalar(0, 0, 0));
//提取对应小图像的左上角坐标x,y
int posX = (showWindowsImages.cols - (nShowImageSize*nSizeWindows.width +(nSizeWindows.width - 1)*nSplitLineSize)) / 2;//左上角第一张图片的x坐标 左右方向
int posY = (showWindowsImages.rows - (nShowImageSize*nSizeWindows.height +(nSizeWindows.height - 1)*nSplitLineSize)) / 2;//左上角第一张图片的y坐标 上下方向
cout << posX << " " << posY << endl;
int tempPosX = posX;
int tempPosY = posY;
//将每一幅小图像整合成一幅大图像
for (int i = 0; i < nNumImages; i++)
{
//小图像坐标转换
if ((i%nSizeWindows.width == 0) && (tempPosX != posX))
{
//图像根据 nSizeWindows = Size(3, 2) 布局大小,对新的一行数据点 左上角左边进行更新
tempPosX = posX;
tempPosY += (nSplitLineSize + nShowImageSize);
}
//利用Rect区域将小图像置于大图像的相应区域
Mat tempImage = showWindowsImages(Rect(tempPosX, tempPosY, nShowImageSize, nShowImageSize));
resize(srcImages[i], tempImage,Size(nShowImageSize, nShowImageSize));//利用resize函数实现图像缩放
tempPosX += (nSplitLineSize + nShowImageSize);
}//for
imshow("单窗口显示多图片", showWindowsImages);
}
int main()
{
//图像源输入
vector<Mat>srcImage(9);
srcImage[0] = imread("010.jpg");
srcImage[1] = imread("010.jpg");
srcImage[2] = imread("010.jpg");
srcImage[3] = imread("020.jpg");
srcImage[4] = imread("020.jpg");
srcImage[5] = imread("020.jpg");
srcImage[6] = imread("030.jpg");//安乐
srcImage[7] = imread("030.jpg");
srcImage[8] = imread("030.jpg");
//判断当前vector读入的正确性
for (int i = 0; i < srcImage.size(); i++)
{
if (srcImage[i].empty())
{
cout << "read error" << endl;
return -1;
}
}
//调用 单窗口显示图像
showManyImages(srcImage, Size(147, 118));
waitKey(0);
system("pause");
return 0;
}
3.运行结果
注意根据vector<Mat>srcImage(9);输入大小不同,将会不同布局