C++ OpenCV4.5 项目实战一(六)
·
系列文章目录
前言
学了那么多OpenCV API,开始做一个小项目,巩固一下之前学的知识点
一、电子相册
针对一张图片,进行模糊、美颜、加边框和调亮度等等,制作一张电子相册,效果图如下:

二、实现原理
1.主函数
代码如下(示例):
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
Mat g_srcImg; // 源图片
Mat g_beautyFgImg; // 美颜后的前景图片
Mat g_vagueBgImg; // 模糊后背景图
Mat g_roiImg; // 前景和背景组合后的图片
Mat g_rectImg; // 绘制矩形边框
Mat g_brightImg; // 调整亮度的图片
char g_szOutputWin[] = "output image";
// 调整模糊程度
int g_iVagueValue = 3;
int g_iVagueMaxSize = 10;
// 调整美颜程度
int g_iBeautyValue = 9;
int g_iBeautyMaxSize = 20;
// 绘制矩形,设置相框
int g_iRectValue = 5;
int g_iRectMaxSize = 30;
// 调整图片亮度
int g_iBrightValue = 6;
int g_iBrightMaxSize = 20;
// 调整模糊程度
void TrackbarVague(int, void*);
// 调整美颜程度
void TrackbarBeauty(int, void*);
// 绘制矩形,设置相框
void TrackbarRect(int, void*);
// 调整图片亮度
void TrackbarBright(int, void*);
// 将美颜前景图贴到模糊背景图层上
void SetROI(void);
int main(void)
{
g_srcImg = imread("E:\\1.png");
if (g_srcImg.empty())
{
cout << "load image fail..." << endl;
return -1;
}
imshow("input image", g_srcImg);
// 必须先创建窗口,不然滚动条无法绑定父窗口
namedWindow(g_szOutputWin, WINDOW_AUTOSIZE);
// 功能:创建滚动条并将其附加到指定的窗口
// 参数:trackbarname 创建的滚动条的名称
// winname 滚动条父窗口的名称
// value 滚动条所在位置的值,滑动滚动条,该值会改变
// count 滚动条的最大值,最小值总是0
// onChange 指向滚动条改变位置时要调用的函数的指针(回调函数),函数的原型应该是void Foo(int,void*);
// 其中第一个参数是滚动条所在位置,第二个参数是用户数据(见下一个参数);如果回调函数传空,则不调用回调,但只更新滚动条值
// userdata 按原样传递给回调的用户数据,它可以用来处理滚动条不使用全局变量的事件。
// 返回:成功返回0
createTrackbar("背景模糊", g_szOutputWin, &g_iVagueValue, g_iVagueMaxSize, TrackbarVague);
TrackbarVague(0, 0);
createTrackbar("前景美颜", g_szOutputWin, &g_iBeautyValue, g_iBeautyMaxSize, TrackbarBeauty);
TrackbarBeauty(0, 0);
createTrackbar("相框宽度", g_szOutputWin, &g_iRectValue, g_iRectMaxSize, TrackbarRect);
TrackbarRect(0, 0);
createTrackbar("图片亮度", g_szOutputWin, &g_iBrightValue, g_iBrightMaxSize, TrackbarBright);
TrackbarBright(0, 0);
waitKey(0);
return 0;
}
2.调整背景模糊
代码如下(示例):
void TrackbarVague(int, void*)
{
// SigmaX和SigmaY必须是奇数
int iSigma = 2 * g_iVagueValue + 1;
// 利用高斯模糊做底图
GaussianBlur(g_srcImg, g_vagueBgImg, Size(iSigma, iSigma), iSigma, iSigma);
// 全部初始化完才显示
if (g_beautyFgImg.data && g_vagueBgImg.data)
{
SetROI();
}
}
3.调整前景美颜
代码如下(示例):
void TrackbarBeauty(int, void*)
{
// 利用双边模糊,实现磨皮的效果
int iSigmaSpace = 50 + 10 * g_iBeautyValue;
Mat tmpImg;
bilateralFilter(g_srcImg, tmpImg, 15, iSigmaSpace, 0);
// 再利用掩膜计算,增加图像对比度,最终实现美颜相机的效果
Mat kernal = (Mat_<int>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
filter2D(tmpImg, g_beautyFgImg, -1, kernal, Point(-1, -1), 0);
// 功能:调整图像大小
// 参数:src 源图像
// dst 目标图像
// dsize 输出图像大小,如果为(0, 0),则大小为(img.cols * fx, img.rows * fy)
// fx x方向的缩小比例
// fy y方向的缩小比例
resize(g_beautyFgImg, g_beautyFgImg, Size(0, 0), 0.8, 0.8);
// 全部初始化完才显示
if (g_beautyFgImg.data && g_vagueBgImg.data)
{
SetROI();
}
}
4.调整相框厚度
代码如下(示例):
void TrackbarRect(int, void*)
{
if (!g_roiImg.data)
{
return;
}
// 绘制一个矩形,当做相框
int iPosX = (g_vagueBgImg.cols - g_beautyFgImg.cols) / 2 - g_iRectValue / 2;
int iPosY = (g_vagueBgImg.rows - g_beautyFgImg.rows) / 2 - g_iRectValue / 2;
int iWidth = g_beautyFgImg.cols + g_iRectValue;
int iHeight = g_beautyFgImg.rows + g_iRectValue;
Rect rect(iPosX, iPosY, iWidth, iHeight);
Scalar color(255, 255, 255);
g_rectImg = g_roiImg.clone();
rectangle(g_rectImg, rect, color, g_iRectValue);
// 调整颜色
TrackbarBright(g_iBrightValue, 0);
}
5.调整图片亮度
代码如下(示例):
void TrackbarBright(int, void*)
{
if (!g_rectImg.data)
{
cout << "g_rectImg is empty" << endl;
return;
}
int iRows = g_rectImg.rows;
int iCols = g_rectImg.cols;
Mat tmpImg = Mat::zeros(g_rectImg.size(), g_rectImg.type());
float fAlpha = 0.1 + (float)g_iBrightValue / 10.0;
float fBeta = 30; // 增益变量
for (int i = 0; i < iRows; i++)
{
for (int j = 0; j < iCols; j++)
{
if (g_rectImg.channels() == 1)
{
float f = g_rectImg.at<uchar>(i, j);
tmpImg.at<uchar>(i, j) = saturate_cast<uchar>(f * fAlpha + fBeta);
}
else if (g_rectImg.channels() == 3)
{
float fGreen = g_rectImg.at<Vec3b>(i, j)[0];
float fBlue = g_rectImg.at<Vec3b>(i, j)[1];
float fRed = g_rectImg.at<Vec3b>(i, j)[2];
tmpImg.at<Vec3b>(i, j)[0] = saturate_cast<uchar>(fGreen * fAlpha + fBeta);
tmpImg.at<Vec3b>(i, j)[1] = saturate_cast<uchar>(fBlue * fAlpha + fBeta);
tmpImg.at<Vec3b>(i, j)[2] = saturate_cast<uchar>(fRed * fAlpha + fBeta);
}
}
}
// 保存调整亮度后的背景图
g_brightImg = tmpImg.clone();
imshow(g_szOutputWin, g_brightImg);
}
6.将美颜前景贴到模糊背景
代码如下(示例):
void SetROI(void)
{
// 设定ROI区域
int iPosX = (g_vagueBgImg.cols - g_beautyFgImg.cols) / 2;
int iPosY = (g_vagueBgImg.rows - g_beautyFgImg.rows) / 2;
g_roiImg = g_vagueBgImg.clone();
Mat imageROI = g_roiImg(Rect(iPosX, iPosY, g_beautyFgImg.cols, g_beautyFgImg.rows));
// 加载掩模(必须是灰度图)
Mat mask;
cvtColor(g_beautyFgImg, mask, COLOR_BGR2GRAY);
g_beautyFgImg.copyTo(imageROI, mask);
TrackbarRect(g_iRectValue, 0);
}
总结
该项目绝大部分API都是用到之前学过的,因为对API了解不是很深,写的有点乱;
如果只是单纯的熟悉某个API,那也太无趣了,所以结合PS的部分操作,做了一个实战小项目,虽然做完了,但是和预想的差太多了😥,等到后面基础扎实了,再完善做个效果好的
更多推荐
所有评论(0)