分类目录归档:Python绘图

教你一行代码自动绘制艺术画 (Discoart)

DiscoArt 是一个很牛逼的开源模块,它能根据你给定的关键词自动绘画。

绘制过程是完全可见的,你可以在 jupyter 页面上看见这个绘制的过程:

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install discoart

为了运行 Discoart, 你需要Python 3.7+ 和支持 CUDA 的 PyTorch.

2.开始使用 Discoart

你可以在Jupyter中运行Discoart,这样能方便地实时展示绘制过程:

from discoart import create

da = create()

这样将使用默认的 文本描述 和参数创建图像:

text_prompts:
  - A beautiful painting of a singular lighthouse, shining its light across a tumultuous sea of blood by greg rutkowski and thomas kinkade, Trending on artstation.
  - yellow color scheme

init_image:
width_height: [ 1280, 768 ]

skip_steps: 0
steps: 250

init_scale: 1000
clip_guidance_scale: 5000

tv_scale: 0
range_scale: 150
sat_scale: 0
cutn_batches: 4

diffusion_model: 512x512_diffusion_uncond_finetune_008100
use_secondary_model: True
diffusion_sampling_mode: ddim

perlin_init: False
perlin_mode: mixed
seed:
eta: 0.8
clamp_grad: True
clamp_max: 0.05

randomize_class: True
clip_denoised: False
rand_mag: 0.05

cut_overview: "[12]*400+[4]*600"
cut_innercut: "[4]*400+[12]*600"
cut_icgray_p: "[0.2]*400+[0]*600"
cut_ic_pow: 1.

save_rate: 20
gif_fps: 20
gif_size_ratio: 0.5
n_batches: 4
batch_size: 1
batch_name:
clip_models:
  - ViT-B-32::openai
  - ViT-B-16::openai
  - RN50::openai
clip_models_schedules:

use_vertical_symmetry: False
use_horizontal_symmetry: False
transformation_percent: [0.09]

on_misspelled_token: ignore
diffusion_model_config:
cut_schedules_group:
name_docarray:
skip_event:
stop_event:
text_clip_on_cpu: False
truncate_overlength_prompt: False
image_output: True
visualize_cuts: False
display_rate: 1

创建出来的就是这个图:

Create 支持的所有参数如下:

text_prompts:
  - A beautiful painting of a singular lighthouse, shining its light across a tumultuous sea of blood by greg rutkowski and thomas kinkade, Trending on artstation.
  - yellow color scheme

init_image:
width_height: [ 1280, 768 ]

skip_steps: 0
steps: 250

init_scale: 1000
clip_guidance_scale: 5000

tv_scale: 0
range_scale: 150
sat_scale: 0
cutn_batches: 4

diffusion_model: 512x512_diffusion_uncond_finetune_008100
use_secondary_model: True
diffusion_sampling_mode: ddim

perlin_init: False
perlin_mode: mixed
seed:
eta: 0.8
clamp_grad: True
clamp_max: 0.05

randomize_class: True
clip_denoised: False
rand_mag: 0.05

cut_overview: "[12]*400+[4]*600"
cut_innercut: "[4]*400+[12]*600"
cut_icgray_p: "[0.2]*400+[0]*600"
cut_ic_pow: 1.

save_rate: 20
gif_fps: 20
gif_size_ratio: 0.5
n_batches: 4
batch_size: 1
batch_name:
clip_models:
  - ViT-B-32::openai
  - ViT-B-16::openai
  - RN50::openai
clip_models_schedules:

use_vertical_symmetry: False
use_horizontal_symmetry: False
transformation_percent: [0.09]

on_misspelled_token: ignore
diffusion_model_config:
cut_schedules_group:
name_docarray:
skip_event:
stop_event:
text_clip_on_cpu: False
truncate_overlength_prompt: False
image_output: True
visualize_cuts: False
display_rate: 1

你可以这么使用:

from discoart import create

da = create(
    text_prompts='A painting of sea cliffs in a tumultuous storm, Trending on ArtStation.',
    init_image='https://d2vyhzeko0lke5.cloudfront.net/2f4f6dfa5a05e078469ebe57e77b72f0.png',
    skip_steps=100,
)

如果你不是用jupyter运行的,你也可以看到中间结果,因为最终结果和中间结果都会被创建在当前工作目录下,即

./{name-docarray}/{i}-done.png
./{name-docarray}/{i}-step-{j}.png
./{name-docarray}/{i}-progress.png
./{name-docarray}/{i}-progress.gif
./{name-docarray}/da.protobuf.lz4
  • name-docarray是运行时定义的名称,如果没有定义,则会随机生成。
  • i-* 第几个Batch。
  • *-done-* 是当前Batch完成后的最终图像。
  • *-step-* 是某一步的中间图像,实时更新。
  • *-progress.png 是到目前为止所有中间结果的png图像,实时更新。
  • *-progress.gif 是到目前为止所有中间结果的动画 gif,实时更新。
  • da.protobuf.lz4 是到目前为止所有中间结果的压缩 protobuf,实时更新。

3.显示/保存/加载配置

如果你想知道你当前绘图的配置,有三种方法:

from discoart import show_config

show_config(da)  # show the config of the first run
show_config(da[3])  # show the config of the fourth run
show_config(
    'discoart-06030a0198843332edc554ffebfbf288'
)  # show the config of the run with a known DocArray ID

要保存 Document/DocumentArray 的配置:

from discoart import save_config

save_config(da, 'my.yml')  # save the config of the first run
save_config(da[3], 'my.yml')  # save the config of the fourth run

从配置中导入:

from discoart import create, load_config

config = load_config('my.yml')
create(**config)

此外,你还能直接把配置导出为图像的形式

from discoart.config import save_config_svg

save_config_svg(da)

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

Manim 一个特漂亮的Python数学教学动画开发模块

Manim 是3b1b开源的一个特别漂亮的数学动画模块。

我们能够基于Manim绘制许多解释性的动画,比如下面这个:

也支持函数图像:

甚至是一些3D视图和矩阵变换,Manim都可以轻易实现:

如果你是一个数学课程的演讲者,或者你需要给观众演示某些数学公式的图形,那么Manim就是你的不二之选。

Manim 支持 Python 3.7 及以上版本,推荐Python3.8.

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

conda create --name manim python=3.8 # 创建虚拟环境
conda activate manim # 切换到此虚拟环境
pip install manimgl # 安装manim

安装完毕后在终端输入 manimgl,会出现如下的界面,说明安装完成。

2. Manim 基本使用

首先学会画一个基本的数学图形,如圆圈:

from manimlib import *

class SquareToCircle(Scene):
    def construct(self):
        circle = Circle()
        circle.set_fill(BLUE, opacity=0.5)
        circle.set_stroke(BLUE_E, width=4)

        self.add(circle)

编写完毕后,在终端里敲下这行命令:

manimgl 你的py文件名.py SquareToCircle

