这是一个比较有意思的demo,用到了播送融合,具体效果见下图:

文件结构如图所示

主程序代码

#include"stdafx.h"
#include<opencv2/photo.hpp>
#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<Point> //寻找最大的轮廓
VP FindBigestContour(Mat src) {
int imax = 0; //代表最大轮廓的序号
int imaxcontour = -1; //代表最大轮廓的大小
std::vector<std::vector<Point>>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_<Vec3f> inp_begin, inp_end;
inp_begin = Img_in.begin<Vec3f>();
inp_end = Img_in.end<Vec3f>();
// define the iterator of the output image
MatIterator_<Vec3f> out_begin, out_end;
out_begin = Img_out.begin<Vec3f>();
out_end = Img_out.end<Vec3f>();
// 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<Mat> 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;
}

其他包含的库文件放到我的链接:https://i-beta.cnblogs.com/files

OpenCV实现"你的名字"滤镜的更多相关文章

  1. [转] Matlab与C++混合编程,添加OpenCV库

    原文地址 峰回璐转 最近在做运动医学软件优化工作,此款软件框架及算法语言全由matlab实现,虽然matlab矩阵运算.数值计算能力强大,但速度让人难以忍 受.软件立刻移植到C++上又不太实际,故采用 ...

  2. Matlab与C++混合编程,添加OpenCV库

    最近在做运动医学软件优化工作,此款软件框架及算法语言全由matlab实现,虽然matlab矩阵运算.数值计算能力强大,但速度让人难以忍受.软件立刻移植到C++上又不太实际,故采用联合编程的方式,速度难 ...

  3. Ubuntu系统---编译opencv程序的几种方式g++、Makefile、Cmake

    Ubuntu系统---编译opencv程序的几种方式g++.Makefile.Cmake 先建立一个工程(一个文件夹),写好xxx.cpp文件,可以是多个: //----------opencv.cp ...

  4. Poisson Blending(Seamless clone)研究和实现

    Poisson Blending 实现了非常棒的效果,可以看 <自己动手,实现“你的名字”滤镜> http://www.cnblogs.com/jsxyhelu/p/7216795.htm ...

  5. studio 配置 opencv3.1

    环境 win10 android studio2.0 OpenCV-3.1.0-android-sdk android-ndk-r10e-windows-x86_64 jdk-8u102-window ...

  6. vs2017 dlib19.3 opencv3.41 C++ 环境配置 人脸特征点识别

    身为一个.net程序员经过两天的采坑终于把人脸特征检测的项目跑通了,然后本文将以dlib项目中人脸特征检测工程为例,讲解dlib与opencv 在vs2017 C++ 项目中的编译与运行路径配置. 1 ...

  7. 高反差保留滤镜学习OpenCV:滤镜系列(11)——高反差保留

    这几周笔者几篇文章介绍了改高反差保留滤镜的文章. 关联文章的地址 高反差保留就是高通滤波 r=(pix[x,y]-avg(R))/128 pix[x,y]*r+128*(1-r) #include & ...

  8. opencv滤镜-使用opencv实现各种图像滤镜特效

    图像处理-滤镜 链接:https://mangoroom.cn/opencv/image-processing-filter.html opencv滤镜-实现晕影vignetting效果 链接:htt ...

  9. 学习OpenCV:滤镜系列(15)——羽化(模糊边缘)

    ============================================== 版权所有:小熊不去实验室CSDN博客 ================================== ...

随机推荐

  1. 百度前端技术学院task16源代码

    欢迎访问我的github:huanshen 做这道题目的时候遇到了很多困难. 1.怎么给空对象添加数据,愣是不知道从哪里下手:遍历对象,一个个输出操作: 2.中英文的正则表达式不知道,赶紧去百度: 3 ...

  2. Java学习:数组工具类Arrays

    数组工具类Arrays java.util.Arrays是一个与数组相关的工具类,里面提供了大量的静态方法,用来实现数组常见的操作. public static String toString(数组) ...

  3. APS.NET MVC + EF (08)---数据注解和验证

    对于Web开发人员来说,用户输入验证一直是一个挑战.不仅在客户端浏览器中需要执行验证逻辑,在服务器端也需要执行.如果觉得验证是令人望而生畏的繁杂琐事,ASP.NET MVC框架提供了数据注解的方式帮助 ...

  4. 使用 HttpWebRequest 类做 POST 请求没有应反

    这几天给系统做第三方集成, 需要调用另一个软件的一个接口, 通过 HTTP 的方式调用,调用代码也挺简单的: string serviceUrl = string.Format("{0}/{ ...

  5. Promise介绍及使用场景

    Promise 介绍 Promise 是一个构造函数,是异步编程的一种解决方案.所谓Promse,它本身就是一个容器,里面保存着异步操作的结果,对的,这和回调函数类似. Promise 容器本身不是异 ...

  6. ionic创建组件、页面或者过滤器

    ionic可以直接 用命令来创建组件.页面或者过滤器. 在ionic项目根目录打开命令窗口.输入下列命令: ionic g page pageName //创建新页面 ionic g componen ...

  7. Js数组语法

    js数组整理导向图 ---欢迎收藏^ - ^

  8. Cheat Engine 字节数组类型

    BIG5 编码:http://www.qqxiuzi.cn/zh/hanzi-big5-bianma.php 打开游戏 准备修改名字 查找BIG5码 藤 吉 开始扫描 使用字节数组类型扫描 新BIG5 ...

  9. Android Studio 导入 Android 系统模块并编译和调试

    FAQ: AS导入系统模块源码,并且能够编译调试,正常查看java doc ???? Android AOSP基础(五)Android Studio调试系统源码的三种方式http://liuwangs ...

  10. Android中自定义环形图2

    如图: 自定义属性,在values文件夹下创建 attrs.xml <?xml version="1.0" encoding="utf-8"?> & ...