自己动手,实现“你的名字”滤镜
我喜欢《你的名字》这个故事,前一段时间在微信上使用过它的滤镜,实现的效果很惊艳,应该类似于下面的这些结果
这三幅图应该都是手机版本制作的,它们一个比较显著的特点是分辨率比较相似。如何实现类似的效果了?(注意后面两图天上的云是相同的)
首先我想到的是Prisma的实现方法,这种实现方法,最后得到的是纹理的转换,效果应该说非常好,但是依赖于深度学习,目前这个方面掌握的不是很明确。而且显然上面三图不是纹理转换。
继续寻找,主要参考《
实现<你的名字>同款滤镜,python+opencv》等相关资料。
一、问题分析
对于这样一副图片,如果想变成《你的名字》这种效果,需要做以下事情
(一)背景(天空)分割,替换后再融合
在自然界的图片中,很难出现动漫中大多大多的云彩。首先需要将
背景(天空)分割出来,替换成动漫的天空,并且在很好地融合回去。
需要实现的技术:1.
背景(天空)分割;2.再融合。需要准备的材料:1.大块的动漫云图
(二)前景色调转换
为了实现漫画中具有卡通意味的前景色调,需要对前面切割下来的前景图片进行色调转换。
需要实现的技术:3.LUT和色块制作
(三)程序框架
需要实现的技术:基于GOMfcTemplate2,实现图像的输入输出、滤镜操作的参数选择等基础操作
二、材料准备
1.大朵的云。先找到一副自然界中的云。
再准备(制作)一幅动漫的云和一副星空的图片.
三、算法实验
1.
背景(天空)分割,采用材料中的方法,修改形态学部分
/************************************************************************/
/* 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());
imshow(
"原始图",matSrc);
对于这幅图来说,效果不错(右上角明显的是错误,而塔中间的一个很小的空洞,最后生成的效果应该可以忽略不计)
2.再融合
以此为mask,直接将云图拷贝过来(之前需要先做尺度变换,就是resize) 距离变换?
cvtColor(temp,mask,COLOR_BGR2GRAY);
//将结果存入mask
resize(matCloud,matCloud,matSrc.size());
matCloud.copyTo(matSrc,mask);
这个时候看图片,还是有很多瑕疵的,特别是下方护栏的边缘的地方。但是对于这样的图片,其前景和背景的分割,主要部分的效果还是非常不错的;
所以采用seamlessclone,得到以下结果
//seamless clone
Point center(matSrc.cols
/
2,matSrc.rows
/
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);
NORMAL_CLONE
MIXED_CLONE
MONOCHROME_TRANSFER
相比较之下,
MIXED_CLONE对原图纹理的保存更好一些,对有错误的地方的进行了很好地遮盖。
3.LUT和色卡制作
色调转换的意义,在于使得全图具有更多的“卡通”意味在厘米,毕竟我们想要实现的最终效果想要类似“你的名字”。那么什么是“动漫”的效果?这是一个见仁见智的问题。我找到一些做得较好的转换
总的来说,卡通的效果是“颜色更加鲜艳”“细节比较少”等,是一个比较主观的定义;对于”你的名字“这个效果来说,应该还有一个色调的变换
那么,就以表面模糊、彩色直方图均衡以及色相调整这些比较容易实现的方法来达到目的。
step1.双边滤波
step2.彩色直方图
step3.饱和度调整
/************************************************************************/
/* 3.卡通画处理 */
/************************************************************************/
//双边滤波
bilateralFilter(mixed_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);
//提高饱和度
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);
算法部分各种结果展现
现在看来,结果还是不很想”你的名字“的效果,但是美化的效果是有的。存在比较大的硬伤就是天空算法中,会找到一些边界,比如。
为什么会出现这种情况?因为seamlessClone只是clone算法,而不是融合算法,所以需要后续优化。
四、工程实现
基于GOMfcTemplate2,实现图像的输入输出、滤镜操作的参数选择等基础操作
下一步,还需要继续研究清楚各种算法的原理,得到更好的结果。
2017年7月25日19:18:45 前面的问题没有解决完,耽搁了几天:
一个是最上面边缘的不和谐过渡问题,我重新学习了一下《实现<你的名字>同款滤镜》,他的解决方法更好,主要是在seamless的时候,不是全图融合,而是找出轮廓后再融合。
//2017年7月25日 添加寻找白色区域最大外接矩形的代码
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();
resize(matCloud,matCloud,matDst.size());
matCloud.copyTo(matDst,mask);
//为seamless准备材料
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);
这个时候,结果就更是perfect了,和原文一样,我采用
NORMAL_CLONE
的方法,目前的结果为
而在曾经出现过问题的地方,有所收敛
好看多了
修改代码的时候需要注意mask的修改,这点在代码里面说明了,自己看。
二个是,我感觉现在前景虽然对比度提高,颜色鲜艳,但明显不是动漫的感觉呀。漫画的效果肯定是有一些论文的,
依稀记得《master opencv with practical projects》第一章实现cartoon效果,
但是这个效果也太随意了(这篇文章在作者一定是个爸爸,妈妈是不会放自己小孩这样的图片的)。找到它的代码进行修改
应该还可以进一步提高,但是这个效果很有意思,开源之,大家可以一起来看。
2017年7月28日19:21:27
进一步思考,这种融合效果能否用于图像拼接?进行了一些常识
Mat matreult
=
Mat(normal_clone.rows
+
30
,matCloud.cols,CV_8UC3,Scalar(
0
));
Mat halfTop
= matreult(Rect(
0,
0,maxRect.width,
30));
Mat halfDown
= matreult(Rect(
0,
30,normal_clone.cols,normal_clone.rows));
matTop.copyTo(halfTop);
normal_clone.copyTo(halfDown);
Mat matNormal
= matreult.clone();
mixed_clone.copyTo(halfDown);
Mat matMixed
= matreult.clone();
monochrome_clone.copyTo(halfDown);
Mat matMonochrome
= matreult.clone();
可以看到,在边缘部分,由于meanlessclone进行了全局的处理,所以和原图的差距比较大,反而造成了新的误差,所以可能直接适用于图像拼接不适合。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!