就能弹出一个图形界面,绘制完成:

你还可以操作弹出的这个窗口:

  • 滚动鼠标中键来上下移动画面
  • 按住键盘上 z 键的同时滚动鼠标中键来缩放画面
  • 按住键盘上 f 键的同时移动鼠标来平移画面
  • 按住键盘上 d 键的同时移动鼠标来改变三维视角
  • 按下键盘上 r 键恢复到最初的视角

最后,你可以通过按 q 来关闭窗口并退出程序。

接下来,我们学习如何让圆形变成方形:

# 公众号: Python实用宝典
from manimlib import *

class CircleToSquare(Scene):
    def construct(self):
        square = Square()
        square.set_fill(BLUE, opacity=0.5)
        square.set_stroke(BLUE_E, width=4)
        circle = Circle()

        self.play(ShowCreation(circle))
        self.wait()
        self.play(ReplacementTransform(circle, square))
        self.wait()

ShowCreation: 演示圆圈绘制过程。

ReplacementTransform: 延时从第一个参数的图形变化到第二个参数的图形的过程。

self.wait(): 等待上个play操作执行完成。

终端运行命令:

manimgl 你的py文件名.py CircleToSquare

效果如下:

再来一个复杂一点的演示,增加拉伸、旋转和变换:

# 公众号: Python实用宝典
from manimlib import *

class CircleToSquare(Scene):
    def construct(self):
        square = Square()
        square.set_fill(BLUE, opacity=0.5)
        square.set_stroke(BLUE_E, width=4)
        circle = Circle()

        self.play(ShowCreation(circle))
        self.wait()
        self.play(ReplacementTransform(circle, square))
        self.wait()
        # 在水平方向上拉伸到四倍
        self.play(square.animate.stretch(4, dim=0))
        self.wait()
        # 旋转90°
        self.play(Rotate(square, TAU / 4))
        self.wait()
        # 在向右移动2单位同时缩小为原来的1/4
        self.play(square.animate.shift(2 * RIGHT), square.animate.scale(0.25))
        self.wait()
        # 为了非线性变换,给square增加10段曲线(不会播放动画)
        square.insert_n_curves(10)
        # 给square上的所有点施加f(z)=z^2的复变换
        self.play(square.animate.apply_complex_function(lambda z: z**2))
        self.wait()

square.animate.stretch: 将图形拉伸第一个参数的倍数,第二个维度指明方向,dim=0为水平方向,dim=1为垂直方向。

square.animate.shift: 可以调整图形位置和大小。

square.animate.apply_complex_function: 增加函数复变换。

效果如下:

3. Manim 坐标轴与函数图像

想要实现函数图像绘制,我们需要先添加坐标轴:

# 公众号: Python实用宝典
from manimlib import *

class GraphExample(Scene):
    def construct(self):
        axes = Axes((-3, 10), (-1, 8))
        axes.add_coordinate_labels()

        self.play(Write(axes, lag_ratio=0.01, run_time=1))

运行以下命令显示坐标轴:

manimgl 你的py文件名.py GraphExample

坐标轴绘制完成后,就可以开始绘制图像了:

class GraphExample(Scene):
    def construct(self):
        axes = Axes((-3, 10), (-1, 8))
        axes.add_coordinate_labels()

        self.play(Write(axes, lag_ratio=0.01, run_time=1))

        # Axes.get_graph会返回传入方程的图像
        sin_graph = axes.get_graph(
            lambda x: 2 * math.sin(x),
            color=BLUE,
        )
        # 默认情况下,它在所有采样点(x, f(x))之间稍微平滑地插值
        # 但是,如果图形有棱角,可以将use_smoothing设为False
        relu_graph = axes.get_graph(
            lambda x: max(x, 0),
            use_smoothing=False,
            color=YELLOW,
        )
        # 对于不连续的函数,你可以指定间断点来让它不试图填补不连续的位置
        step_graph = axes.get_graph(
            lambda x: 2.0 if x > 3 else 1.0,
            discontinuities=[3],
            color=GREEN,
        )

        # Axes.get_graph_label可以接受字符串或者mobject。如果传入的是字符串
        # 那么将将其当作LaTeX表达式传入Tex中
        # 默认下,label将生成在图像的右侧,并且匹配图像的颜色
        sin_label = axes.get_graph_label(sin_graph, "\\sin(x)")
        relu_label = axes.get_graph_label(relu_graph, Text("ReLU"))
        step_label = axes.get_graph_label(step_graph, Text("Step"), x=4)

        self.play(
            ShowCreation(sin_graph),
            FadeIn(sin_label, RIGHT),
        )
        self.wait(2)
        self.play(
            ReplacementTransform(sin_graph, relu_graph),
            FadeTransform(sin_label, relu_label),
        )
        self.wait()
        self.play(
            ReplacementTransform(relu_graph, step_graph),
            FadeTransform(relu_label, step_label),
        )
        self.wait()

        parabola = axes.get_graph(lambda x: 0.25 * x**2)
        parabola.set_stroke(BLUE)
        self.play(
            FadeOut(step_graph),
            FadeOut(step_label),
            ShowCreation(parabola)
        )
        self.wait()

        # 你可以使用Axes.input_to_graph_point(缩写Axes.i2gp)来找到图像上的一个点
        dot = Dot(color=RED)
        dot.move_to(axes.i2gp(2, parabola))
        self.play(FadeIn(dot, scale=0.5))

        # ValueTracker存储一个数值,可以帮助我们制作可变参数的动画
        # 通常使用updater或者f_always让其它mobject根据其中的数值来更新
        x_tracker = ValueTracker(2)
        f_always(
            dot.move_to,
            lambda: axes.i2gp(x_tracker.get_value(), parabola)
        )

        self.play(x_tracker.animate.set_value(4), run_time=3)
        self.play(x_tracker.animate.set_value(-2), run_time=3)
        self.wait()

在这份代码中,我们先绘制了Sinx的图像,通过 ReplacementTransform 和 FadeTransform 转换成 ReLu 函数,然后通过同样的步骤转换成了Step图像。最后实现点在曲线上的移动。

manimgl 你的py文件名.py GraphExample

效果如下:

如果在运行的时候你出现了这样的错误:

请下载安装MiKTex和dvisvgm.

MiKTex: https://miktex.org/download

Dvisvgm: https://dvisvgm.de/Downloads/

还有更多有趣的绘制案例,你可以在Manim官网上学习:

https://docs.manim.org.cn/getting_started/example_scenes.html

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

Altair 一个漂亮易用的统计可视化库,甚至可拖动计数!

Altair 是一个基于Jupyter Notebook的强大可视化库。它提供了强大而简洁的可视化语法,使我们能够快速构建各种统计可视化图表。

通过下面10行代码,你就能创建一个可交互的散点图:

import altair as alt

from vega_datasets import data
cars = data.cars()

