#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <list>
#include <string>
#include <cstring>
#include <vector>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
void mergeDiffPic(vector<string> pic_list, int pic_cols_rows, string output_file, bool horizontal = true, bool draw_rect = false)
{
int pic_cols = 0;
int pic_rows = 0;
int max_cols=0;
int max_rows=0;
int size_cols=0;
int size_rows=0;
vector<int> tmp_cols;
vector<int> tmp_rows;
//获取图片数量
int pic_num = pic_list.size();
vector<Mat>input(pic_num);
Mat merge;
for(int i = 0; i < pic_num; i++){
input[i] = imread(pic_list[i]);
//draw_rect为true,画矩形
if(draw_rect){
Rect rect = Rect(0, 0, input[i].cols, input[i].rows);
rectangle(input[i], rect, Scalar(0, 0, 255));
}
}
//按水平方向合成
if (horizontal){
pic_cols = pic_cols_rows;
pic_rows = pic_num / pic_cols;
//生成的图片行数
if(pic_num % pic_cols != 0) pic_rows += 1;
int i = 0;
int j = 0;
for(i = 0; i < pic_rows; i++) {
max_cols = 0;
//保存每行图片的最大高度,方便后面确定图片的摆放位置
tmp_rows.push_back(size_rows);
max_rows = 0;
for (j = 0; j < pic_cols; j++) {
if ((i * pic_cols + j) >= pic_num) break;
//保存每行图片的最大宽度,用于确定合成图的宽度
max_cols += input[i * pic_cols + j].cols;
max_rows = (max_rows > input[i * pic_cols + j].rows ? max_rows : input[i * pic_cols + j].rows * 7 / 6); // 按比例留1/6宽的空白在图片下方,用于备注
}
//合成图的宽度和高度
size_cols = (max_cols > size_cols ? max_cols : size_cols);
size_rows += max_rows;
if ((i * pic_cols + j) >= pic_num) break;
}
//创建size_cols×size_rows大小的空白图片,用于摆放小图
Size mergesize(size_cols, size_rows);
merge.create(mergesize, CV_MAKETYPE(input[0].depth(), 3));//rgb 3通道
merge = Scalar::all(192);
int fontFace = FONT_HERSHEY_SIMPLEX; // 字体
double fontScale = 0.80; //字体缩放比
int thickness = 1; // 粗细
int baseline = 0;
vector<Mat>temp(pic_num);
//摆放图片
for(i = 0; i < pic_rows; i++) {
int32 sum_cols = 0;
for(j = 0; j < pic_cols; j++) { //j为这一行第几张照片
if((i * pic_cols + j) >= pic_num) break;
//确定第(i * pic_cols + j)张图在merge上的位置
temp[i * pic_cols + j] = merge(Rect(sum_cols, tmp_rows[i], input[i * pic_cols + j].cols, input[i * pic_cols + j].rows));
//插入文字备注
string text = to_string(i) + "-" + to_string(j) + " " + "text will be here"; // 字符
Size textSize = getTextSize(text, fontFace, fontScale, thickness, &baseline);
baseline += thickness;
Point textOrg(sum_cols + (input[i * pic_cols + j].cols - textSize.width) / 2, (input[i * pic_cols + j].rows * 7 / 6) * (i + 1) - (input[i * pic_cols + j].rows / 6 - textSize.height) / 2); // 文字框位置 将以图片的高度决定位置 未来考虑所有图片按比例放大/缩小到一定高度使注释文字不会过大或者过小
putText(merge, text, textOrg, fontFace, fontScale, Scalar(0, 0, 255), thickness, 8);
//下一张图的起始位置(x坐标)
sum_cols += input[i * pic_cols + j].cols;
input[i * pic_cols + j].copyTo(temp[i * pic_cols + j]);
cout << text << endl;
cout << sum_cols + (input[i * pic_cols + j].cols - textSize.width) / 2 << " " << (input[i * pic_cols + j].rows * 7 / 6) * (i + 1) - (input[i * pic_cols + j].rows / 6 - textSize.height) / 2 << endl;
}
if ((i*pic_cols+j) >= pic_num) break;
}
}else{
pic_rows = pic_cols_rows;
pic_cols = pic_num / pic_rows;
if (pic_num % pic_rows != 0) pic_cols += 1;
int32 i = 0;
int32 j = 0;
for (i = 0; i < pic_cols; i++){
max_rows = 0;
tmp_cols.push_back(size_cols);
max_cols = 0;
for (j = 0; j < pic_rows; j++){
if ((i * pic_rows + j) >= pic_num) break;
max_rows += input[i * pic_rows + j].rows;
max_cols = (max_cols > input[i * pic_rows + j].cols ? max_cols : input[i * pic_rows + j].cols);
}
size_rows = (max_rows > size_rows ? max_rows : size_rows);
size_cols += max_cols;
if ((i * pic_rows + j) >= pic_num) break;
}
//std::cout<<size_cols<<std::endl;
//std::cout<<size_rows<<std::endl;
Size mergesize(size_cols, size_rows);
vector<Mat>temp(pic_num);
merge.create(mergesize, CV_MAKETYPE(input[0].depth(), 3));//rgb 3通道
merge = Scalar::all(0);
for (i = 0; i < pic_cols; i++){
int32 sum_rows = 0;
for (j = 0; j < pic_rows; j++){
if ((i * pic_rows + j) >= pic_num) break;
temp[i * pic_rows + j] = merge(Rect(tmp_cols[i], sum_rows, input[i * pic_rows + j].cols, input[i * pic_rows + j].rows));
sum_rows += input[i * pic_rows + j].rows;
input[i * pic_rows + j].copyTo(temp[i * pic_rows + j]);
}
if ((i * pic_rows + j) >= pic_num) break;
}
}
//显示图片
//imshow("merge", merge);
//保存图片
imwrite(output_file.c_str(), merge);
//waitKey(0);
}
int main()
{
vector<string> pic_list;
pic_list.push_back("test1.jpg");
pic_list.push_back("test2.jpg");
pic_list.push_back("test3.jpg");
pic_list.push_back("test4.jpg");
pic_list.push_back("test5.jpg");
pic_list.push_back("test6.jpg");
pic_list.push_back("test7.jpg");
mergeDiffPic(pic_list, 3, "merge.jpg", true, true);
return 0;
}
工作中遇上了需要在linux环境下将7张图片按顺序合并成一张图并且加文字注释的情况,倒腾了一番,结果还行
include估计有多余的,因为其他代码不方便发出来,供参考与学习,欢迎大佬帮忙优化
参考文章: