用函数画出可爱的卡通猫

来源:互联网 发布:开淘宝店被骗了怎么办 编辑:程序博客网 时间:2024/04/29 20:02

http://www.jianshu.com/p/167ab9cccf38


Logo写文章注册登录

震惊!无聊男子竟用函数画出可爱的卡通猫

144 
作者 Zorm 关注
2017.02.19 20:43 字数 1437 阅读 93评论 0

函数共 268 页 11783 行,前后折腾了近半个月。可惜还是有些小瑕疵,不然文章标题就该叫《震惊!死宅竟用三角函数画出可爱的老婆》了......


用函数画的 Pusheen

画 Pusheen 的函数

前言

在推上看到这样一张图:


Twitter截图

觉着用函数画妹子什么的好有趣,决定自己试着实现一下。

思路

从图中可以看到,绘制妹子的函数为三角函数项的和。不难发现,函数以 t 为参数,两个一组分别为正弦级数和余弦级数,首项(a0/b0)为常数,很容易看出来,函数应该和傅里叶级数有关系。

大体思路如下:

  1. 预处理图片。用 MATLAB 将想要用函数绘制的图片读入
  2. 提取轮廓
  3. 获取轮廓的坐标
  4. 处理坐标。获取到的坐标为 N 点长的离散序列,将其进行 N 点离散傅里叶级数展开(DFS)
  5. 验证。将输出结果的函数绘制成图像,观察效果

实现

先画个简单点的。桌面上有张可爱的 Pusheen 图片,就用它啦。


萌萌的 Pusheen 猫

1. 预处理图片

将 Pusheen 图片读入MATLAB。

cd C:\Users\Desktoppic = imread('C:\Users\Ascend\Desktop\pusheen.jpg');

转换为二值图像。

pic = im2bw(pic);show(pic)

转换为二值图像的原因是便于提取轮廓。看下效果。


二值图像效果

2. 提取轮廓

这里直接调用了 MATLAB 自带提取轮廓的算法。

pic = edge(pic,'sobel');imshow(pic);

效果如下图,看起来不错,轮廓分明线条干净。


轮廓

3. 获取轮廓坐标

获取轮廓坐标,并将能够围成封闭曲线的坐标分组,则每组为一个有限长的离散序列,再将每个序列进行 DFS 展开。

获取轮廓坐标并不难,难在拟合封闭曲线这里。想了想毫无头绪,上网搜索找到了 MATLAB 自带的 imcontour 函数。精度一般,使用条件苛刻,后文再叙,先凑合用。

point = imcontour(pic);

得到一个 2x126494 的矩阵 point,里面有我们需要的坐标。

4. 处理坐标

处理矩阵

坐标已经得到,先试着用坐标画一下图像。

width=point(2,:);height=point(1,:);plot(width,height)

却得到了一副非常奇怪的图像。


一团乱麻

按道理,坐标描点得到的图像就应该为 Pusheen 猫的轮廓。注意到图像有几个异常点,横坐标特别大。查看矩阵 point 的结构。


矩阵 point 的结构

第一行为纵坐标 height ,第二行为横坐标 width,每一列为一个点 (height,width)。

第一个点的数值很奇怪。横坐标为 2435 ,纵坐标为 0.1,怎么看都不是轮廓上的点。也许是某种标记?于是向后翻了2435个点,看到第 2437 列:


2437

又是一个 (0.1,2427)。再向后翻 2427 个点:


4865

第 4865 列,又是一个 (0.1,2531)。于是这个点的意义就清楚了:横坐标为 0.1 的点为特殊标记,其值为该组点的个数。依此可以将这个 2x126494 的矩阵拆成多个小矩阵,每个矩阵为一组可以拟合成封闭曲线的坐标(imcontour函数认为的)。

拆分矩阵

%判断point(1,:)第一行 0.1 的个数,从而判断length的长度length=0;for i=1:size(point,2)  if point(1,i)==0.1   length=length+1;  endend%开始分段,拆成a1,a2,a3,...,一共length个二维数组for i=1:length  temp=point(2,1);  point(:,1)=[];  eval(sprintf('a%d=point(1:2,1:temp);', i)); %将第i段数据送入第i个数组  point(:,1:temp)=[];end%纵坐标取负数,将离散数据转为坐标for i=1:length  eval(sprintf('a%d(2,:)=-a%d(2,:);',i,i));end

离散傅里叶级数展开

离散傅里叶级数的公式如下,根据公式,写出 MATLAB 代码。


