C++ OpenCV生成蒙太奇圖像的示例詳解
前言
本文將使用OpenCV C++ 生成蒙太奇圖像。
一、輸入模板圖像

原圖如圖所示。我們將對此圖生成蒙太奇圖像。
Mat src = imread("Taylor.jpg");
if (src.empty())
{
cout << "No image!" << endl;
system("pause");
return 0;
}
resize(src, src, Size(step_x*30, step_y*30), 1, 1, INTER_CUBIC);
這里的step_x,step_y表示素材圖像尺寸。我們要把模板圖像resize成 Size(step_x 30, step_y*30)尺寸,將模板圖像分割成30x30個block,即使用30x30張素材圖像來生成我們的蒙太奇圖像。
二、讀取素材圖像

所有素材圖像。
//獲取文件夾下所有圖像路徑
int getImagePathList(string folder, vector<String> &imagePathList)
{
glob(folder, imagePathList);
return 0;
}
我們定義getImagePathList函數(shù)獲取文件夾下所有圖像的路徑。
vector<Mat>images;
string filename = "images/";
cout << "loading..." << endl;
vector<String> imagePathList;
getImagePathList(filename, imagePathList);
for (int i = 0; i < imagePathList.size(); i++)
{
Mat img = cv::imread(imagePathList[i]);
resize(img, img, Size(step_x, step_y), 1, 1, INTER_AREA);
images.push_back(img);
}
cout << "done!" << endl;
我們將讀取進來的所有素材圖像都resize成 Size(step_x, step_y)大小,并把它們都push_back到images容器內(nèi),以便后續(xù)使用。
三、生成蒙太奇模板
int rows = src.rows;
int cols = src.cols;
//height:表示生成的蒙太奇圖像需要多少張素材圖像填充rows
//width:表示生成的蒙太奇圖像需要多少張素材圖像填充cols
int height = rows / step_y, width = cols / step_x;
Mat temp;
Mat dst = Mat(src.size(), CV_8UC3, Scalar(255, 255, 255));
for (int i = 0; i < height; ++i)
{
for (int j = 0; j < width; ++j)
{
//index表示當(dāng)前素材圖像的索引
int index = i * width + j;
//將當(dāng)前素材圖像拷貝到temp零時變量
images[index].copyTo(temp);
//將temp圖像賦值給需要生成的蒙太奇圖像對應(yīng)區(qū)域
temp = dst(Rect(j * step_x, i * step_y, step_x, step_y));
}
}
imshow("dst", dst);
通過兩個for循環(huán)就可以遍歷到每個蒙版區(qū)域。這個類似于遍歷圖像的所有像素,只不過我們把步長加大了而已。整個代碼的核心就是以下這兩句。
//將當(dāng)前素材圖像拷貝到temp零時變量 images[index].copyTo(temp); //將temp圖像賦值給需要生成的蒙太奇圖像對應(yīng)區(qū)域 temp = dst(Rect(j * step_x, i * step_y, step_x, step_y));

將所有的素材圖像copy到指定區(qū)域就可以生成蒙版圖像啦。接下來我們就得對這個蒙版圖像做像素處理了。
四、生成蒙太奇圖像
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < cols; ++j)
{
//像素RGB值修改
dst.at<Vec3b>(i, j)[0] = 0.312*dst.at<Vec3b>(i, j)[0] + 0.698*src.at<Vec3b>(i, j)[0];
dst.at<Vec3b>(i, j)[1] = 0.312*dst.at<Vec3b>(i, j)[1] + 0.698*src.at<Vec3b>(i, j)[1];
dst.at<Vec3b>(i, j)[2] = 0.312*dst.at<Vec3b>(i, j)[2] + 0.698*src.at<Vec3b>(i, j)[2];
}
}
imshow("蒙太奇圖像", dst);
我們通過遍歷模板圖像所有像素,并改變它們的權(quán)值,就可以得到蒙太奇圖像啦。

