• 如何用代码画出一幅好看的画


    前言

    随着计算机技术的逐步发展,借助计算机强大的能力进行绘画操作,已经变得非常容易。绘画作品的水平也是越来越高,下面就来看看用编程语言绘画,能搞出什么有意思的东西,相比人类的创作又有哪些值得我们思考的地方。

    绘画

    用代码输出类似绘画的内容,最最原始的恐怕就是直接使用 print 函数了。

    print 输出字符

    def do_print():
        print('''
    
            へ     /|
          /\7    ∠_/
          / │   / /
         │ Z _,< /   /`ヽ
         │     ヽ   /  〉
          Y     `  /  /
         イ● 、 ●  ⊂⊃〈  /
         ()  へ    | \〈
          >ー 、_  ィ  │ //
          / へ   / ノ<| \\
          ヽ_ノ  (_/  │//
          7       |/
          >―r ̄ ̄`ー―_
         ''')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    这个方法执行后,就可以在控制台看到下面这幅可爱的皮卡丘画了。

    请添加图片描述

    这种做法,可以说是完全没有什么技术水平了。想要画什么内容,还得预先编排字符,太麻烦了。于是便有了升级版。

    图片转字符

    这种用图片转字符,看似没有什么意义,但其实有时候可以创作出意想不到的作品。比如前一阵子的顶流冰墩墩。

    在这里插入图片描述

    这种做法的思路总的来说,就是把图片的抽样图片的像素信息,然后将像素信息中关键的亮度信息用特殊的字符串进行打印,效果就是我们最终看到的样子。

    public static void printImage(BufferedImage image) throws IOException {
        final char[] PIXEL_CHAR_ARRAY = {'W', '@', '#', '8', '&', '*', 'o', ':', '.', ' '};
        int width = image.getWidth();
        int height = image.getHeight();
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                int rgb = image.getRGB(j, i);
                Color color = new Color(rgb);
                int red = color.getRed();
                int green = color.getGreen();
                int blue = color.getBlue();
                // 一个用于计算RGB像素点灰度的公式
                Double grayscale = 0.2126 * red + 0.7152 * green + 0.0722 * blue;
                double index = grayscale / (Math.ceil(255 / PIXEL_CHAR_ARRAY.length) + 0.5);
                System.out.print(PIXEL_CHAR_ARRAY[(int)(Math.floor(index))]);
            }
            System.out.println();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    更多具体实现可以参考 字符作画,我用字符画个冰墩墩

    使用 Python-turtle 库作图

    下面这几幅知乎用户的回答,可以说是非常有水平了。

    import random
    import turtle
    from turtle import *
    
    t = turtle.Turtle()
    w = turtle.Screen()
    
    
    def tree(branchLen, t):
        if branchLen > 3:
            if 8 <= branchLen <= 12:
                if random.randint(0, 2) == 0:
                    t.color('snow')
                else:
                    t.color('lightcoral')
                t.pensize(branchLen / 3)
            elif branchLen < 8:
                if random.randint(0, 1) == 0:
                    t.color('snow')
                else:
                    t.color('lightcoral')
                t.pensize(branchLen / 2)
            else:
                t.color('sienna')
                t.pensize(branchLen / 10)
    
            t.forward(branchLen)
            a = 1.5 * random.random()
            t.right(20 * a)
            b = 1.5 * random.random()
            tree(branchLen - 10 * b, t)
            t.left(40 * a)
            tree(branchLen - 10 * b, t)
            t.right(20 * a)
            t.up()
            t.backward(branchLen)
            t.down()
    
    
    def petal(m, t):  # 树下花瓣
        for i in range(m):
            a = 200 - 400 * random.random()
            b = 10 - 20 * random.random()
            t.up()
            t.forward(b)
            t.left(90)
            t.forward(a)
            t.down()
            t.color("lightcoral")
            t.circle(1)
            t.up()
            t.backward(a)
            t.right(90)
            t.backward(b)
    
    
    def main():
        t = turtle.Turtle()
        myWin = turtle.Screen()
        getscreen().tracer(5, 0)
        turtle.screensize(bg='wheat')
        t.left(90)
        t.up()
        t.backward(150)
        t.down()
        t.color('sienna')
        tree(60, t)
        petal(100, t)
    
        myWin.exitonclick()
    
    
    if __name__ == '__main__':
        main()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75


    可以看到,使用 turtle 库加上强大的数学几何知识,可以创作出非常好的看图像。更多内容可以参考 这个问题

    使用 AI 作画

    ERNIE-ViLG文生图

    使用以上方案绘制的内容,一般都比较刻板,缺少一些人文气息。少了一些人类才能有的特点。但是随着 AI 算力的提升和大数据的逐步发展,已经有很多可以使用 AI 进行作画的平台了。 比如 百度飞浆文心大模型 ERNIE-ViLG文生图 平台。

    import wenxin_api
    from wenxin_api.tasks.text_to_image import TextToImage
    import secret
    
    
    def draw(t, s):
        wenxin_api.ak = secret.ak
        wenxin_api.sk = secret.sk
        input_dict = {
            "text": t,
            "style": s
        }
        rst = TextToImage.create(**input_dict)
        print(rst)
    
    
    if __name__ == '__main__':
        text = "夏天"
        style = "油画"
        draw(text, style)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    使用上面的代码,就可以创作出 油画 风格的夏天,可以看看 AI 生成结果。

    2022-08-28 12:20:06,785 - model is painting now!, 
    - taskId: 1062408, waiting: 30s
    {'imgUrls': ['https://wenxin.baidu.com/younger/file/ERNIE-ViLG/89df26b9853d837d331d626ffa62828fex', 'https://wenxin.baidu.com/younger/file/ERNIE-ViLG/89df26b9853d837d331d626ffa62828fi4', 'https://wenxin.baidu.com/younger/file/ERNIE-ViLG/89df26b9853d837d331d626ffa62828f5q', 'https://wenxin.baidu.com/younger/file/ERNIE-ViLG/89df26b9853d837d331d626ffa62828f30', 'https://wenxin.baidu.com/younger/file/ERNIE-ViLG/89df26b9853d837d331d626ffa62828fv9', 'https://wenxin.baidu.com/younger/file/ERNIE-ViLG/89df26b9853d837d331d626ffa62828fa2']}
    
    • 1
    • 2
    • 3

    可以看到速度还是很快的出不多一分钟就搞定了。可以预览一下结果






    可以看到还是很厉害了,水平应可以赶上专科院校的毕业生了,但是作画速度那可是降维打击啊。

    使用 ERNIe-ViLG 搭配自定义的关键字可以生成 水彩、油画、粉笔画、卡通、蜡笔画、儿童画等多种风格的图片。

    可以再试一下水彩画风格的天龙八部






    是不是还挺有感觉的。

    DALL·E 2

    当然,说到 AI 绘画,国外大公司也有很厉害的。比如 OpenAI 公司DALL·E 2

    比如以写实风格创作一个宇航员骑着一匹马的图像

    请添加图片描述

    在换个铅笔画风格的

    请添加图片描述

    使用 DALL·E 2 可以根据创作风格,更多关键字由 AI 创作出非常有想象力的作品。可以到 DALL·E 2 的主页查看更多更详细的内容。

    总结

    其实用代码直接绘制图形,还有很多其他方案。比如大名鼎鼎的 MATLAB ,可以创作出非常精良的数学几何图形。

    但是比较一下上面的这几种方案,可以说 AI 作画的水平,一下子提升了好几个层次。创作需要的输入越来越明确,越来越简答,越发的人性化。但是输出的内容,却越发的开始接近甚至超越了人类的水平。

    参考文档

  • 相关阅读:
    几种平滑处理方法
    粒子群优化算法(PSO)python实践
    GO微服务实战第一节 为什么说云原生重构了互联网产品开发模式?
    判断序列是否为正确的出栈序列
    K8S安装过程七:Kubernetes 节点配置调整
    Java:Java 仍然很棒的7个原因
    Ant design table实现单选和点击行选中
    Flutter 自定义ScrollPhysics实现PageView禁止左滑或右滑
    HBase海量数据高效入仓解决方案
    springboot超市库存管理系统java ssm
  • 原文地址:https://blog.csdn.net/TOYOTA11/article/details/126575202