alt.Chart(cars).mark_point().encode(
    x='Horsepower',
    y='Miles_per_Gallon',
    color='Origin',
).interactive()

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install altair vega_datasets

2.Altair 基本使用

Altair 中的数据是围绕 Pandas Dataframe 构建的。

我们首先导入 Pandas 并创建一个简单的 DataFrame 以进行可视化,a 列中有一个分类变量,b 列有一个数值变量:

import pandas as pd
data = pd.DataFrame({'a': list('CCCDDDEEE'),
                     'b': [2, 7, 4, 1, 2, 6, 8, 4, 7]})

Altair 中的基本对象是Chart,它将上述的数据作为单个参数:

import altair as alt
chart = alt.Chart(data)

到目前为止,我们已经定义了 Chart 对象,但是我们还没有告诉图表对数据任何事情。接下来会出现。

有了这个图表对象,我们现在可以指定我们希望如何可视化数据,比如作为点:

alt.Chart(data).mark_point()

然后对数据进行编码,比如指定 a 列为x,b列为y:

alt.Chart(data).mark_point().encode(
    x='a', y='b'
)

效果如下:

如果你希望聚合求得某列得平均值,你还可以这么做:

alt.Chart(data).mark_point().encode(
    x='a',
    y='average(b)'
)

如果你希望使用柱状图,只需要把mark_point改为mark_bar:

alt.Chart(data).mark_bar().encode(
    x='a',
    y='average(b)'
)

还可以获得水平柱状图,我们只需要把x和y对调一下:

alt.Chart(data).mark_bar().encode(
    y='a',
    x='average(b)'
)

除了点状图和柱状图,Altair 还支持几十种图表类型:

更多的图表类型请在官网查看:

https://altair-viz.github.io/gallery/index.html

3.高级使用

你可以给图表自定义你喜欢的颜色和对应的横坐标纵坐标标题:

alt.Chart(data).mark_bar(color='firebrick').encode(
    alt.Y('a', title='category'),
    alt.X('average(b)', title='avg(b) by category')
)

你还可以将图表保存为HTML:

chart = alt.Chart(data).mark_bar().encode(
    x='a',
    y='average(b)',
)
chart.save('chart.html')

如果你希望能够通过区间选择数据点并计数,你可以这么做:

import altair as alt
from vega_datasets import data

source = data.cars()

brush = alt.selection(type='interval')

points = alt.Chart(source).mark_point().encode(
    x='Horsepower',
    y='Miles_per_Gallon',
    color=alt.condition(brush, 'Origin', alt.value('lightgray'))
).add_selection(
    brush
)

bars = alt.Chart(source).mark_bar().encode(
    y='Origin',
    color='Origin',
    x='count(Origin)'
).transform_filter(
    brush
)

points & bars

跟牛逼的是,Altair还可以做多图表联动:

# 公众号:Python实用宝典 整合
import altair as alt
from vega_datasets import data

cars = data.cars.url
brush = alt.selection_interval()

chart = alt.Chart(cars).mark_point().encode(
    y='Horsepower:Q',
    color=alt.condition(brush, 'Origin:N', alt.value('lightgray'))
).properties(
    width=250,
    height=250
).add_selection(
    brush
)

chart.encode(x='Acceleration:Q') | chart.encode(x='Miles_per_Gallon:Q')

左边圈起来的 Acceleration 数据点,右边会对应显示其 Miles_per_Gallon 数据点:

除了这些,Altair还有更多的交互功能,比如选择框拖动、比例绑定、自动响应、表达式选择等等,你可以阅读 Altair 官网学习并使用:

https://altair-viz.github.io/user_guide/interactions.html

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

超级安全!Python Pillow合成多张图片到PDF格式

在日常生活中,经常会遇到需要提交身份证正反面证明资料的情况,而且这些网站大部分只接受pdf格式,这时候我们就需要把身份证正反面两张图片合成为一个pdf文件。

在macOS系统下,预览软件可以轻松做到这一点,同时打开图片到一个预览窗口下,点击导出PDF就能成功导出。但是Windows系统就没有这么方便的软件可以实现这一点,网上有很多合成PDF的网站,但是这些网站无一例外需要上传PDF进行合成,个人认为非常地不安全。

因此,最安全的方法,还是我们自己写一个Python脚本实现合成功能。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install pillow

2.Pillow 合成PDF原理

Pillow模块,即PIL:Python Imaging Library,已经是Python平台事实上的图像处理标准库了。PIL功能非常强大,但API却非常简单易用。通过它,我们能很轻松地操作图像,并导出为不同格式。

首先来一个简单的示例,我们将打开一张图片,并将其保存为pdf格式:

from PIL import Image
import os


def convert_img_pdf(filepath, output_path):
    """
    转换图片为pdf格式

    Args:
        filepath (str): 文件路径
        output_path (str): 输出路径
    """
    output = Image.open(filepath)
    output.save(output_path, "pdf", save_all=True)
    
    
if __name__ == "__main__":
    convert_img_pdf("1.jpeg", "./test.pdf")

随便使用一张图片测试一下:

在运行代码后,它便成功地转化为了PDF文件:

几行代码便完成了这个转换,这个可比那些把照片上传到云端的网站安全多了。

3.多张照片合成PDF

有了前面照片转化PDF的基础知识,想要理解下面的多图合成PDF的代码就非常简单了。

其实就是使用了.save的一个特殊参数 append_images:

output.save(pdfFilePath, "pdf", save_all=True, append_images=sources)

通过把图片都存入到一个”sources”数组中,我们就能很轻易地合成这些图像到PDF中。

from PIL import Image
import os

def combine_imgs_pdf(folder_path, pdf_file_path):
    """
    合成文件夹下的所有图片为pdf

    Args:
        folder_path (str): 源文件夹
        pdf_file_path (str): 输出路径
    """
    files = os.listdir(folder_path)
    png_files = []
    sources = []
    for file in files:
        if 'png' in file or 'jpg' in file:
            png_files.append(folder_path + file)
    png_files.sort()

    output = Image.open(png_files[0])
    png_files.pop(0)
    for file in png_files:
        png_file = Image.open(file)
        if png_file.mode == "RGB":
            png_file = png_file.convert("RGB")
        sources.append(png_file)
    output.save(pdf_file_path, "pdf", save_all=True, append_images=sources)

if __name__ == "__main__":
    folder = r"G:\证件\\"
    pdfFile = r"G:\证件\身份证.pdf"
    combine_imgs_pdf(folder, pdfFile)

这样,只要将你的证件照都放在一个文件夹中,运行这个Python代码,它就能自动将这些证件合成到一个PDF中,并输出到你指定的路径。非常简单方便。

有需要的小伙伴,刚开那这份代码去试一下吧!在Python实用宝典后台回复 合成pdf 就能下载啦!

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python tiler 生成复古像素图片实战教程