這就是我們生成的蒙太奇圖像
五、源碼
#include <iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
//素材圖像尺寸
const int step_x = 20;
const int step_y = 20;
//獲取文件夾下所有圖像路徑
int getImagePathList(string folder, vector<String> &imagePathList)
{
glob(folder, imagePathList);
return 0;
}
int main()
{
Mat src = imread("Taylor.jpg");
if (src.empty())
{
cout << "No image!" << endl;
system("pause");
return 0;
}
resize(src, src, Size(step_x*30, step_y*30), 1, 1, INTER_CUBIC);
vector<Mat>images;
string filename = "images/";
cout << "loading..." << endl;
vector<String> imagePathList;
getImagePathList(filename, imagePathList);
for (int i = 0; i < imagePathList.size(); i++)
{
Mat img = cv::imread(imagePathList[i]);
resize(img, img, Size(step_x, step_y), 1, 1, INTER_AREA);
images.push_back(img);
}
cout << "done!" << endl;
int rows = src.rows;
int cols = src.cols;
//height:表示生成的蒙太奇圖像需要多少張素材圖像填充rows
//width:表示生成的蒙太奇圖像需要多少張素材圖像填充cols
int height = rows / step_y, width = cols / step_x;
Mat temp;
Mat dst = Mat(src.size(), CV_8UC3, Scalar(255, 255, 255));
for (int i = 0; i < height; ++i)
{
for (int j = 0; j < width; ++j)
{
//index表示當(dāng)前素材圖像的索引
int index = i * width + j;
//將當(dāng)前素材圖像拷貝到temp零時變量
images[index].copyTo(temp);
//將temp圖像賦值給需要生成的蒙太奇圖像對應(yīng)區(qū)域
temp = dst(Rect(j * step_x, i * step_y, step_x, step_y));
}
}
imshow("dst", dst);
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < cols; ++j)
{
//像素RGB值修改
dst.at<Vec3b>(i, j)[0] = 0.312*dst.at<Vec3b>(i, j)[0] + 0.698*src.at<Vec3b>(i, j)[0];
dst.at<Vec3b>(i, j)[1] = 0.312*dst.at<Vec3b>(i, j)[1] + 0.698*src.at<Vec3b>(i, j)[1];
dst.at<Vec3b>(i, j)[2] = 0.312*dst.at<Vec3b>(i, j)[2] + 0.698*src.at<Vec3b>(i, j)[2];
}
}
imshow("蒙太奇圖像", dst);
waitKey(0);
system("pause");
return 0;
}
總結(jié)
本文使用OpenCV C++生成蒙太奇圖像,關(guān)鍵步驟有以下幾點。
1、將你需要生成的蒙太奇圖像模板resize成合適大小,使其恰好能夠被素材圖像填充。
2、載入素材圖像。
3、使用素材圖像去填充蒙版圖。核心就是上面的兩個for循環(huán)。
4、將蒙版與模板圖像進行融合,改變其像素權(quán)值就可以生成蒙太奇圖像了。
本文使用較為簡單,也比較容易理解的程序生成蒙太奇圖像。網(wǎng)上也有許多是使用直方圖匹配——將模板圖像分割成不等分區(qū)域,然后使用素材庫中的圖像與這些區(qū)域一一進行直方圖匹配,找到最匹配的那張圖像填充該區(qū)域。有興趣的小伙伴可以嘗試一下這種方法!!
以上就是C++ OpenCV生成蒙太奇圖像的示例詳解的詳細內(nèi)容,更多關(guān)于C++ OpenCV蒙太奇圖像的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
解析c中stdout與stderr容易忽視的一些細節(jié)
本篇文章是對在c語言中stdout與stderr容易忽視的一些細節(jié)進行了詳細的分析介紹,需要的朋友參考下2013-05-05
OpenCV實現(xiàn)繞圖片中任意角度旋轉(zhuǎn)任意角度
這篇文章主要為大家詳細介紹了在圖片不被裁剪時,opencv如何實現(xiàn)繞圖片中任意點旋轉(zhuǎn)任意角度,文中的示例代碼講解詳細,需要的可以參考一下2022-09-09
基于Matlab實現(xiàn)多目標(biāo)粘液霉菌算法的示例代碼
多目標(biāo)粘液霉菌算法(MOSMA),這是最近開發(fā)的粘液霉菌算法(SMA)的多目標(biāo)變體,用于處理工業(yè)中的多目標(biāo)優(yōu)化問題。本文將用Matlab實現(xiàn)這一算法,需要的可以參考一下2022-05-05
C語言中關(guān)于動態(tài)內(nèi)存分配的詳解
動態(tài)內(nèi)存是指在堆上分配的內(nèi)存,而靜態(tài)內(nèi)存是指在棧上分配的內(nèi)存。棧上分配的內(nèi)存是由系統(tǒng)分配和釋放的,空間有限,在復(fù)合語句或函數(shù)運行結(jié)束后就會被系統(tǒng)自動釋放而堆上分配的內(nèi)存則不會有這個問題。2021-09-09

