服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++ OpenCV生成蒙太奇图像的示例详解

C++ OpenCV生成蒙太奇图像的示例详解

2022-08-15 10:14Zero___Chen C/C++

图片的蒙太奇效果,一般称为马赛克图。由很多小图拼接成一个大图。这篇文章主要为大家介绍如何利用C++ OpenCV实现生成蒙太奇图像,感兴趣的可以了解一下

前言

本文将使用OpenCV C++ 生成蒙太奇图像。

一、输入模板图像

C++ OpenCV生成蒙太奇图像的示例详解

原图如图所示。我们将对此图生成蒙太奇图像。

?
1
2
3
4
5
6
7
Mat src = imread("Taylor.jpg");
if (src.empty())
{
    cout << "No image!" << endl;
    system("pause");
    return 0;
}
?
1
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张素材图像来生成我们的蒙太奇图像。

二、读取素材图像

C++ OpenCV生成蒙太奇图像的示例详解

所有素材图像。

?
1
2
3
4
5
6
//获取文件夹下所有图像路径
int getImagePathList(string folder, vector<String> &imagePathList)
{
    glob(folder, imagePathList);
    return 0;
}

我们定义getImagePathList函数获取文件夹下所有图像的路径。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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容器内,以便后续使用。

三、生成蒙太奇模板

?
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
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表示当前素材图像的索引
        int index = i * width + j;
 
        //将当前素材图像拷贝到temp零时变量
        images[index].copyTo(temp);
 
        //将temp图像赋值给需要生成的蒙太奇图像对应区域
        temp = dst(Rect(j * step_x, i * step_y, step_x, step_y));
    }
}
 
imshow("dst", dst);

通过两个for循环就可以遍历到每个蒙版区域。这个类似于遍历图像的所有像素,只不过我们把步长加大了而已。整个代码的核心就是以下这两句。

?
1
2
3
4
5
//将当前素材图像拷贝到temp零时变量
images[index].copyTo(temp);
 
//将temp图像赋值给需要生成的蒙太奇图像对应区域
temp = dst(Rect(j * step_x, i * step_y, step_x, step_y));

C++ OpenCV生成蒙太奇图像的示例详解

将所有的素材图像copy到指定区域就可以生成蒙版图像啦。接下来我们就得对这个蒙版图像做像素处理了。

四、生成蒙太奇图像

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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);

我们通过遍历模板图像所有像素,并改变它们的权值,就可以得到蒙太奇图像啦。

C++ OpenCV生成蒙太奇图像的示例详解

这就是我们生成的蒙太奇图像

五、源码

?
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
#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表示当前素材图像的索引
            int index = i * width + j;
 
            //将当前素材图像拷贝到temp零时变量
            images[index].copyTo(temp);
 
            //将temp图像赋值给需要生成的蒙太奇图像对应区域
            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;
}

总结

本文使用OpenCV C++生成蒙太奇图像,关键步骤有以下几点。

1、将你需要生成的蒙太奇图像模板resize成合适大小,使其恰好能够被素材图像填充。

2、载入素材图像。

3、使用素材图像去填充蒙版图。核心就是上面的两个for循环。

4、将蒙版与模板图像进行融合,改变其像素权值就可以生成蒙太奇图像了。

本文使用较为简单,也比较容易理解的程序生成蒙太奇图像。网上也有许多是使用直方图匹配——将模板图像分割成不等分区域,然后使用素材库中的图像与这些区域一一进行直方图匹配,找到最匹配的那张图像填充该区域。有兴趣的小伙伴可以尝试一下这种方法!!

以上就是C++ OpenCV生成蒙太奇图像的示例详解的详细内容,更多关于C++ OpenCV蒙太奇图像的资料请关注服务器之家其它相关文章!

原文链接:https://blog.csdn.net/Zero___Chen/article/details/119815275

延伸 · 阅读

精彩推荐
  • C/C++C++中const的用法详细总结

    C++中const的用法详细总结

    以下是对C++中const的用法进行了详细的总结分析,需要的朋友可以过来参考下,希望对大家有所帮助...

    C++教程网9542021-01-03
  • C/C++C++ 中实现把EXCEL的数据导入数据库(ACCESS、MSSQL等)实例代码

    C++ 中实现把EXCEL的数据导入数据库(ACCESS、MSSQL等)实例代码

    这篇文章主要介绍了C++ 中实现把EXCEL的数据导入数据库(ACCESS、MSSQL等)实例代码的相关资料,需要的朋友可以参考下...

    咪当我系欧巴9822021-05-06
  • C/C++c语言 malloc函数详解

    c语言 malloc函数详解

    这篇文章主要介绍了c语言 malloc函数详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小...

    Billy121387712021-08-06
  • C/C++基于list循环删除元素,迭代器失效的问题详解

    基于list循环删除元素,迭代器失效的问题详解

    下面小编就为大家带来一篇基于list循环删除元素,迭代器失效的问题详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来...

    C语言教程网5552021-04-24
  • C/C++C++ 中类的拷贝、赋值、销毁的实例详解

    C++ 中类的拷贝、赋值、销毁的实例详解

    这篇文章主要介绍了C++ 中类的拷贝、赋值、销毁的实例详解的相关资料,希望通过本文能帮助到大家,需要的朋友可以参考下...

    C++教程网7282021-06-03
  • C/C++c++如何实现跳表(skiplist)

    c++如何实现跳表(skiplist)

    这篇文章主要介绍了c++如何实现跳表,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...

    evenleo12592021-09-23
  • C/C++Windows上CLion的配置步骤详解

    Windows上CLion的配置步骤详解

    这篇文章主要介绍了Windows上CLion的配置,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参...

    至学者7172021-10-07
  • C/C++C语言循环控制入门介绍

    C语言循环控制入门介绍

    大家好,本篇文章主要讲的是C语言循环控制入门介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览...

    七7777322022-08-11