像文字云一样,用各种小图拼出大的图片,构建一个像素风的世界,就像《我的世界》里一样,一定非常有趣,Python Tiler模块可以帮助我们做到这一点。
Python tiler 生成复古像素图片实战教程
还可以拿来做拼贴画、十字绣等装饰。
在这个名为 tiler 的 GitHub 开源项目里你就可以自动实现这一切,它刚刚开源一天,就已经涨到了 1500 星,增长速度肉眼可见。
https://github.com/nuno-faria/tiler
Tiler,意味瓦工,也就是用各种小元素作为 “瓦”,搭建出一张大图片。
项目预设了不少 “瓦”:有乐高、加号、圆形、@符号、心形、乘号、波浪线、横竖条、《我的世界》中的各种格子,以及曲别针形:
另外还有一组万圣节主题 icon,包括各种南瓜灯、小鬼头、蝙蝠、猫头鹰:
这些不同的 “瓦” 都可以设定大小颜色和角度,以适应不同的画面规格。
另外,你还可以设定整个画面中由多少种颜色构成和 “瓦片” 的大小,也就是马赛克的模糊程度。
你可以用不同材质的 “瓦片”,拼接出各种图案。
比如梵高的《星空》,项目中展示了 10×10、25×25、50×50 三种圆形拼成的规格:
10×10 的《星空》
25×25 的《星空》
50×50 的《星空》
有没有在 PS 里拖动高斯模糊半径控制条的感觉?
你也可以设置让构成图片的 “瓦片” 大小不一
也可以试试拿乐高积木来拼:
放大看,斑斓的星空,是这样的:
一个个小砖块,布满了乐高积木表面特有的圆形凸起。
嗯,要是真有这么大一片乐高,想想就爽歪歪。
(此处冲去乐高门店下单,金币 – 1000)
还有乘号版:
如果放大,你就会发现,这就是十字绣的图样啊!
这么大一副十字绣,色彩艳丽,斑斓交错,一看就可以玩很久,退休老母亲看到两眼发光。
就是绣完挂在家里,也和你北欧风 / 极简风 / 莫兰迪风 / 自如风的房间非常搭配,成为全场最吸睛的装饰画。
要是木有耐心,可以考虑一个迷你版:
还可以做成《我的世界》的样子
星空的细节如下:
你们能认识这些砖块都是啥么……

Python tiler 实战教程

如果想在自己电脑上运行的话,除了 Python 3 和 pip,你还需要装 OpenCV、numpy 和 tqdm。
之后,靠命令行就可以解决了。
你需要设置几个参数:
在 gen_tiles.py 中设置:
DEPTH:每个颜色通道中的分割数量 (ex: DEPTH = 4 -> 4 * 4 * 4 = 64 colors);
ROTATIONS:旋转列表,以度为单位,应用在原始图像上 (ex: [0, 90])。
在 tiler.py 中设置:
COLOR_DEPTH:每个颜色通道中的分割数量 (ex: COLOR_DEPTH = 4 -> 4 4 4 = 64 colors);
RESIZING_SCALES:应用于每个图块的比例 (ex: [1, 0.75, 0.5, 0.25]);
PIXEL_SHIFT:移动以创建每个框的像素数 (ex: (5,5)); if None, shift will be the same as the tile dimension);
OVERLAP_TILES:如果构成图像的 “瓦片” 可以重叠;
RENDER:渲染图像;
POOL_SIZE:多处理池大小;
IMAGE_TO_TILE:图像到瓦片(如果作为第一个参数传递则忽略);
TILES_FOLDER:瓦片文件夹(如果作为第二个 arg 传递则忽略);
OUT:结果图像文件名。

脑洞丰富的作者

这个项目的作者 ID 叫 nuno-faria,除了这个 Tiler 项目之外,他还开源过不少有趣的东西。
有一个用 Java 写的推箱子:
像素风满满的桌面足球:
还有俄罗斯方块、弹球等许多种,个个都还蛮有意思的~
如此极具创造力的作者,实在令人佩服,有兴趣的话,可以到其主页深入了解一下:
https://github.com/nuno-faria
本文转自:量子位,作者郭一璞

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

Cufflinks实战教程—1行python代码就可实现炫酷可视化

作者:python数据分析之禅

来源:小dull鸟

之前画图一直在用matlibplot、pyecharts,最近学习了一个新的可视化库–cufflinks,用了两天我已经深深爱上它了

主要是因为它用法简单、图形漂亮、代码量少,用一两行代码,就能画出非常漂亮的图形

下面我们一起来看看吧!

1.用法简单

cufflinks库主要和dataFrame数据结合使用,绘图函数就是 dataFrame.iplot,记住这个就行了,但是 iplot 函数里的参数很多,一些参数说明如下:

1. kind:图的种类,如 scatter、pie、histogram 等
2. mode:lines、markers、lines+markers,分别表示折线、点、折线和点
3. colors:轨迹对应的颜色
4. dash:轨迹对应的虚实线,solid、dash、dashdot 三种
5. width:轨迹的粗细
6. xTitle:横坐标名称
7. yTitle:纵坐标的名称
8. title:图表的标题

如下图,df为随机生成的dataFrame数据,kind=’bar’表示柱状图,title代表标题,xTitle命名X轴,yTitle命名Y轴:

import pandas as pd
import numpy as np
import cufflinks as cf
df=pd.DataFrame(np.random.rand(124), columns=['a''b''c''d'])
df.iplot(kind ='bar',title='示例', xTitle = 'X轴', yTitle ='Y轴')

2.少量代码就能画出非常漂亮的图形

cufflinks为我们提供了丰富的主题样式,支持包括polar、pearl、henanigans、solar、ggplot、space和white等7种主题。

折线图

cf.datagen.lines(4,10).iplot(mode='lines+markers',theme='solar')

cufflinks使用datagen生成随机数,figure定义为lines形式,cf.datagen.lines(2,10)的具体形式如下:

cf.datagen.lines(2,10)  #2代表2组,10代表10天
  WCB.EH OAA.CQ
2015-01-01 -0.052580 -0.351618
2015-01-02 1.056254 -1.476417
2015-01-03 0.078017 1.129168
2015-01-04 0.282141 0.908655
2015-01-05 0.960537 -0.223996
2015-01-06 1.420355 0.212851
2015-01-07 2.266144 0.358502
2015-01-08 0.008034 1.086130
2015-01-09 1.876946 2.226895
2015-01-10 1.855625 2.852383

散点图

df = pd.DataFrame(np.random.rand(504), columns=['a''b''c''d'])
df.iplot(kind='scatter',mode='markers',colors=['orange','teal','blue','yellow'],size=20,theme='solar')

气泡图

df.iplot(kind='bubble',x='a',y='b',size='c',theme='solar')

subplots 子图

df=cf.datagen.lines(4)
df.iplot(subplots=True,shape=(4,1),shared_xaxes=True,vertical_spacing=.02,fill=True,theme='ggplot')