DFS公式
file = fopen('outer.txt', 'w'); %I/O方式输出结果,结果输出到桌面的outer.txt中for count=1:length  eval(sprintf('a=a%d;',count));  N = size(a,2);  %a->ax(虚数组)  are=a(1,:);  aim=a(2,:);  ax=are+aim*j;  clear are aim;  %A:傅里叶正变换数组  A=[];  for i = 0:N-1      ang = -2 * 1j * pi * i / N;      r = 0;      for j=0:N-1          r = r + exp(ang * j) * ax(j+1);      end      A(i+1)=r;  end  clear ang i j r;  fprintf(file,['t=1:',num2str(N),';\n']);  fprintf(file,'x(t)=');  for i = 0:N-1      ang = 2 * pi * i / N;      fprintf(file,'+');      fprintf(file,[num2str(real(A(i+1) / N)),'*cos(', num2str(ang), '*t)-']);      fprintf(file,[num2str(imag(A(i+1) / N)),'*sin(', num2str(ang), '*t)']);  end  fprintf(file,';\n');  fprintf(file,'y(t)=');  for i = 0:N-1      ang = 2 * pi * i / N;      fprintf(file,[num2str(imag(A(i+1) / N)),'*cos(', num2str(ang), '*t)+']);      fprintf(file,[num2str(real(A(i+1) / N)),'*sin(', num2str(ang), '*t)+']);  end  fprintf(file,'0;\n');  fprintf(file,'plot(x,y);hold on;\n');endfclose(file);

5. 验证

输出的函数在桌面的 outer.txt 文件中。


结果

将函数输入到 MATLAB 中画图像,结果如下。


Pusheen

验证无误。输出那一堆就是能画出可爱的 Pusheen 的函数啦 ~

其他

卡通小猫都画出来了,打算也画一个卡通妹子。在网上找了张艾米莉亚线稿


EMT

使用了用同样的方法,结果如下。


混乱的艾米莉亚

一脸茫然,大概轮廓倒能看出来,可怎么会乱成这样子[笑cry]

仔细想了想,原因可能出在闭合曲线分组那儿。卡通猫轮廓上的蜜汁线条也可能因为此。

对卡通猫的函数进行 Debug:


step1

step2

step3

step4

step5

这些就差不多能看出原因了。imcontour 函数将鼻子、眼睛也认为是外轮廓的一部分,错误地将其分为一组数据。对于像 Pusheen 这种线条简单的图形来说,精度一般,分错组数较少。对于艾米莉亚这种复杂的人像来说,精度远远不够,错误就太多了。

回到从推上看到的图片。人家是如何画出那么完美的人像的呢?翻了翻博主的其他推文,发现人家利用游戏引擎 Hot Soup Processor 设计了一个画图板程序,在程序上手绘一组组封闭曲线,游戏引擎会用傅里叶级数将这组封闭曲线展开为函数。这个过程不需要用程序将离散序列分组,精度极高。

在没找到更好的分组方法前,就只能画画轮廓简单的图片啦[笑cry]

一些其他的函数曲线:

Twitter Curve:


twitterline

twitterfunction

1:


one

onefunction

参考资料

https://mathematica.stackexchange.com/questions/17704/how-to-create-a-new-person-curve
http://blog.wolfram.com/2013/05/17/making-formulas-for-everything-from-pi-to-the-pink-panther-to-sir-isaac-newton/
http://blog.wolframalpha.com/2013/06/10/using-formulas-for-everything-from-a-complex-analysis-class-to-political-cartoons-to-music-album-covers/
http://blog.wolfram.com/2013/08/15/even-more-formulas-for-everything-from-filled-algebraic-curves-to-the-twitter-bird-the-american-flag-chocolate-easter-bunnies-and-the-superman-solid/
http://www.isnowfy.com/generate-any-function-curve/
https://yvt.jp/contours/

Pusheen 函数下载地址

 粗浅技术

若此文有幸能帮到你,希望你能用因此节省下来的时间,点一下 “喜欢”。

赞赏支持
登录 后发表评论
评论
智慧如你,不想发表一点想法咩~

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 微博账号被冻结了怎么办 微博一天多次解冻怎么办 肿瘤对化疗不敏感怎么办 2个月宝宝肺炎怎么办 小孩咳嗽2个月怎么办 两个月的小孩子气管炎怎么办? 小孩子两个月发烧38度怎么办 两个月的小孩子咳嗽怎么办 5个月宝宝吃奶少怎么办 26岁的1型糖尿病怎么办 睡前吃得太饱怎么办 胰岛素2小时>300怎么办 血清c肽测定高怎么办 体测蛋白质和骨骼肌偏高怎么办 半个月重了十斤怎么办 月经停了2个月怎么办 在练腹肌中腹痛怎么办 越练肌肉越肥怎么办 喘不过气来 心闷怎么办 被气得喘不过气怎么办 健身完头晕想吐怎么办 吃多了反胃头晕怎么办 合同未约定退货货物积压怎么办 运动内衣把胸压平怎么办 经常穿皮鞋脚臭怎么办 买衣服胸围小了怎么办 内衣下胸围太紧怎么办 穿文胸衣服要开怎么办 运动内衣的拉链老来怎么办 胸罩没干急着穿怎么办 跑步时大腿很痒怎么办 胖大腿内侧磨伤怎么办 内衣围带过松怎么办 内衣底围特别紧怎么办 全棉衣服上的油怎么办 高腰牛仔裤腰大了怎么办 新买衣服太硬怎么办 棉麻的衣服发硬怎么办 新衣服太硬怎么办雪纺 衣服硬的咯人怎么办 脖子上的勒痕怎么办