这是一个比较有意思的demo,用到了播送融合,具体效果见下图:
文件结构如图所示
主程序代码
#include"stdafx.h"
#include
#include"HSL.hpp"
using namespace std;
using namespace cv;
const string window_name = "photo";
static Mat src;
static HSL hsl;
static int color = 0;
static int hue = 180;
static int saturation = 100;
static int brightness = 100;
#define VP vector
//寻找最大的轮廓
VP FindBigestContour(Mat src) {
int imax = 0; //代表最大轮廓的序号
int imaxcontour = -1; //代表最大轮廓的大小
std::vector<:vector>>contours;
findContours(src, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size(); i++) {
int itmp = contourArea(contours[i]);//这里采用的是轮廓大小
if (imaxcontour < itmp) {
imax = i;
imaxcontour = itmp;
}
}
return contours[imax];
}
//提高饱和度
Mat EnhanceSaturation(Mat temp)
{
Mat matDst;
Mat Img_out(temp.size(), CV_32FC3);
temp.convertTo(Img_out, CV_32FC3);
Mat Img_in(temp.size(), CV_32FC3);
temp.convertTo(Img_in, CV_32FC3);
// define the iterator of the input image
MatIterator_ inp_begin, inp_end;
inp_begin = Img_in.begin();
inp_end = Img_in.end();
// define the iterator of the output image
MatIterator_ out_begin, out_end;
out_begin = Img_out.begin();
out_end = Img_out.end();
// increment (-100.0, 100.0)
float Increment = 50.0 / 100.0; //饱和度参数调整
float delta = 0;
float minVal, maxVal;
float t1, t2, t3;
float L, S;
float alpha;
for (; inp_begin != inp_end; inp_begin++, out_begin++)
{
t1 = (*inp_begin)[0];
t2 = (*inp_begin)[1];
t3 = (*inp_begin)[2];
minVal = std::min(std::min(t1, t2), t3);
maxVal = std::max(std::max(t1, t2), t3);
delta = (maxVal - minVal) / 255.0;
L = 0.5*(maxVal + minVal) / 255.0;
S = std::max(0.5*delta / L, 0.5*delta / (1 - L));
if (Increment > 0)
{
alpha = max(S, 1 - Increment);
alpha = 1.0 / alpha - 1;
(*out_begin)[0] = (*inp_begin)[0] + ((*inp_begin)[0] - L * 255.0)*alpha;
(*out_begin)[1] = (*inp_begin)[1] + ((*inp_begin)[1] - L * 255.0)*alpha;
(*out_begin)[2] = (*inp_begin)[2] + ((*inp_begin)[2] - L * 255.0)*alpha;
}
else
{
alpha = Increment;
(*out_begin)[0] = L * 255.0 + ((*inp_begin)[0] - L * 255.0)*(1 + alpha);
(*out_begin)[1] = L * 255.0 + ((*inp_begin)[1] - L * 255.0)*(1 + alpha);
(*out_begin)[2] = L * 255.0 + ((*inp_begin)[2] - L * 255.0)*(1 + alpha);
}
}
Img_out /= 255;
Img_out.convertTo(matDst, CV_8UC3, 255);
return matDst;
}
int _tmain(int argc, _TCHAR* argv[])
{
Mat matSrc = imread("../src3.jpg");
Mat matCloud = imread("../cloud2.jpg");
Mat temp; Mat matDst; Mat mask;
vector planes;
/************************************************************************/
/* 1.背景(天空)分割 */
/************************************************************************/
cvtColor(matSrc, temp, COLOR_BGR2HSV);
split(temp, planes);
equalizeHist(planes[2], planes[2]);//对v通道进行equalizeHist
merge(planes, temp);
inRange(temp, Scalar(100, 43, 46), Scalar(124, 255, 255), temp);
erode(temp, temp, Mat());//形态学变换,填补内部空洞
dilate(temp, temp, Mat());
mask = temp.clone();//将结果存入mask
/************************************************************************/
/* 2.再融合,以1的结果mask,直接将云图拷贝过来(之前需要先做尺度变换) */
/************************************************************************/
//寻找白色区域最大外接矩形的代码
VP maxCountour = FindBigestContour(mask);
Rect maxRect = boundingRect(maxCountour);
if (maxRect.height == 0 || maxRect.width == 0)
maxRect = Rect(0, 0, mask.cols, mask.rows);//特殊情况
matDst = matSrc.clone();
//注意这里的mask 需要和matCloud同样尺寸
mask = mask(maxRect);
resize(matCloud, matCloud, maxRect.size());
//seamless clone
//中间位置为蓝天的背景位置
Point center = Point((maxRect.x + maxRect.width) / 2, (maxRect.y + maxRect.height) / 2);
Mat normal_clone;
Mat mixed_clone;
Mat monochrome_clone;
seamlessClone(matCloud, matSrc, mask, center, normal_clone, NORMAL_CLONE);
seamlessClone(matCloud, matSrc, mask, center, mixed_clone, MIXED_CLONE);
seamlessClone(matCloud, matSrc, mask, center, monochrome_clone, MONOCHROME_TRANSFER);
/************************************************************************/
/* 3.卡通画处理 */
/************************************************************************/
//双边滤波
bilateralFilter(normal_clone, temp, 5, 10.0, 2.0);
//彩色直方图均衡,将RGB图像转到YCbCr分量,然后对Y分量上的图像进行直方图均衡化
cvtColor(temp, temp, COLOR_BGR2YCrCb);
split(temp, planes);
equalizeHist(planes[0], planes[0]);
merge(planes, temp);
cvtColor(temp, temp, COLOR_YCrCb2BGR);
//提高图像饱和度
matDst = EnhanceSaturation(temp);
imshow("原始图", matSrc);
imshow("结果图", matDst);
cv::waitKey();
getchar();
return 0;
}
标签:begin,Mat,temp,mask,inp,名字,OpenCV,滤镜,out
来源: https://www.cnblogs.com/liuboblog/p/12026925.html