箱形图

cf.datagen.box(20).iplot(kind='box',legend=False,theme='ggplot')

 

直方图

df.iloc[:,0:3].iplot(kind='histogram')

 

3D图

cf.datagen.scatter3d(5,4).iplot(kind='scatter3d',x='x',y='y',z='z',text='text',categories='categories')

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

Folium — 可能是 Python 最强的绘制地图神器

今天给大家介绍一个非常 NB 的Python 库,专门用来绘制地图的,它叫 Folium.

1. Folium简介

Folium是一个基于leaflet.js的Python地图库,其中,Leaflet是一个非常轻的前端地图可视化库。

即可以使用Python语言调用Leaflet的地图可视化能力。它不单单可以在地图上展示数据的分布图,还可以使用Vincent/Vega在地图上加以标记。

Folium可以让你用Python强大生态系统来处理数据,然后用Leaflet地图来展示。

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

2. Folium的使用

地图的生成

img

folium.folium.Map()详解

folium.folium.Map(location=None, width='100%', height='100%', left='0%', top='0%', position='relative', tiles='OpenStreetMap', attr=None, min_zoom=0, max_zoom=18, zoom_start=10, min_lat=-90, max_lat=90, min_lon=-180, max_lon=180, max_bounds=False, crs='EPSG3857', control_scale=False, prefer_canvas=False, no_touch=False, disable_3d=False, png_enabled=False, zoom_control=True, **kwargs)

参数说明

  • location (tuple or list, default None):纬度和经度

  • width (pixel int or percentage string (default: ‘100%’)):地图宽度

  • height (pixel int or percentage string (default: ‘100%’)):地图高度

  • tiles (str, default ‘OpenStreetMap’) :瓦片名称或使用TileLayer classass.

  • min_zoom (int, default 0):地图可缩放的最小级别

  • max_zoom (int, default 18):地图可缩放的最大级别

  • zoom_start (int, default 10) :地图的初始缩放级别

  • attr (string, default None):当使用自定义瓦片时,传入自定义瓦片的名词

  • crs (str, default ‘EPSG3857’) :投影坐标系标识

  • EPSG3857: Web墨卡托投影后的平面地图,坐标单位为米。大部分国外地图使用的时该标准。

  • EPSG4326: Web墨卡托投影后的平面地图,但仍然使用WGS84的经度、纬度表示坐标。

  • EPSG3395: 墨卡托投影,主要用于航海图

  • Simple: 简单的x,y匹配,用于自定义瓦片(比如游戏地图)

  • control_scale (bool, default False) :是否在地图上显示缩放标尺

  • prefer_canvas (bool, default False):强制使用Canvas渲染

  • no_touch (bool, default False) :是否允许触摸事件

  • disable_3d (bool, default False) :强制使用CSS 3D效果

  • zoom_control (bool, default True) :是否要限制zoom操作

  • **kwargs:Leaflets地图类的其他参数: https://leafletjs.com/reference-1.5.1.html#map

“tiles”参数可选值:

  • “OpenStreetMap”

  • “Mapbox Bright” (Limited levels of zoom for free tiles)

  • “Mapbox Control Room” (Limited levels of zoom for free tiles)

  • “Stamen” (Terrain, Toner, and Watercolor)

  • “Cloudmade” (Must pass API key)

  • “Mapbox” (Must pass API key)

  • “CartoDB” (positron and dark_matter)

“tiles”的自定义设置:

 

img

地球上同一个地理位置的经纬度,在不同的坐标系中,会有少量偏移,国内目前常见的坐标系主要分为三种:

  • 地球坐标系——WGS84:常见于GPS设备,Google地图等国际标准的坐标体系。

  • 火星坐标系——GCJ-02:中国国内使用的被强制加密后的坐标体系,高德坐标就属于该种坐标体系。

  • 百度坐标系——BD-09:百度地图所使用的坐标体系,是在火星坐标系的基础上又进行了一次加密处理。

所以在设置“tiles”时需要考虑目前手中得经纬度属于那种坐标系。

由于投影坐标系中没有GCJ-02和BD-09对应的标识,所以在自定义瓦片时主要经纬度能匹配上,crs中的设置可保持不变。更多详情介绍请看:瓦片坐标系学习

如果需要将地图保存,只需执行:m.save(“map.html”) 即可。

添加点、线、面要素

添加点

import folium
m = folium.Map(location=[39.917834116.397036], zoom_start=13, width='50%',height='50%', zoom_control='False',
               tiles='http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}&ltype=6',attr='AutoNavi')

tooltip ='请点击我查看该点信息'
folium.Marker([39.937282,116.403187], popup='南锣鼓巷',tooltip=tooltip).add_to(m)
folium.Marker([39.917834,116.397036], popup='故宫',tooltip=tooltip).add_to(m)
folium.Marker([39.928614,116.391746], popup='北海公园', tooltip=tooltip, icon=folium.Icon(color='red')).add_to(m)
folium.Marker([39.942143,116.382590], popup='后海公园', tooltip=tooltip, icon=folium.Icon(color='green', prefix='fa', icon='taxi')).add_to(m)

m

 

img

Folium.Icon类可以设置color, icon_color, icon, angle, prefix这5个参数:

  • color的可选项包括:[‘red’, ‘blue’, ‘green’, ‘purple’, ‘orange’, ‘darkred’, ‘lightred’, ‘beige’, ‘darkblue’, ‘darkgreen’, ‘cadetblue’, ‘darkpurple’, ‘white’, ‘pink’, ‘lightblue’, ‘lightgreen’, ‘gray’, ‘black’, ‘lightgray’] ,或者HTML颜色代码

  • icon_color同上

  • icon可以在Font-Awesome网站中找到对应的名字,并设置prefix参数为’fa’

  • angle以度为单位设置

其他:

m.add_child(folium.LatLngPopup()) #显示鼠标点击点经纬度
m.add_child(folium.ClickForMarker(popup='Waypoint')) # 将鼠标点击点添加到地图上

添加圆

folium.Circle(
    radius=300,
    location=[39.928614,116.391746],
    popup='北海公园',
    color='crimson',
    fill=False,
).add_to(m)
folium.CircleMarker(
    location=[39.942143,116.382590],
    radius=50,
    popup='后海公园',
    color='#3186cc',
    fill=True,
    fill_color='#3186cc'
).add_to(m)

 

img

Circle和CircleMarker的不同:CircleMarker的radius一个单位是像素,Circle的一个单位时米

添加线段

folium.PolyLine([
    [39.917834,116.397036],
    [39.928614,116.391746],
    [39.937282,116.403187],
    [39.942143,116.382590]
],color='red').add_to(m)

 

img

添加多边形

folium.Marker([39.917834,116.397036], popup='故宫').add_to(m)
folium.Marker([39.928614,116.391746], popup='北海公园').add_to(m)
folium.Marker([39.937282,116.403187], popup='南锣鼓巷').add_to(m)
folium.Marker([39.942143,116.382590], popup='后海公园').add_to(m)

