分类目录归档:Python绘图

Python Pyecharts 可视化轻松展示交通拥堵情况

就在今天,我感受到了来自堵车的深深恶意。没有错!我今天被堵在路上近乎3个小时,美好的约会就这样化为泡影了。

我倒还真想看看这路到底能有多堵。于是,我爬取了各城市的拥堵数据,并将它们可视化:

特别说明:由于数据具有实时性,画图时已经过了高峰期,于是图上一片绿油油也并不奇怪。有感兴趣的客官,您接着往下看,待我给您慢慢分解。(ps.涉及到爬虫pyechartsflask等)

一、爬取拥堵指数

某度智慧交通提供了各个城市的拥堵指数的数据,我们只需要通过几行代码便可轻松抓取:

# 获取各城市的拥堵指数  
url = 'https://jiaotong.baidu.com/trafficindex/city/list' # 接口api  
res = requests.get(url)  
data = res.json()  

其中,url为获取数据的接口地址,通过简单的抓包分析便能知道。而data为返回后的数据,它包括很多字段,但是我们只需要提取其中的城市名拥堵指数即可:

# 提取数据  
citys = [i['cityname'for i in data['data']['list']] # 提取城市  
indexs = [float(i['index']) for i in data['data']['list']] # 提取对应的指数  

有了数据,接下来我们就可以将其可视化展示出来。

二、数据可视化

利用可视化神器pyecharts库绘制地图,并将城市以及对应的拥堵指数表示出来。其安装如下:

pip install pyecharts  

部分版本需要再安装额外的地图库,方法如下:

pip install echarts-countries-pypkg  
pip install echarts-cities-pypkg  
pip install echarts-china-provinces-pypkg   
pip install echarts-china-cities-pypkg  

首先定义地图:

geo = Geo()  
geo.add_schema(maptype = 'china'# 加入中国地图  

添加数据并进行相关设置:

geo.add('各城市拥堵指数', zip(citys,indexs), type_ = 'effectScatter'# 设置地图类型及数据  
geo.set_series_opts(label_opts = opts.LabelOpts(is_show = False))  #设置是否显示标签  

根据拥堵指数的大小进行分类,分别为畅通、缓行、拥堵、严重拥堵:

geo.set_global_opts(visualmap_opts = opts.VisualMapOpts(  
                    #max_ = 2.5, # 用于连续表示  
                    is_piecewise = True# 是否分段  
                    pieces = [{'min':1.0,'max':1.5,'label':'畅通','color':'#16CE95'},  
                              {'min':1.5,'max':1.8,'label':'缓行','color':'#F79D06'},  
                              {'min':1.8,'max':2.0,'label':'拥堵','color':'#D80304'},  
                              {'min':2.0,'max':2.5,'label':'严重拥堵','color':'#8F0921'}])) # 设置图例显示  

最后将地图保存在本地:

geo.render(path='各城市拥堵指数.html')  

到这里,我们就得到了文章一开始看到的那张图~

然而,由于拥堵数据是实时变化的,如果我每次都要去运行一次代码岂不是很麻烦?

很显然,机智的社会主义青年是不会这么做的,您接着往下看。

三、搭建展示网站

为了更加方便地将各城市拥堵情况展示出来,我决定搭建一个用于展示的网站。方法可以是各式各样的,在这里我选择了利用flask框架,简单快捷,完整代码回复堵车获得:

代码中,get_geo()为获取地图的函数,返回了pyecharts绘制的地图。在当前目录下创建templates文件夹,并创建模块文件geo.html,如下:

<!DOCTYPE html>  
<html>  
  
<head>  
    <meta charset="utf-8">  
    <title>各城市交通拥堵指数</title>  
</head>  
  
<body>  
  {{mygeo|safe}}  
</body>  
  
</html>  

至此,访问网站地址即可看到绘制的拥堵情况地图~

本文转自快学Python.

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

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

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

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

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

Python 漂亮的新型绘图库 — PyG2Plot 实战教程

最近看了一篇文章《一个牛逼的Python 可视化库:PyG2Plot》,可惜只是简单介绍,并且只有一个简陋的官方示例。

经过小五一番测试成功复现了其中一个示例图片,还很精致。今天正好把完整过程分享给大家,看看这个新库绘图也可以这么漂亮!

Python可视化新秀

这个Python可视化新秀,在GitHub上是这样介绍的:

🎨 PyG2Plot 是@AntV/G2Plot 在 Python3 上的封装。G2Plot 是一套简单、易用、并具备一定扩展能力和组合能力的统计图表库,基于图形语法理论搭建而成。

不过研究PyG2Plot还得先从G2开始讲,它是蚂蚁金服开源一个基于图形语法,面向数据分析的统计图表引擎。后来又在其基础上,封装出业务上常用的统计图表库——G2Plot

不过现在Python这么热,几乎每一个nb的前端可视化库,最终都会被用python开发一套生成相应html的库!它也不例外,封装出了Python可视化库——PyG2Plot

在GitHub上,也提供了一张示例图,我对右下角的散点图比较感兴趣。

结果兴致勃勃地去看示例,这简直买家秀与卖家秀啊!

我不管,我就要右边那个👉

自己动手,丰衣足食

看来还是需要自己动手,那就先安装PyG2Plot库吧

pip install pyg2plot

目前目前 pyg2plot 只提供简单的一个 API,只列出需要的参数

  • Plot
  1. Plot(plot_type: str): 获取 Plot 对应的类实例。
  2. plot.set_options(options: object): 给图表实例设置一个 G2Plot 图形的配置。
  3. plot.render(path, env, **kwargs): 渲染出一个 HTML 文件,同时可以传入文件的路径,以及 jinja2 env 和 kwargs 参数。
  4. plot.render_notebook(env, **kwargs): 将图形渲染到 jupyter 的预览。

于是我们可以先导入Plot方法

from pyg2plot import Plot

我们要画散点图

scatter = Plot("Scatter")

下一步就是要获取数据和设置参数plot.set_options(),这里获取数据直接利用requset解析案例json,而参数让我在后面一一道来:

import requests

#请求地址
url = "https://gw.alipayobjects.com/os/bmw-prod/0b37279d-1674-42b4-b285-29683747ad9a.json"

#发送get请求
a = requests.get(url)

#获取返回的json数据,并赋值给data
data = a.json()

成功获取解析好的对象集合数据。

下面是对着参数,一顿操作猛如虎:

scatter.set_options(
{
    'appendPadding'30,
    'data': data,
    'xField''change in female rate',
    'yField''change in male rate',
    'sizeField''pop',
    'colorField''continent',
    'color': ['#ffd500''#82cab2''#193442''#d18768','#7e827a'],
    'size': [430],
    'shape''circle',
    'pointStyle':{'fillOpacity'0.8,'stroke''#bbb'},
    'xAxis':{'line':{'style':{'stroke''#aaa'}},},
    'yAxis':{'line':{'style':{'stroke''#aaa'}},},
    'quadrant':{
        'xBaseline'0,
        'yBaseline'0,
        'labels': [
        {'content''Male decrease,\nfemale increase'},
        {'content''Female decrease,\nmale increase'},
        {'content''Female & male decrease'},
        {'content''Female &\n male increase'}, ],},
})

如果在Jupyter notebook中预览的话,则执行下方语句

scatter.render_notebook()

如果想渲染出完整的html的话,则执行下方语句

scatter.render("散点图.html")

看一下成果吧

参数解析&完整代码

各位看官,这块可能比较无聊,可以直接划到文末或者点击收藏。

主要还是详解一下刚才scatter.set_options()里的参数,方便大家后续自己改造!

分成几个部分一点一点解释:

参数解释 一

'appendPadding'30#①
'data': data, #②
'xField''change in female rate'#③
'yField''change in male rate'

① 图表在上右下左的间距,加不加这个参数具体看下图

② 设置图表数据源(其中data在前面已经赋值了),这里的数据源为对象集合,例如:[{ time: ‘1991’,value: 20 }, { time: ‘1992’,value: 20 }]。

xFieldyField这两个参数分别是横/纵向的坐标轴对应的字段。

参数解释 二

'sizeField''pop'#④
'colorField''continent'#⑤
'color': ['#ffd500''#82cab2''#193442''#d18768','#7e827a'], #⑥
'size': [430], #⑦
'shape''circle'#⑧

④ 指定散点大小对应的字段名,我们用的pop(人口)字段。

⑤ 指定散点颜色对应的字段名,我们用的continent(洲)字段。

⑥ 设置散点的颜色,指定了系列色值。

⑦ 设置散点的大小,可以指定大小数组 [minSize, maxSize]

⑧ 设置点的形状,比如ciclesquare

参数解释 三

'pointStyle':{'fillOpacity'0.8,'stroke''#bbb'}, #⑨
'xAxis':{'line':{'style':{'stroke''#aaa'}},}, #⑩
'yAxis':{'line':{'style':{'stroke''#aaa'}},},

pointStyle是指折线样式,不过在散点图里,指的是散点的描边。另外fillOpacity是设置透明度,stroke是设置描边颜色。

⑩ 这里只是设置了坐标轴线的颜色。

参数解释 四

'quadrant':{
    'xBaseline'0,
    'yBaseline'0,
    'labels': [
    {'content''Male decrease,\nfemale increase'},
    {'content''Female decrease,\nmale increase'},
    {'content''Female & male decrease'},
    {'content''Female &\n male increase'}, ],},

quadrant是四象限组件,具体细分配置如下:

细分配置 功能描述
xBaseline x 方向上的象限分割基准线,默认为 0
yBaseline y 方向上的象限分割基准线,默认为 0
labels 象限文本配置

PyG2Plot的介绍文档还不完善,上文中的很多参数是摸索的,大家作为参考就好。

PyG2Plot 原理其实非常简单,其中借鉴了 pyecharts 的实现,但是因为蚂蚁金服的 G2Plot 完全基于可视分析理论的配置式结构,所以封装上比 pyecharts 简洁非常非常多。

本文转自快学Python.

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

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

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

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

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

超简单 Python 头像戴圣诞帽教程

还记得疫情之初,我们用Python给头像戴口罩的文章吗?

当时只是简单的调用了第三方模块将口罩图片替换入原图,内容非常简短。

今天,我们将提供一个能够通过以下三种方式给头像戴上圣诞帽的Python教程:

  • 1.实时打开摄像头读取头像图佩戴圣诞帽
  • 2.从本地读取一幅头像图佩戴圣诞帽
  • 3.从文件夹中批量读取头像图佩戴圣诞帽

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

此外,推荐大家用VSCode编辑器,因为它可以在编辑器下方的终端运行命令安装依赖模块:Python 编程的最好搭档—VSCode 详细指南。

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

pip install https://pypi.python.org/packages/da/06/bd3e241c4eb0a662914b3b4875fc52dd176a9db0d4a2c915ac2ad8800e9e/dlib-19.7.0-cp36-cp36m-win_amd64.whl#md5=b7330a5b2d46420343fbed5df69e6a3f
pip install opencv-python

有两个依赖,一个是 dlib模块,需要通过whl文件安装。一个是常用的opencv模块,直接pip安装即可。

文章源代码fork自:amusi/Merry_Christmas_Hat

本文全部源代码及图片可在此下载:
https://github.com/Ckend/Merry_Christmas_Hat

如果你访问不了Github,可在Python实用宝典公众号后台回复:圣诞帽 下载。

2.给头像戴上圣诞帽

为防大家没耐心看下去,我把佩戴圣诞帽的教程提前了。

下载源代码后,进入源代码的文件夹,一共有三种方式给你的头像佩戴圣诞帽。

1.打开摄像头读取头像图:

当摄像头打开后,会实时出现佩戴着圣诞帽的你。按q保存你最喜欢的图片即可。

def method_one(hat_img):
    """
    方式1: 打开摄像头读取头像图
    """
    cap = cv2.VideoCapture(0)
    if not cap.isOpened():
        print('摄像头打开失败!')
    else:
        print('摄像头打开成功!')
        print("请按下键盘上的'q',保存当前满意图像!")
        while cap.isOpened():
            _, img = cap.read()
            cv2.imshow("img", img)
            k = cv2.waitKey(33) & 0xFF
            if(k == ord('q')):
                cv2.imwrite("sefile.jpg", img)
                face_flag, output = add_hat(img, hat_img)
                if(-1 == face_flag):
                    break
                cv2.imshow("output", output)
                print("请按下键盘上的任意按键,退出当前程序!")
                cv2.waitKey(0)
                cv2.imwrite("output.jpg", output)
                break

# 读取帽子图,第二个参数-1表示读取为rgba通道,否则为rgb通道
hat_img = cv2.imread("hat.png", -1)

# 选择你需要的方式
method_one(hat_img)

cv2.destroyAllWindows()

这样,通过运行Merry_Chirstmas_Hat.py文件就能打开摄像头并实时显示佩戴圣诞帽的你:

python Merry_Chirstmas_Hat.py

2.读取一个图像佩戴圣诞帽

这是最常见的使用场景,你只需要的源代码文件夹下,放置你所需要佩戴圣诞帽的图像,命名为test.jpg(或其他,只需要改函数调用里你的指定文件名称)。

放置完成后运行Merry_Chirstmas_Hat.py文件即可佩戴圣诞帽。

def method_two(hat_img, filename):
    """
    方式2: 从本地读取一幅头像图
    """
    img = cv2.imread(filename)
    success, output = add_hat(img, hat_img)
    if not success:
        print("戴失败了!")
        return
    # 展示效果
    cv2.imshow("output", output)
    cv2.waitKey(0)
    cv2.imwrite("output.jpg", output)

# 读取帽子图,第二个参数-1表示读取为rgba通道,否则为rgb通道
hat_img = cv2.imread("hat.png", -1)

# 选择你需要的方式
method_two(hat_img, "test.jpg")

cv2.destroyAllWindows()

3. 从文件夹中读取多张头像图(批量处理)

在源代码的文件夹下,创建一个名为images的文件夹,在里面放置所有以.jpg结尾的图像,运行Merry_Chirstmas_Hat.py文件后你能看到所有这些图像佩戴圣诞帽的效果。

def method_three(hat_img):
    """
    方式3: 从文件夹中读取多张头像图(批量处理)
    """
    import glob as gb

    img_path = gb.glob("./images/*.jpg")

    for path in img_path:
        img = cv2.imread(path)

        # 添加帽子
        success, output = add_hat(img, hat_img)
        if not success:
            print("戴失败了!")
            continue

        # 展示效果
        cv2.imshow("output", output)
        cv2.waitKey(0)
        
# 读取帽子图,第二个参数-1表示读取为rgba通道,否则为rgb通道
hat_img = cv2.imread("hat.png", -1)

# 选择你需要的方式
method_three(hat_img)

cv2.destroyAllWindows()

我们的代码默认使用了第二种方式佩戴圣诞帽,你可以修改代码178行的method选择你所需要的方式。佩戴效果如下:

原图:

佩戴效果图:

3.原理分析

在上面的三种佩戴圣诞帽方法中,都调用了一个叫 add_hat 的函数。

顾名思义,这个函数里对原图像做了佩戴圣诞帽的逻辑,其步骤如下:

  • 1. 正脸识别(才好佩戴帽子到头部)。
  • 2. 遍历所有人脸,取5个关键点,并根据人脸大小调整帽子大小。
  • 3. 利用alpha通道的图像提取放帽子的区域(提取空心区域)。
  • 4. 将原帽子覆盖至第3步提取出来的空心区域上并放回原图。

下面分步骤阐述:

1.正脸识别

利用了dlib中已经训练好的人脸关键点检测模型对图像进行提取人脸的操作:

# dlib人脸关键点检测器(需要确保.py文件同级目录下有shape_predictor_5_face_landmarks.dat这个文件)
predictor_path = "shape_predictor_5_face_landmarks.dat"
predictor = dlib.shape_predictor(predictor_path)

# dlib正脸检测器
detector = dlib.get_frontal_face_detector()

# 正脸检测
dets = detector(img, 1)

检测到的人脸数据将会保存到dets变量中,因此dets的长度将大于0.

2.遍历人脸,取关键点并调整帽子大小

获取保存的人脸数据的各种参数,并根据这些参数对帽子进行比例转化:

# 如果检测到人脸
if len(dets) > 0:
    # 遍历所有人脸
    for d in dets:
        x, y, w, h = d.left(), d.top(), d.right()-d.left(), d.bottom()-d.top()
        
        # 关键点检测,5个关键点
        shape = predictor(img, d)
        
        # 选取左(0)右(2)眼眼角的点
        point1 = shape.part(0)
        point2 = shape.part(2)
        
        # 求两点中心
        eyes_center = ((point1.x+point2.x)//2, (point1.y+point2.y)//2)
        
        # 根据人脸大小调整帽子大小
        factor = 1.5    # 比例因子
        resized_hat_h = int(
            round(rgb_hat.shape[0]*w/rgb_hat.shape[1]*factor))
        resized_hat_w = int(
            round(rgb_hat.shape[1]*w/rgb_hat.shape[1]*factor))
        
        # 避免帽子高度超出图像画面
        if resized_hat_h > y:
            resized_hat_h = y-1
            
        # 根据人脸大小调整帽子大小
        resized_hat = cv2.resize(rgb_hat, (resized_hat_w, resized_hat_h))

3. 利用alpha通道的图像提取放帽子的区域(提取空心区域)。

通过alpha通道生成的黑白图像作为mask,将其填充到原图中。生成了bg.jpg.

# 用alpha通道作为mask(bitwise_not)
mask = cv2.resize(a, (resized_hat_w, resized_hat_h))
mask_inv = cv2.bitwise_not(mask)

# 帽子相对与人脸框上线的偏移量
dh = 0
dw = 0
# 原图ROI
bg_roi = img[y+dh-resized_hat_h:y+dh,
             (eyes_center[0]-resized_hat_w//3):(eyes_center[0]+resized_hat_w//3*2)]

# 原图ROI中提取放帽子的区域
bg_roi = bg_roi.astype(float)
mask_inv = cv2.merge((mask_inv, mask_inv, mask_inv))
alpha = mask_inv.astype(float)/255

# 相乘之前保证两者大小一致(可能会由于四舍五入原因不一致)
alpha = cv2.resize(alpha, (bg_roi.shape[1], bg_roi.shape[0]))
bg = cv2.multiply(alpha, bg_roi)
bg = bg.astype('uint8')
cv2.imwrite("bg.jpg", bg)

如果你打开bg.jpg,你就会发现这是一个佩带黑色模板的原图帽子区域:

4.将原帽子覆盖至第3步提取出来的空心区域上并放回原图。

接下来要做的,就是将帽子替换到第3部生成的空心区域上并放回原图:

# 提取帽子区域
hat = cv2.bitwise_and(resized_hat, resized_hat, mask=mask)
cv2.imwrite("hat.jpg", hat)

# 相加之前保证两者大小一致(可能会由于四舍五入原因不一致)
hat = cv2.resize(hat, (bg_roi.shape[1], bg_roi.shape[0]))

# 两个ROI区域相加
add_hat = cv2.add(bg, hat)

# 把添加好帽子的区域放回原图
img[y+dh-resized_hat_h:y+dh, (eyes_center[0]-resized_hat_w//3):(
    eyes_center[0]+resized_hat_w//3*2)] = add_hat
return 1, img

这样,便完成了整个佩戴圣诞帽的流程。文章完整源代码可在Python实用宝典公众号后台回复:圣诞帽 下载。

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

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

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

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

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

Python 一行语句算出每个省的面积—geopandas

教你如何用一行语句算出每个省的面积—Geopandas.

GeoPandas是一个基于pandas,针对地理数据做了特别支持的第三方模块。

它继承pandas.Series和pandas.Dataframe,实现了GeoSeries和GeoDataFrame类,使得其操纵和分析平面几何对象非常方便。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上噢,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda

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

当然,我更推荐大家用VSCode编辑器,把本文代码Copy下来,在编辑器下方的终端运行命令安装依赖模块,多舒服的一件事啊:Python 编程的最好搭档—VSCode 详细指南。

由于geopandas涉及到许多第三方依赖,pip安装起来非常麻烦。因此在本教程中,我只推荐使用conda安装geopandas:

conda install geopandas

一行语句即可完成安装。

2.基本使用

设定坐标绘制简单的图形:

>>> import geopandas
>>> from shapely.geometry import Polygon
>>> p1 = Polygon([(0, 0), (1, 0), (1, 1)])
>>> p2 = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])
>>> p3 = Polygon([(2, 0), (3, 0), (3, 1), (2, 1)])
>>> g = geopandas.GeoSeries([p1, p2, p3])
>>> g
0    POLYGON ((0 0, 1 0, 1 1, 0 0))
1    POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))
2    POLYGON ((2 0, 3 0, 3 1, 2 1, 2 0))
dtype: geometry

这里有一个强大的用法,通过area属性,geopandas能直接返回这些图形的面积:

>>> print(g.area)
0    0.5
1    1.0
2    1.0
dtype: float64

不仅如此,通过plot属性函数,你还可以直接生成matplotlib图。

>>> g.plot()

通过matplot的pyplot,可以将图片保存下来:

import matplotlib.pyplot as plt
g.plot()
plt.savefig("test.png")

学会上面的基本用法, 我们就可以进行简单的地图绘制及面积的计算了。

3.绘制并算出每个省的面积

此外,它最大的亮点是可以通过fiona读取比如ESRI shapefile(一种用于存储地理要素的几何位置和属性信息的非拓扑简单格式)。

import geopandas
import matplotlib.pyplot as plt
from shapely.geometry import Polygon
maps = geopandas.read_file('1.shx')
# 读取的数据格式类似于
#                                             geometry
# 0   POLYGON ((1329152.341 5619034.278, 1323327.591...
# 1   POLYGON ((-2189253.375 4611401.367, -2202922.3...
# 2   POLYGON ((761692.092 4443124.843, 760999.873 4...
# 3   POLYGON ((-34477.046 4516813.963, -41105.128 4...
# ... ...
maps.plot()
plt.savefig("test.png")

如代码所示,通过read_file你可以读取shx、gpkg、geojson等数据。读取出来的图形如下:

同样滴,我这个shapefile是省级行政区的,每一个省级行政区都被划分为一个区块,因此可以一行语句算出每个省级行政区所占面积:

print(maps.area)
# 0     4.156054e+11
# 1     1.528346e+12
# 2     1.487538e+11
# 3     4.781135e+10
# 4     1.189317e+12
# 5     1.468277e+11
# 6     1.597052e+11
# 7     9.770609e+10
# 8     1.385692e+11
# 9     1.846538e+11
# 10    1.015979e+11
# ... ...

怎么样,是不是很酷?它还有许多更库的特性,欢迎阅读官方文档:
https://geopandas.readthedocs.io/

本文用到的shx格式省级行政区数据,可以在【Python实用宝典】公众号后台回复 省级行政区下载。​

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

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

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


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

用Python实战制作一张极具意义的人生进度图

时间如流水,一路向前,转眼间,2020年已过半。

这半年的你,过得还好吗?

无论过去的半年里,你是快乐还是难过,请不要沉溺于过去。

因为如果我们从宏观的角度上来看待人生,按周计算,你会发现过去的半年实际上也不过是微小的几个点而已。

对于我而言,它是这样的:

这些微小的点像钻石一般组成了你的人生。每一个点都很重要,但未来的点更关键。

看着这张图表,你有一个非常重要的问题需要回答:“我是否在充分利用自己的时间,我有没有适当地享受人生”

事实上,我认为这张图表上的每个点,即人生的每个星期,这样过是最合适的:

1.享受生活

2.为未来的每个点能够享受生活打下基础

3.创造一些能让自己或他人活得更有趣的东西

在理想状态下,上面的三点应该是互相平衡的。(当然,理想状态是不存在的)

如果你现在暂时无法平衡这三点,没关系,制作这张图,每个星期都来关注一下自己的人生进度。

神秘的原力会帮助你平衡这三点的(咋回事,我可是纯正的理工科生。

你可以把一些关键的人生时间节点标记在这张图表上,比如我认为创建Python实用宝典是一件很有趣的事情:

这么看,Python实用宝典创建了才不到半年的时间就赶上了疫情啊,这一点我倒是没注意到。

当然,你也可以丰富一下这张图表,把一些从小到大的重要节点写上,并记录今天所在的位置:

粗略地画了一张我的Life Graph,(当然没把细致的写出来哈,毕竟属于隐私),不过,我这个一会玩疯一会学疯也是挺有趣的。

接下来就教大家如何用Python最快、最方便地画出这张表,实际上我仅用了20行代码。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上噢,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda

事实上,如果我们从零开始画这个图表,是会比较麻烦的。

幸好,已经有Python同好—K20shore 大神的 Life-Graph项目帮我们做了这件事了。

你可以直接在GitHub上下载他的源代码,也可以关注Python实用宝典公众号,回复 “人生” 下载。

这份源代码依赖于Latex,所以你还需要下载 MiKTeX,一路按默认安装即可:
https://miktex.org/download

安装的时候请记住路径,因为安装完成后还需要将latex.exe的路径放入环境变量中:

2.基本使用

K20shores大神的这个库基本包含了我们所有需要使用的元件。

比如前面提到的标记某一个时间段,可以用add_era:

# 增加事件名称及其时间段
g.add_era('COVID-19', date(2020, 1, 1), date(2020, 7, 1), color="#605041")

示例如下:

from lifegraph.lifegraph import Lifegraph, Papersize, Side
from datetime import date

# 以出生日期为起点
birthday = date(1997, 6, 28)
g = Lifegraph(birthday, dpi=300, size=Papersize.A4, max_age=100)

g.add_title("Life Graph")
g.show_max_age_label()

# 增加事件名称及其时间段
g.add_era('COVID-19', date(2020, 1, 1), date(2020, 7, 1), color="#605041")

g.save("grid.png")

部分截图:

如果你需要标记一个点,可以使用add_life_event函数:

# 标记一个生命事件,可配置文本颜色及显示位置
g.add_life_event('Pythondict\nCreated', date(2019, 7, 31), color="#dc143c", side=Side.LEFT)

参数color可以配置相关线条及文本颜色,side可以配置文本显示在左边还是右边。

示例如下:

from lifegraph.lifegraph import Lifegraph, Papersize, Side
from datetime import date

# 以出生日期为起点
birthday = date(1997, 6, 28)
g = Lifegraph(birthday, dpi=300, size=Papersize.A4, max_age=100)

g.add_title("Life Graph")
g.show_max_age_label()

# 增加事件名称及其时间段
g.add_era('COVID-19', date(2020, 1, 1), date(2020, 7, 1), color="#605041")
g.add_life_event('Pythondict\nCreated', date(2019, 7, 31), color="#dc143c", side=Side.LEFT)

g.save("grid.png")

部分截图:

事实上,只要你会了这两个操作,基本上就没问题了。

值得注意的是,如果你需要用中文,请搜索“Latex 使用中文”相关的配置教程。

3.高级使用

其实它还可以配置背景图,这是我没想到的:

from lifegraph.lifegraph import Lifegraph, Papersize, Side
from datetime import date

# 以出生日期为起点
birthday = date(1997, 6, 28)
g = Lifegraph(birthday, dpi=300, size=Papersize.A4, max_age=100)

g.add_title("Life Graph")
g.show_max_age_label()

# 增加事件名称及其时间段
g.add_era('COVID-19', date(2020, 1, 1), date(2020, 7, 1), color="#605041")
g.add_life_event('Pythondict\nCreated', date(2019, 7, 31), color="#dc143c", side=Side.LEFT)

# 设置背景图
g.add_image("unnamed.jpg", alpha=0.5)

g.save("grid.png")

效果如下:

此外,连接多个点也是可以的:

from lifegraph.lifegraph import Lifegraph, Papersize, Side
from datetime import date

# 以出生日期为起点
birthday = date(1997, 6, 28)
g = Lifegraph(birthday, dpi=300, size=Papersize.A4, max_age=100)

g.add_title("Life Graph")
g.show_max_age_label()

# 增加事件名称及其时间段
g.add_era('COVID-19', date(2020, 1, 1), date(2020, 7, 1), color="#605041")

# 连接 A B 两个日期
g.add_era_span(
    'From A to B',
    date(2016, 12, 31), date(2020, 7, 13),
    color="#4423fe",
    side=Side.LEFT
)

g.save("grid.png")

基本上全部的使用方法就这些了。

希望大家能用这个工具,时刻提醒自己:

快乐地度过每一个星期,做一些有意义的事情,不负韵华。

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

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


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

国外牛人整理的Matplotlib超强使用指南与笔记,值得收藏

是不是经常被Matplotlib各种复杂的函数和颜色折腾地死去活来?

是不是在使用Matplotlib画图的时候,没有搜索引擎就走不动路?

其实,如果我们能把常用的函数和模块集中在一张图表上,工作效率会快许多。

国外有个牛人(Nicolas-Rougier)就这么做了,来看看他的笔记:

1.基本使用—初学者教程

每一个代码块对应其右边的图形,非常简洁明了,根本不需要翻译!

比较进阶的使用,结合许多基本图形生成复杂的图形:

一些使用上的提醒和小技巧:

2.常用函数的使用笔记:

建议在你使用Matplotlib绘图时,开个小窗体将下面两张图放在旁边。

这样你就能清楚知道什么样的图形最符合你的需求、代码该怎么写、有没有其他style可选,非常方便。

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

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


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

Python 快速绘制画出漂亮的系统架构图

Diagrams  是一个基于Python绘制云系统架构的模块,它能够通过非常简单的描述就能绘制画出可视化架构,其支持使用以下6种云产品的图标:

AWSAzureGCPKubernetes阿里云, Oracle Cloud

基于Diagrams提供的节点,你只需要指定一个云产品(实际上选哪个都一样,我们只需要那个产品相应的图标,你可以选一个自己觉得好看的),使用其内部自带的云产品的图标,就能简单绘制基于某云产品图标的架构图,比如下面的代码,绘制了一个简单的基于数据库集群的网络服务架构:

from diagrams import Cluster, Diagram
from diagrams.aws.compute import ECS
from diagrams.aws.database import RDS
from diagrams.aws.network import Route53

with Diagram("Simple Web Service with DB Cluster", show=False):
    dns = Route53("dns")
    web = ECS("service")

    with Cluster("DB Cluster"):
        db_master = RDS("master")
        db_master - [RDS("slave1"),
                     RDS("slave2")]

    dns >> web >> db_master

非常适合用来做毕业论文的架构图绘制,强烈推荐。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上噢,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda

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

当然,我更推荐大家用VSCode编辑器,把本文代码Copy下来,在编辑器下方的终端运行命令安装依赖模块,多舒服的一件事啊:Python 编程的最好搭档—VSCode 详细指南。

在终端输入以下命令安装我们所需要的依赖模块:

pip install diagrams

看到 Successfully installed xxx 则说明安装成功。

2.基本使用与例子

2.1 初始化与导出

使用 Diagram 类初始化一个绘图上下文,这个类接收到的第一个参数将会成为架构图的文件名,而一当代码运行完毕,它将会以该文件名保存(空格会被下划线所替代):

from diagrams import Diagram
from diagrams.aws.compute import EC2

with Diagram("Simple Diagram"):
    EC2("web")

此外,它还可以选择导出的文件格式,在Diagram类里增加outformat参数,也可以不以第一个参数为文件保存名称,增加filename参数指定名称即可:

with Diagram("Simple Diagram", outformat="jpg", filename="my_diagram")

2.2 节点类型

由于节点类型比较多,我们无法一一展示出来,所有类型的节点里都可以在官方文档里找到,比如:

阿里云:https://diagrams.mingrammer.com/docs/nodes/alibabacloud
K8S: https://diagrams.mingrammer.com/docs/nodes/k8s
AWS: https://diagrams.mingrammer.com/docs/nodes/aws

接下来以AWS为例子,讲解几个基本的数据流例子:

from diagrams import Diagram
from diagrams.aws.compute import EC2
from diagrams.aws.database import RDS
from diagrams.aws.network import ELB
from diagrams.aws.storage import S3

# show参数表示是否自动打开图像
with Diagram("Web Services", show=False):
    ELB("lb") >> EC2("web") >> RDS("userdb") >> S3("store")
    ELB("lb") >> EC2("web") >> RDS("userdb") << EC2("stat")
    (ELB("lb") >> EC2("web")) - EC2("web") >> RDS("userdb")

几个操作符:

>> 表示从左到右的数据流
<< 表示从右到左的数据流
– 表示没有箭头的数据流

可以用变量赋值的形式简化代码:

from diagrams import Diagram
from diagrams.aws.compute import EC2
from diagrams.aws.database import RDS
from diagrams.aws.network import ELB

with Diagram("Workers", show=False, direction="TB"):
    lb = ELB("lb")
    db = RDS("events")
    lb >> EC2("worker1") >> db
    lb >> EC2("worker2") >> db
    lb >> EC2("worker3") >> db
    lb >> EC2("worker4") >> db
    lb >> EC2("worker5") >> db

可以看到这里箭头的方向变了,这是因为Diagram加了direction参数,TB 表示数据流向 top to bottm, 即从上到下,可选的其他参数还有:LR(左至右)、BT(底至上)、RL(右至左)。

上面的代码还可以用数组的形式进一步简化:

from diagrams import Diagram
from diagrams.aws.compute import EC2
from diagrams.aws.database import RDS
from diagrams.aws.network import ELB

with Diagram("Grouped Workers", show=False, direction="TB"):
    ELB("lb") >> [EC2("worker1"),
                  EC2("worker2"),
                  EC2("worker3"),
                  EC2("worker4"),
                  EC2("worker5")] >> RDS("events")

2.3 集群块

使用Cluster 类 并用with以上下文的形式,你可以非常方便地生成一个集群块:

from diagrams import Cluster, Diagram
from diagrams.aws.compute import ECS
from diagrams.aws.database import RDS
from diagrams.aws.network import Route53

with Diagram("Simple Web Service with DB Cluster", show=False):
    dns = Route53("dns")
    web = ECS("service")

    with Cluster("DB Cluster"):
        db_master = RDS("master")
        db_master - [RDS("slave1"),
                     RDS("slave2")]

    dns >> web >> db_master

而且还可以做得相当复杂:

这里代码很简单,但是比较长,不展示了,有兴趣的话可以点击最下方阅读原文进行查看。

from diagrams import Cluster, Diagram
from diagrams.aws.compute import ECS, EKS, Lambda
from diagrams.aws.database import Redshift
from diagrams.aws.integration import SQS
from diagrams.aws.storage import S3

with Diagram("Event Processing", show=False):
    source = EKS("k8s source")

    with Cluster("Event Flows"):
        with Cluster("Event Workers"):
            workers = [ECS("worker1"),
                       ECS("worker2"),
                       ECS("worker3")]

        queue = SQS("event queue")

        with Cluster("Processing"):
            handlers = [Lambda("proc1"),
                        Lambda("proc2"),
                        Lambda("proc3")]

    store = S3("events store")
    dw = Redshift("analytics")

    source >> workers >> queue >> handlers
    handlers >> store
    handlers >> dw

2.4 自定义线的颜色与属性

使用Edge函数,你可以自定义线的颜色与属性以及备注,比如:

Edge(color="firebrick", style="dashed", label="test")
# 火砖色的虚线,备注为test

一个比较复杂,但是阅读起来很简单的例子如下:

from diagrams import Cluster, Diagram, Edge
from diagrams.onprem.analytics import Spark
from diagrams.onprem.compute import Server
from diagrams.onprem.database import PostgreSQL
from diagrams.onprem.inmemory import Redis
from diagrams.onprem.logging import Fluentd
from diagrams.onprem.monitoring import Grafana, Prometheus
from diagrams.onprem.network import Nginx
from diagrams.onprem.queue import Kafka

with Diagram(name="Advanced Web Service with On-Premise (colored)", show=False):
    ingress = Nginx("ingress")

    metrics = Prometheus("metric")
    metrics << Edge(color="firebrick", style="dashed") << Grafana("monitoring")

    with Cluster("Service Cluster"):
        grpcsvc = [
            Server("grpc1"),
            Server("grpc2"),
            Server("grpc3")]

    with Cluster("Sessions HA"):
        master = Redis("session")
        master - Edge(color="brown", style="dashed") - Redis("replica") << Edge(label="collect") << metrics
        grpcsvc >> Edge(color="brown") >> master

    with Cluster("Database HA"):
        master = PostgreSQL("users")
        master - Edge(color="brown", style="dotted") - PostgreSQL("slave") << Edge(label="collect") << metrics
        grpcsvc >> Edge(color="black") >> master

    aggregator = Fluentd("logging")
    aggregator >> Edge(label="parse") >> Kafka("stream") >> Edge(color="black", style="bold") >> Spark("analytics")

    ingress >> Edge(color="darkgreen") << grpcsvc >> Edge(color="darkorange") >> aggregator

3.总结

不得不说,这真是一个基于Python,且非常简单好用的开源免费架构图设计模块,用途其实非常广,包括不仅限于:计算机应用的架构图、毕业设计架构等等。希望大家能够学以致用。

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

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

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

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

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

Python 批量转化彩色图片为黑白图片

最近遇到了一个新的情景,需要将彩色图片转化为黑白图片,如果手动地去转化一张一张图片,那就真的太原始人了。

用Python,咱只需要几行代码就可以在几秒内转化上千张图片。而且,这个功能的用途相当广泛,不仅能使图片变得深邃,而且还可以简化一些复杂模型的数学计算,具体可见第三部分的分析。

1.准备

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

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

当然,我更推荐大家用VSCode编辑器,把本文代码Copy下来,在编辑器下方的终端装依赖模块,多舒服的一件事啊:Python 编程的最好搭档—VSCode 详细指南

输入以下命令安装本文所需要的依赖模块:

pip install pillow -i https://pypi.tuna.tsinghua.edu.cn/simple some-package

看到 Successfully installed xxx 则说明安装成功。

2.编写代码

首先写一下我们的彩色图转单色图的转化函数,接收两个参数,一个是输入文件的路径,一个是输出文件路径:

from PIL import Image

def colorful_to_single(input_img_path, output_img_path):
    """
    彩色图转单色图
    :param input_img_path: 图片路径
    :param output_img_path: 输出图片路径
    """

    img = Image.open(input_img_path)
    # 转化为黑白图片
    img = img.convert("L")
    img.save(output_img_path) 

(又是注释比代码长系列)

然后将你需要转化的图片放到一个文件夹中,我这里命名该文件夹为imgs,然后指定一个输出文件夹 output,如下:

dataset_dir = 'imgs'
output_dir = 'output'

# 获得需要转化的图片路径并生成目标路径
image_filenames = [(
    os.path.join(dataset_dir, file_dir),
    os.path.join(output_dir, file_dir)
) for file_dir in os.listdir(dataset_dir)]

# 转化所有图片
for path in image_filenames:
    colorful_to_single(path[0], path[1])

这里比较难理解的可能是image_filenames,用到了列表推导式,即遍历所有dataset_dir里的文件:

for file_dir in os.listdir(dataset_dir) 

并将其和我们指定的目录以路径的形式链接起来:

os.path.join(output_dir, file_dir) 

最终生成一个数组,第一个元素是输入路径,第二个元素是输出路径:

image_filenames = [(
    os.path.join(dataset_dir, file_dir),
    os.path.join(output_dir, file_dir)
) for file_dir in os.listdir(dataset_dir)]

3.效果及用途

黑白效果就是这样的:

用途当然也有很多了,比如:

1.在深度学习分类图像的时候,如果并不需要考虑颜色的维度,可以先将图片转化为黑白图,简化运算复杂度。

2.黑白图片有的时候比彩色图片更具备冲击力,能够更加突出主题。

3.黑白图片有些时候也有美颜的作用,因为此时注意力的重点在于脸型,如果那个人的脸型特别好看,但是肤色比较差,这时候黑白照片就很有效果。

我们的文章到此就结束啦,如果你喜欢我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


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

Python 批量修改图片亮度和饱和度

在Photoshop里也可以做到批量修改图片的亮度和饱和度,但是很多人都没有条件使用Photoshop,此外,Photoshop里的批量修改其实很耗性能,而且使用起来并不是很方便。

那我们能不能用Python做一个小工具,先找到合适的亮度和饱和度,然后再根据这个指定的值对所有需要做相似调整的图片做批量修改呢?答案是肯定的。

1.准备

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

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal). 输入以下命令安装我们所需要的模块:

pip install numpy
pip install opencv-python

看到 Successfully installed xxx 则说明安装成功。

2.开发调整工具

这一部分,我们将开发出一个能够调整图像亮度和饱和度的工具,而且这个工具支持滑动调整。其实放到别的语言里,这可是个小工程,但是放到Python里,我们用50行代码就能解决了。

首先是加载图片,然后需要将图片转化为HLS模式才能够调整亮度和饱和度。这是因为默认的图片颜色空间是RGB,它非常适合显示器显示,但由于只有三个颜色分类,并不适合图像处理。而HLS模式相对于RGB颜色空间则复杂得多,HLS分别代表H: Hue(色调),L: Lightness(亮度), S: Saturation(饱和度)。

其颜色空间是一个三维空间,如下图所示:

这样的颜色空间才使得我们可以调整图片的细节部分。Python代码中,将RGB转化为HLS空间是很简单的,两行代码就能做到:

import numpy as np
import cv2

# 加载图片 读取彩色图像归一化且转换为浮点型
image = cv2.imread('2.jpg', cv2.IMREAD_COLOR).astype(np.float32) / 255.0

# 颜色空间转换 BGR转为HLS
hlsImg = cv2.cvtColor(image, cv2.COLOR_BGR2HLS)

然后我们需要做两个滑动块,一个调节亮度,一个调节饱和度:

# 滑动条最大值
MAX_VALUE = 100
# 滑动条最小值
MIN_VALUE = 0

# 调节饱和度和亮度的窗口
cv2.namedWindow("lightness and saturation", cv2.WINDOW_GUI_NORMAL)

# 创建滑动块
cv2.createTrackbar("lightness", "lightness and saturation", MIN_VALUE, MAX_VALUE, lambda x:x)
cv2.createTrackbar("saturation", "lightness and saturation", MIN_VALUE, MAX_VALUE, lambda x:x)

调节前还需要保存一下原图,所以我们会在内存里复制一个新的变量用于调节图片,然后获得两个滑动块的值,再根据值进行亮度和饱和度的调整:

# 调整饱和度和亮度
while True:
    # 复制原图
    hlsCopy = np.copy(hlsImg)
    # 得到 lightness 和 saturation 的值
    lightness = cv2.getTrackbarPos('lightness', 'lightness and saturation')
    saturation = cv2.getTrackbarPos('saturation', 'lightness and saturation')
    # 1.调整亮度(线性变换)
    hlsCopy[:, :, 1] = (1.0 + lightness / float(MAX_VALUE)) * hlsCopy[:, :, 1]
    hlsCopy[:, :, 1][hlsCopy[:, :, 1] &gt; 1] = 1
    # 饱和度
    hlsCopy[:, :, 2] = (1.0 + saturation / float(MAX_VALUE)) * hlsCopy[:, :, 2]
    hlsCopy[:, :, 2][hlsCopy[:, :, 2] &gt; 1] = 1
    # HLS2BGR
    lsImg = cv2.cvtColor(hlsCopy, cv2.COLOR_HLS2BGR)
    # 显示调整后的效果
    cv2.imshow("lightness and saturation", lsImg)

效果如下图所示:

到这里还不够,由于是while循环支持的调节,我们还需要让其可以退出和保存:

    ch = cv2.waitKey(5)
    # 按 ESC 键退出
    if ch == 27:
        break
    elif ch == ord('s'):
        # 按 s 键保存并退出
        lsImg = lsImg * 255
        lsImg = lsImg.astype(np.uint8)
        cv2.imwrite("lsImg.jpg", lsImg)
        break

这样,按s键可以保存图片并退出,按ESC键可以直接退出编辑器。 完整文字版50行代码请在Python实用宝典公众号后台回复:批量修改图片 获得。

3.批量修改

前面根据我们的小工具获得了需要的饱和度和亮度,把这对值记下来就可以批量修改图片了。当然,我们没有自动批量修改到正确值这么逆天的功能,这个工具只适合相同场景下,能够用同一对亮度和饱和度进行调整的图片:

def update(input_img_path, output_img_path, lightness, saturation):
    """
    用于修改图片的亮度和饱和度
    :param input_img_path: 图片路径
    :param output_img_path: 输出图片路径
    :param lightness: 亮度
    :param saturation: 饱和度
    """

    # 加载图片 读取彩色图像归一化且转换为浮点型
    image = cv2.imread(input_img_path, cv2.IMREAD_COLOR).astype(np.float32) / 255.0

    # 颜色空间转换 BGR转为HLS
    hlsImg = cv2.cvtColor(image, cv2.COLOR_BGR2HLS)

    # 1.调整亮度(线性变换)
    hlsImg[:, :, 1] = (1.0 + lightness / float(MAX_VALUE)) * hlsImg[:, :, 1]
    hlsImg[:, :, 1][hlsImg[:, :, 1] &gt; 1] = 1
    # 饱和度
    hlsImg[:, :, 2] = (1.0 + saturation / float(MAX_VALUE)) * hlsImg[:, :, 2]
    hlsImg[:, :, 2][hlsImg[:, :, 2] &gt; 1] = 1
    # HLS2BGR
    lsImg = cv2.cvtColor(hlsImg, cv2.COLOR_HLS2BGR) * 255
    lsImg = lsImg.astype(np.uint8)
    cv2.imwrite(output_img_path, lsImg)

这部分其实比制作刚刚的工具简单,可以说是工具的简化版。分为以下六个步骤:

1.加载图片。
2.转化为HLS空间。
3.调整亮度。
4.调整饱和度。
5.转化为RGB空间。
6.保存。

然后我们只需要批量地将图片传入该函数,就能实现批量转化:

dataset_dir = 'imgs'
output_dir = 'output'
lightness = 10
saturation = 20

# 获得需要转化的图片路径, 并生成目标路径
image_filenames = [(os.path.join(dataset_dir, x), os.path.join(output_dir, x))
                    for x in os.listdir(dataset_dir)]
# 转化所有图片
for path in image_filenames:
    update(path[0], path[1], lightness, saturation)

通过这份Python代码,你能在1分钟内修改几千张图片,这样的效率并非Photoshop能比的。当然,它也有它的缺点,那就是只能根据你输入的值进行修改,而Photoshop能够进行自动优化(虽然精度评价因人而异)。

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


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

Python 绘制属于你的世界地图

Python之所以这么流行,是因为它不仅能够应用于科技领域,还能用来做许多其他学科的研究工具,最常见的便是绘制地图

今天我们用matplot工具包之一的:mpl_toolkits来绘制世界地图,这是一个简单的可视化地图工具,你如果希望绘制更加复杂的地图,可以考虑使用Google Maps API,不过这不在我们今天的讨论范围之内。

1.安装

如果你还没有安装Python,请见这篇文章:超详细Python安装指南

为了能够顺利开展本项目,你需要先安装以下依赖,在cmd或Terminal中输入以下命令:

pip install numpy

pip install matplotlib

为了使用 mpl_toolkits, 单纯安装matplotlib是不够的,我们还需要单独安装basemap,如果你已经安装了Anaconda,那这一步就非常好办,输入以下命令安装即可:

conda install basemap

如果没有的话,就稍微麻烦一点:

1.安装geos: pip install geos
2.根据你的Python版本下载basemap
http://www.lfd.uci.edu/~gohlke/pythonlibs/#basemap
PS: cp后面的数字是Python的版本。(在页面上按ctrl+F,输入basemap快速定位)
3.在 cmd 下进入该文件的目录,运行
pip install basemap‑1.2.1‑cp37‑cp37m‑win_amd64.whl

2.简单地图

让我们开始绘制一个地球,中心指向中国:

# 导入需要的包
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap

# 初始化图形
plt.figure(figsize=(8, 8))
# 底图:圆形, lat_0:纬度;lon_o: 经度, (113,29)是武汉
m = Basemap(projection='ortho', resolution=None, lat_0=29, lon_0=113)
# 底色
m.bluemarble(scale=0.5)
# 显示
plt.show()

这里的重点在于Basemap,指定好你想要放置的中心。

效果还不错哦,不仅如此,它其实不单单只是一张图像,它还是一个功能齐全的matplot画布。这也就意味着,你能够在上面画线!让我们放大地图,进入中国区域,然后标记出深圳的位置:

# 导入需要的包
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap

# 以下三行是为了让matplot能显示中文
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['FangSong']
mpl.rcParams['axes.unicode_minus'] = False

fig = plt.figure(figsize=(8, 8))
# 注意几个新增的参数, width和height是用来控制放大尺度的
# 分别代表投影的宽度和高度(8E6代表 8x10^6米)
m = Basemap(projection='lcc', resolution=None,
            width=8E6, height=8E6,
            lat_0=23, lon_0=113,)
m.bluemarble(scale=0.5)

# 这里的经纬度是:(经度, 纬度)
x, y = m(113, 23)
plt.plot(x, y, 'ok', markersize=5) 
plt.text(x, y, '深圳', fontsize=12, color="red") 
plt.show()

不要用蓝底图了,看得不是很清晰,我们换成浮雕型:

可以很明显地看到山区、丘陵等地理样貌。你还可以根据你的需要,针对某几个城市做连线或者绘制某些经纬度之间的区域。别忘了,这可是matplotlib可编辑的画布。

3.世界地图

接下来,我们将上述的世界地图展开成带经纬线的平面图形。

# 导入需要的包
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
from itertools import chain


def draw_map(m, scale=0.2):
    # 绘制带阴影的浮雕图像
    m.shadedrelief(scale=scale)

    # 根据经纬度切割,每13度一条线
    lats = m.drawparallels(np.linspace(-90, 90, 13))
    lons = m.drawmeridians(np.linspace(-180, 180, 13))

    # 集合所有线条
    lat_lines = chain(*(tup[1][0] for tup in lats.items()))
    lon_lines = chain(*(tup[1][0] for tup in lons.items()))
    all_lines = chain(lat_lines, lon_lines)

    # 循环画线
    for line in all_lines:
        line.set(linestyle='-', alpha=0.3, color='w')


fig = plt.figure(figsize=(8, 6), edgecolor='w')
m = Basemap(projection='cyl', resolution=None,
            llcrnrlat=-90, urcrnrlat=90,
            llcrnrlon=-180, urcrnrlon=180,)

draw_map(m)
plt.show()

嗯,有点那个味了哈。都可以自己去打印出来给小孩子学习地理了。但是他如果想学习地理,好像整个世界有点大?我们先让他学习世界著名景点的位置吧?

# 导入需要的包
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
from itertools import chain

# 以下三行是为了让matplot能显示中文
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['FangSong']
mpl.rcParams['axes.unicode_minus'] = False


def draw_point(m, x, y, name):
    # 这里的经纬度是:(经度, 纬度)
    x, y = m(x, y)
    plt.plot(x, y, 'ok', markersize=5)
    plt.text(x, y, name, fontsize=12, color="red")


def draw_map(m, scale=0.2):
    # 绘制带阴影的浮雕图像
    m.shadedrelief(scale=scale)

    # 根据经纬度切割,每13度一条线
    lats = m.drawparallels(np.linspace(-90, 90, 13))
    lons = m.drawmeridians(np.linspace(-180, 180, 13))

    # 集合所有线条
    lat_lines = chain(*(tup[1][0] for tup in lats.items()))
    lon_lines = chain(*(tup[1][0] for tup in lons.items()))
    all_lines = chain(lat_lines, lon_lines)

    # 循环画线
    for line in all_lines:
        line.set(linestyle='-', alpha=0.3, color='w')


fig = plt.figure(figsize=(8, 6), edgecolor='w')
m = Basemap(projection='cyl', resolution=None,
            llcrnrlat=-90, urcrnrlat=90,
            llcrnrlon=-180, urcrnrlon=180,)
locations = {
    '泰姬陵': (17, 78),
    '吉萨金字塔群': (29, 31),
    '英国的巨石阵': (51, 1),
    '巴黎圣母院': (48, 2),
    '卢浮宫': (48, 2),
    '红场和克里姆林': (55, 37),
    # ...
}
draw_map(m)
for loc in locations:
    print(locations[loc])
    draw_point(m, locations[loc][1], locations[loc][0], loc)
plt.show()

这样,你只需要往locations里类似地加入某个地点的经纬度,就能在地图上展示出来了,你还能自定义地画两个地点之间的连线,或者是重点放大某个区域,总而言之,你想干的,基本上基于Matplotlib都可以做得到。

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


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