folium.Polygon([
    [39.917834,116.397036],
    [39.928614,116.391746],
    [39.942143,116.382590],
    [39.937282,116.403187],
],color='blue', weight=2, fill=True, fill_color='blue', fill_opacity=0.3).add_to(m)

 

img

Folium的其他高级应用

在地图上显示前200条犯罪数据

import folium
import pandas as pd

san_map = folium.Map(location=[37.77-122.42], zoom_start=12,width='50%',height='50%')

# cdata = pd.read_csv('https://cocl.us/sanfran_crime_dataset')
cdata = pd.read_csv('Police_Department_Incidents_-_Previous_Year__2016_.csv'#犯罪数据,包含犯罪所在经纬度

# get the first 200 crimes in the cdata
limit = 200
data = cdata.iloc[0:limit, :]
# Instantiate a feature group for the incidents in the dataframe
incidents = folium.map.FeatureGroup()
# Loop through the 200 crimes and add each to the incidents feature group
for lat, lng, in zip(cdata.Y, data.X):
    incidents.add_child(
        folium.CircleMarker(
            [lat, lng],
            radius=7# define how big you want the circle markers to be
            color='yellow',
            fill=True,
            fill_color='red',
            fill_opacity=0.4
        )
    )

san_map.add_child(incidents)

 

img

统计区域犯罪总数

from folium import plugins

# let's start again with a clean copy of the map of San Francisco
san_map = folium.Map(location=[37.77-122.42], zoom_start=12,width='50%',height='50%')

# instantiate a mark cluster object for the incidents in the dataframe
incidents = plugins.MarkerCluster().add_to(san_map)

# loop through the dataframe and add each data point to the mark cluster
for lat, lng, label, in zip(data.Y, data.X, cdata.Category):
    folium.Marker(
        location=[lat, lng],
        icon=None,
        popup=label,
    ).add_to(incidents)

# add incidents to map
san_map.add_child(incidents)

 

img

以热力图的方式呈现

from folium.plugins import HeatMap

san_map = folium.Map(location=[37.77-122.42], zoom_start=12,width='50%',height='50%')

# Convert data format
heatdata = data[['Y','X']].values.tolist()

# add incidents to map
HeatMap(heatdata).add_to(san_map)

san_map

 

img

在地图上呈现GeoJSON边界数据

import json
import requests

# url = 'https://cocl.us/sanfran_geojson'
url = 'san-francisco.geojson'
san_geo = f'{url}'
san_map = folium.Map(location=[37.77-122.42], zoom_start=12,width='50%',height='50%')
folium.GeoJson(
    san_geo,
    style_function=lambda feature: {
        'fillColor''#ffff00',
        'color''blue',
        'weight'2,
        'dashArray''5, 5'
    }
).add_to(san_map)

san_map

 

img

在GeoJSON上绘制Choropleth分级着色图

# Count crime numbers in each neighborhood
disdata = pd.DataFrame(cdata['PdDistrict'].value_counts())
disdata.reset_index(inplace=True)
disdata.rename(columns={'index':'Neighborhood','PdDistrict':'Count'},inplace=True)

san_map = folium.Map(location=[37.77-122.42], zoom_start=12,width='50%',height='50%')

folium.Choropleth(
    geo_data=san_geo,
    data=disdata,
    columns=['Neighborhood','Count'],
    key_on='feature.properties.DISTRICT',
    #fill_color='red',
    fill_color='YlOrRd',
    fill_opacity=0.7,
    line_opacity=0.2,
    highlight=True,
    legend_name='Crime Counts in San Francisco'
).add_to(san_map)

san_map

 

img

3. 各地图提供商瓦片服务地图规则

高德地图

目前高德的瓦片地址有如下两种:

  • http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=7&ltype=1

  • http://webst0{1-4}.is.autonavi.com/appmaptile?style=7&x={x}&y={y}&z={z}

前者是高德的新版地址,后者是老版地址。

高德新版的参数:

  • lang:可以通过zh_cn设置中文,en设置英文

  • size:基本无作用

  • scl:瓦片尺寸控制,1=256,2=512

  • style:设置影像和路网,style=6为卫星图,style=7为街道图,style=8为标注图

  • ltype:线性控制,增加后,只对地图要素进行控制,没有文字注记,要素多少,是否透明

这些规律并不是绝对的,有可能有的组合某些参数不起作用。

谷歌地图

目前谷歌的瓦片地址也存在两种:

  • 国内:http://mt{0-3}.google.cn/vt/lyrs=m&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}

  • 国外:http://mt{0-3}.google.com/vt/lyrs=m&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}

参数详解:

  • lyrs = 类型

  • h = roads only 仅限道路

  • m = standard roadmap 标准路线图

  • p = terrain 带标签的地形图

  • r = somehow altered roadmap 某种改变的路线图

  • s = satellite only 仅限卫星

  • t = terrain only 仅限地形

  • y = hybrid 带标签的卫星图

  • gl = 坐标系

  • CN = 中国火星坐标系

  • hl = 地图文字语言

  • zh-CN = 中文

  • en-US = 英文

  • x = 瓦片横坐标

  • y = 瓦片纵坐标

  • z = 缩放级别 卫星图0-14,路线图0-17

百度地图

百度当前的瓦片地址:

  • http://online{0-4}.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl&udt=202004151&scaler=2&p=0

  • http://api{0-3}.map.bdimg.com/customimage/tile?&x={x}&y={y}&z={z}&udt=20180601&scale=1

  • http://its.map.baidu.com:8002/traffic/TrafficTileService?level={z}&x={x}&y={y}&time=1373790856265&label=web2D&;v=017

备注:瓦片地址中的x和y对应的并不是经纬度值,而是瓦片编号,中国主要地图商的瓦片编号流派:

目前百度的瓦片编号比较特殊,Folium暂不支持。

其他参考资料:

  • https://github.com/geometalab/pyGeoTile

  • https://github.com/anzhihun/OpenLayers3Primer/blob/master/ch05/05-03.md

  • http://www.winseliu.com/blog/2018/01/30/map-started-guide/

  • https://github.com/CntChen/tile-lnglat-transform

腾讯地图

腾讯地图的瓦片地图URL格式:

  • http://rt1.map.gtimg.com/realtimerender?z={z}&x={x}&y={y}&type=vector&style=0

由于腾讯地图使用的瓦片编码时TMS,所以使用时需要额外的设置。具体如下:

 

其他底图

 

  • {0,1,2,3}代表了url的subDomain,在请求时会随机的在url中使用mt0、mt1、mt2、mt3。{z}代表zoom,即缩放级别,{x}代表列号,{y}代表行号。

  • GeoQ 官网有公开的多个基于 ArcGIS 的地图服务,均可使用,详见https://map.geoq.cn/arcgis/rest/services

4. 参考链接:

  • https://leafletjs.com/

  • https://python-visualization.github.io/folium/

  • http://openwhatevermap.xyz/

作者:钱魏Way
原文:https://www.biaodianfu.com/folium.html

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 将你的照片转化为“速写”

Photo-Sketching 一个能将照片的轮廓识别出来并将其转化为“速写”型图像的开源模块。

比如,这只小狗:

经过模型的转化,会变成卡通版的小狗:

当然,也不是什么照片都处理的好,比如这个风景画就不行:

摇身一变,成了抽象风格:

非常好,这很人工智能。

这个模块的使用也相对简单,下面给大家带上全方面的教程:

1.虚拟环境及依赖安装

这个项目推荐大家直接用Anaconda进行环境的构建和开发:Python数据分析与挖掘好帮手—Anaconda,因为作者提供了一个 environment.yml 文件,你只需要输入以下命令,就能一键安装环境和依赖:

conda env create -f environment.yml

此外,推荐大家用VSCode编辑器来编写像这样的小型Python项目:Python 编程的最好搭档—VSCode 详细指南

2.下载预训练模型

作者已经训练好了一些识别模型方便大家使用,可以在下列地址找到:
https://drive.google.com/file/d/1TQf-LyS8rRDDapdcTnEgWzYJllPgiXdj/view

作者使用的是谷歌硬盘,如果你无法科学上网,可以使用我提供的完整源代码+预训练模型,在后台回复:sketch 即可获取。

下载完成后解压文件,将 latest_net_D.pth 和 latest_net_G.pth 放置到 Checkpoints 文件夹下:

3.运行预训练模型

接下来,我们需要修改使用预训练模型的启动脚本,这些脚本都放在 PhotoSketch\scripts 下,我们需要使用的是 test_pretrained.cmd 或者 test_pretrained.sh 这两个脚本。

如果你是 windows 系统,请修改 test_pretrained.cmd 脚本,重点是dataDir、results_dir、checkpoints_dir:

dataDir 指向到 PhotoSketch 所在的文件夹目录,如果你是跟我一样这么配的,results_dir 只需要配成 %dataDir%\PhotoSketch\Results\ 即可,checkpoints_dir 则为 %dataDir%\PhotoSketch\Checkpoints\

如果你是macOS或者Linux,则修改 test_pretrained.sh 文件,修改方法与上面windows 的一样,只不过 反斜杠 “\” 要换成 斜杆 “/” 。

修改完脚本后,打开命令行/终端,输入以下命令,就会将你 PhotoSketch\examples 目录下的文件转化为“速写”。

windows:

scripts\test_pretrained.cmd

Linux/Macos:

./scripts/test_pretrained.sh

转化结果可以在 PhotoSketch\Results 中看到,如下两图所示。

待转化目录:

转化后:

可以看到效果其实不是非常好,由于是作者预训练的模型,所以效果不好也正常,如果大家需要的话,可以自己针对性地拿一些图像训练模型,并针对性地做识别,这样做效果才是最好的。

你需要训练或测试自己的模型也非常简单:

  • 在仓库的根目录中,运行 scripts/train.sh 可以训练模型
  • 在仓库的根目录中,运行 scripts/test.sh 可以测试val集或测试集

当然训练过程肯定没这么简单,你会遇到不少问题,但是我相信大部分都是存放图片的目录结构上的问题,大家如果有兴趣可以动手试试。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

表白神器!使用 Python PIL 库绘制爱心墙!

 

一、爱心墙

通过爬虫搜集到粉丝的头像,然后利用 PIL 库拼接出爱心墙的形状

二、代码分析

1.头像爬取

在个人中心点击我的粉丝便可以看到自己的粉丝

通过抓包可知对应的接口为:

url = 'https://me.csdn.net/api/relation/index?pageno=1&pagesize=20&relation_type=fans' # 接口地址

那么,可以定义一个函数来获取粉丝的信息:

def get_fansInfo():
    '''
    获取粉丝相关信息
    '''

    url = 'https://me.csdn.net/api/relation/index?pageno=%d&pagesize=%d&relation_type=fans' # 接口地址
    cookies = {} # 用户登陆cookies
    headers = {  # 请求头
        'User-Agent''Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0',
        'Accept''application/json, text/plain, */*',
        'Accept-Language''zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
        'Referer''https://i.csdn.net/',
        'Origin''https://i.csdn.net',
        'Connection''keep-alive',
        'TE''Trailers',
    }
    # 获取粉丝总数
    res = requests.get(url%(1,10),headers=headers,cookies=cookies)
    res_json = res.json()
    N_fans = res_json['data']['data_all']
    print('一共有%d个粉丝'%N_fans)
    # 获取全部粉丝数据
    res = requests.get(url%(1,N_fans),headers=headers,cookies=cookies)
    res_json = res.json()
    return res_json

在返回的数据中,包括一个avatar字段,这个就是用户的头像地址

拿到头像地址之后便可以定义个函数来下载相应的头像:

def download_avatar(username,url):
    '''
    下载用户头像
    '''

    savePath = './avatars' # 头像存储目录
    res = requests.get(url)
    with open('%s/%s.jpg'%(savePath,username),'wb'as f:
        f.write(res.content)

定义主函数,运行代码:

if __name__ == '__main__':
    fans = get_fansInfo()
    for f in fans['data']['list']:
        username = f['fans'# 用户名
        url = f['avatar']    # 头像地址
        download_avatar(username,url)
        print('用户"%s"头像下载完成!'%username)

最后我成功将所有头像下载到本地文件夹中:

2.头像去重

聪明的你应该已经发现,在爬取到的头像中有两个头像重复出现(想必这应该是官方默认头像):

 

 

 

于是乎,为了更好地展示,我们得对头像进行去重

这里我们利用每个头像的 MD5 值来进行去重,然后定义函数来计算头像的 MD5 值

def get_md5(filename):
    '''
    获取文件的md5值cls
    '''

    m = hashlib.md5()
    with open(filename,'rb'as f:
        for line in f:
            m.update(line)
    md5 = m.hexdigest()
    return md5

说明:每个文件通过 MD5 计算出摘要,理论来说只有文件完全一致 MD5 值才会相同。因此,可以利用它来进行图像的去重

对头像进行去重,并把去重后的头像保存到另外的目录中:

# 照片去重
md5_already = [] # 用于存储已经记录过的图片,便于去重
for filename in os.listdir('./avatars'):
    md5 = get_md5('./avatars/'+filename)  
    if md5 not in md5_already:
        md5_already.append(md5)
        shutil.copyfile('./avatars/'+filename,'./avatars(dr)/'+filename)

3.绘制爱心墙

这一步,主要是利用 PIL 库来把头像按照设定的框架拼接成一个更大的图片

首先导入相关库:

import os
import random
import numpy as np
import PIL.Image as Image

定义绘制图形的框架(用二维数组表示):

FRAME = [[0,1,1,0,0,0,0,1,1,0],
         [1,1,1,1,0,0,1,1,1,1],
         [1,1,1,1,1,1,1,1,1,1],
         [1,1,1,1,1,1,1,1,1,1],
         [0,1,1,1,1,1,1,1,1,0],
         [0,0,1,1,1,1,1,1,0,0],
         [0,0,0,1,1,1,1,0,0,0],
         [0,0,0,0,1,1,0,0,0,0]]

这里大家完全可以发挥自己的想象,画你心中所想

其中,0 表示不进行填充,1 表示用头像进行填充。

定义相关参数,包括每张用于填充的头像的大小、每个点位填充的次数等

# 定义相关参数
SIZE = 50 # 每张图片的尺寸为50*50
N = 2     # 每个点位上放置2*2张图片

# 计算相关参数
width = np.shape(FRAME)[1]*N*SIZE  # 照片墙宽度
height = np.shape(FRAME)[0]*N*SIZE # 照片墙高度
n_img = np.sum(FRAME)*(N**2)       # 照片墙需要的照片数
filenames = random.sample(os.listdir('./avatars(dr)'),n_img) # 随机选取n_img张照片
filenames = ['./avatars(dr)/'+f for f in filenames]

遍历 FRAME,用头像对背景图片进行填充:

# 绘制爱心墙
img_bg = Image.new('RGB',(width,height)) # 设置照片墙背景
i = 0
for y in range(np.shape(FRAME)[0]):
    for x in range(np.shape(FRAME)[1]):
         if FRAME[y][x] == 1# 如果需要填充
             pos_x = x*N*SIZE # 填充起始X坐标位置
             pos_y = y*N*SIZE # 填充起始Y坐标位置
             for yy in range(N):
                 for xx in range(N):
                     img = Image.open(filenames[i])
                     img = img.resize((SIZE,SIZE),Image.ANTIALIAS)
                     img_bg.paste(img,(pos_x+xx*SIZE,pos_y+yy*SIZE))
                     i += 1
                
# 保存图片
img_bg.save('love.jpg')

写在最后

天气逐渐微寒,愿这次小小的表白可以给你们带来些许暖意;愿风雨兼程,不忘归途;愿身能似月亭亭,千里伴君行!

转自AirPython.

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

Django 展示可视化图表的几种方式对比

1. 前言

使用 Django 进行 Web 开发时,经常有需要展示图表的需求,以此来丰富网页的数据展示,常见方案包含:Highcharts、Matplotlib、Echarts、Pyecharts,其中后 2 种方案使用频率更高

本篇文章将聊聊 Django 结合 Echarts、Pyecharts 实现图表可视化的具体流程

2. Echarts

Echarts 是百度开源的一个非常优秀的可视化框架,它可以展示非常复杂的图表类型

以展示简单的柱状图为例,讲讲 Django 集成 Echarts 的流程

首先,在某个 App 的 views.py 编写视图函数

当请求方法为 POST 时,定义柱状图中的数据值,然后使用 JsonResponse 返回数据

from django.http import JsonResponse
from django.shortcuts import render


def index_view(request):
    if request.method == "POST":

        # 柱状图的数据
        datas = [52036101020]

        # 返回数据
        return JsonResponse({'bar_datas': datas})
    else:
        return render(request, 'index.html', )

在模板文件中,导入 Echarts 的依赖

PS:可以使用本地 JS 文件或 CDN 加速服务

{#导入js和echarts依赖#}
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.0.2/echarts.common.js"></script>

然后,重写 window.onload 函数,发送一个 Ajax 请求给后端,利用 Echarts 将返回结果展示到图表中去

<script>
    // 柱状图
    function show_bar(data{

        //控件
        var bar_widget = echarts.init(document.getElementById('bar_div'));

        //设置option
        option = {
            title: {
                text'简单的柱状图'
            },
            tooltip: {},
            legend: {
                data: ['销量']
            },
            xAxis: {
                type'category',
                data: ["衬衫""羊毛衫""雪纺衫""裤子""高跟鞋""袜子"]
            },
            yAxis: {
                type'value'
            },
            series: [{
                data: data,
                type'bar'
            }]
        };

        bar_widget.setOption(option)
    }

    //显示即加载调用
    window.onload = function () {
        //发送post请求,地址为index(Jquery)
        $.ajax({
            url"/",
            type"POST",
            data: {},
            successfunction (data{
                // 柱状图
                show_bar(data['bar_datas']);

                //后端返回的结果
                console.log(data)
            }
        })
    }
</script>

最后,编写路由 URL,运行项目

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('',include('index.urls')),
    path('admin/', admin.site.urls),
]

发现,首页展示了一个简单的柱状图

更多复杂的图表展示可以参考官方

https://echarts.apache.org/examples/zh/index.html

3. Pyecharts

Pyecharts 是一款使用 Python 对 Echarts 进行再次封装后的开源框架

相比 Echarts,Django 集成 Pyecharts 更快捷、方便

Django 集成 Pyecharts 只需要 4 步

3-1  安装依赖

# 安装依赖
pip(3) install pyecharts

3-2  拷贝 pyecharts 的模板文件到项目下

将虚拟环境中 pyecharts 的模板文件拷贝到项目的模板文件夹下

比如本机路径如下:

/Users/xingag/Envs/xh_log/lib/python3.7/site-packages/pyecharts/render/templates/

3-3  编写视图函数,渲染图表

在视图文件中,使用 pyecharts 库内置的类 Bar 创建一个柱状图

# Create your views here.
from django.http import HttpResponse
from jinja2 import Environment, FileSystemLoader
from pyecharts.globals import CurrentConfig

CurrentConfig.GLOBAL_ENV = Environment(loader=FileSystemLoader("./index/templates"))

from pyecharts import options as opts
from pyecharts.charts import Bar


# http://127.0.0.1:8000/demo/
def index(request):
    c = (
        Bar()
            .add_xaxis(["衬衫""羊毛衫""雪纺衫""裤子""高跟鞋""袜子"])
            .add_yaxis("商家A", [52036107590])
            .add_yaxis("商家B", [15251655488])
            .set_global_opts(title_opts=opts.TitleOpts(title="Bar-基本示例", subtitle="我是副标题"))
    )
    return HttpResponse(c.render_embed())

3-4  运行项目

运行项目,生成的柱状图如下:

这只是最简单的使用实例,更多复杂的图表及前后端分离、更新的例子

可以参考官网:

https://pyecharts.org/#/zh-cn/web_django?id=django-%e5%89%8d%e5%90%8e%e7%ab%af%e5%88%86%e7%a6%bb

4. 最后

文中介绍了 Django 快速集成 Echarts 和 Pyecharts 的基本步骤

实际项目中,一些复杂的图表、前后端分离数据更新可以参考官网去拓展

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典