分类目录归档:Python 数据分析

比PS还好用!Python 20行代码批量抠图

在日常的工作和生活中,我们经常会遇到需要抠图的场景,即便是只有一张图片需要抠,也会抠得我们不耐烦,倘若遇到许多张图片需要抠,这时候你的表情应该会很有趣。

Python能够成为这样的一种工具:在只有一张图片,需要细致地抠出人物的情况下,能帮你减少抠图步骤;在有多张图片需要抠的情况下,能直接帮你输出这些人物的基本轮廓,虽然不够细致,但也够用了。

DeepLabv3+ 是谷歌 DeepLab语义分割系列网络的最新作 ,这个模型可以用于人像分割,支持任意大小的图片输入。如果我们自己来实现这个模型,那可能会非常麻烦,但是幸运的是,百度的paddle hub已经帮我们实现了,我们仅需要加载模型对图像进行分割即可。

1.准备

为了实现这个实验,Python是必不可少的,如果你还没有安装Python,建议阅读我们的这篇文章哦:超详细Python安装指南

然后,我们需要安装百度的paddlepaddle, 进入他们的官方网站就有详细的指引:
https://www.paddlepaddle.org.cn/install/quick

根据你自己的情况选择这些选项,最后一个CUDA版本,由于本实验不需要训练数据,也不需要太大的计算量,所以直接选择CPU版本即可。选择完毕,下方会出现安装指引,不得不说,Paddlepaddle这些方面做的还是比较贴心的(就是名字起的不好)

要注意,如果你的Python3环境变量里的程序名称是Python,记得将语句改为Python xxx,如下进行安装:

python -m pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple

还需要安装paddlehub:

pip install -i https://mirror.baidu.com/pypi/simple paddlehub

2.编写代码

整个步骤分为三步:

1.加载模型
2.指定待抠图的图片目录
3.抠图

import os
import sys
import paddlehub as hub

# 1.加载模型
humanseg = hub.Module(name="deeplabv3p_xception65_humanseg")

# 2.指定待抠图图片目录
path = './source/'
files = []
dirs = os.listdir(path)
for diretion in dirs:
    files.append(path + diretion)

# 3.抠图
results = humanseg.segmentation(data={"image": files})

for result in results:
    print(result['origin'])
    print(result['processed'])

不多不少一共20行代码。抠图完毕后会在本地文件夹下产生一个叫做humanseg_output的文件夹。这里面存放的是已经抠图成功的图片。

本文20行代码及所有图片,请在公众号后台回复:Python自动抠图 下载。

3.结果分析

不得不承认,谷歌的算法就素厉害啊。只要背景好一点,抠出来的细节都和手动抠的细节不相上下,甚至优于人工手段。

不过在背景和人的颜色不相上下的情况下,会产生一些问题,比如下面这个结果:

背后那个大叔完全被忽略掉了(求大叔的内心阴影面积)。尽管如此,这个模型是我迄今为止见过的最强抠图模型,没有之一。

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


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

Python 20行代码检测人脸是否佩戴口罩

最近,口罩成为绝对热门的话题,在疫情之下,出门不戴口罩不仅对自己不负责,对他人而言也是一种潜在的威胁。所以许多小区都有保安在门口守着,谁要是不戴口罩就吼回去(吓死我了)

尽管如此,人工检测总有可能漏掉人,而且无时无刻地盯着,保安叔叔也特别累。今天我们就来尝试用计算机自动检测人脸是否佩戴口罩的可行性,如果可行,那么根据我们以前的推送:人脸检测自动开机,就可以做一个实时摄像头,如果发现有人没戴口罩则发送警告给保安,以提高保安的工作效率。

当然,想要识别人脸是否佩戴口罩,需要做很多训练数据的收集,不过最近百度开源了他们的人脸口罩识别模型:PaddleHub 口罩检测。我们今天就来试试这个模型的效果。

1.准备

为了实现这个实验,Python是必不可少的,如果你还没有安装Python,建议阅读我们的这篇文章哦:超详细Python安装指南

然后,我们需要安装百度的paddlepaddle, 进入他们的官方网站就有详细的指引:
https://www.paddlepaddle.org.cn/install/quick

根据你自己的情况选择这些选项,最后一个CUDA版本,由于本实验不需要训练数据,也不需要太大的计算量,所以直接选择CPU版本即可。选择完毕,下方会出现安装指引,不得不说,Paddlepaddle这些方面做的还是比较贴心的(就是名字起的不好)

要注意,如果你的Python3环境变量里的程序名称是Python,记得将语句改为Python xxx,如下进行安装:

python -m pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple

还需要安装paddlehub:

pip install -i https://mirror.baidu.com/pypi/simple paddlehub

2.编写代码

Paddlehub作为一个深度学习平台,用起来还是相当方便的,尤其是对于我这种(调包小王子)非研究型应用者。一共就只有四个步骤:

  • 1.引入模块和图片
  • 2.载入模型
  • 3.分类与预测
  • 4.结果展示

把我们需要测试的图片保存在该代码文件的同一目录下,命名为3.jpg:

想看这个小姐姐摘下口罩的样子

代码如下:

import paddlehub as hub
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

# 1.待预测图片
test_img_path = ["./3.jpg"]

# 2.载入模型
module = hub.Module(name="pyramidbox_lite_mobile_mask")

# 3.预测
input_dict = {"image": test_img_path}
results = module.face_detection(data=input_dict)

# 4.结果展示
img = mpimg.imread("detection_result/3.jpg")
plt.figure(figsize=(10, 10))
plt.imshow(img)
plt.axis('off')
plt.show()

没错,你没看错,就是这么简单。去掉空行和注释只有12行代码,再狠一点,把matplot展示部分全部去掉,只有6行代码。

再再狠一点,把test_img_path和input_path变量以及module.face_detection语句合并,你会发现只有3行代码:

import paddlehub as hub
module = hub.Module(name="pyramidbox_lite_mobile_mask")
results = module.face_detection(data={"image": ["./3.jpg"]}) 

执行完后的分类结果在同一目录下的detection_result目录下查看即可。所以说,说20行代码是谦虚,3行代码就够了。

3.结果展示

我们测试的那张图片,结果如下:

MASK:97.64% 代表这个人戴了口罩,可信度为97.64%。
NO MASK: 97.41% 代表这个人没戴口罩,可信度为97.41%

最后面那个大叔也是MASK,但是它的可信度只有54.31%,所以很可能是误判,在我们实际应用的时候,只需要把警告阈值(比如80%)提高,即可筛去这些不可信的分类。

不过,这个模型有一个缺点就是,对于远距离的人判断并不是很精确:

离镜头最近的这个人可能是因为侧脸的原因,脸部特征不明显识别不出来。但是远处的这些戴着口罩却被识别为没戴口罩的,就是这个模型的锅了。不过,通过阈值过滤和缩短摄像头摄影距离还是可以将这个模型用于实际生活中的。

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


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

Python 优化—算出每条语句执行时间

用Python写的程序,确实在性能上会比其他语言差一些,这是因为Python为了最大化开发效率,牺牲了一定的运行效率。开发效率和运行效率往往是鱼与熊掌不可兼得的关系。

不过,程序性能较差有很多原因,并不能全把锅甩到Python身上,我们应该首先从自己的代码上找原因,找原因最快的方法就是算出自己写的语句或函数的执行时间。这时候,很多人都会选择用以下的形式打印出语句的执行时间:

import time
a = time.time()
temp = [index*index for index in range(1000000)]
b = time.time()
print(b-a) 

这是一种比较低效的做法,如果你有上万条语句要测试,想用这个方法来找到瓶颈简直是大海捞针。幸好,得益于Python强大的社区功能,我们有很多关于效率的模块可以使用,今天要介绍的是 line_profiler , 它可以算出函数里每条语句的占用时间。

我们将使用上次电影人脸识别中的代码进行讲解:Python 识别电影中的人脸,不过要注意,这篇推送里的函数少传递了几个参数,正确参数请点击该推送下方的阅读原文进行查看哦。

1.准备

Python环境当然是必备的,如果你还没有安装Python,可以看这篇文章:超详细Python安装指南

打开cmd/terminal输入以下命令安装line_profile:

 pip install line_profiler

windows机器如果出现 Microsoft Visual C++ 14.0 is required 这样的错误,请前往微软官网,下载vs2015勾选”适用于visual C++2015的公共工具” 进行安装。

如果出现:ModuleNotFoundError: No module named 'skbuild'的情况,请输入以下命令安装scikit-build:

pip install scikit-build

实在还是安装不上的话,可以下载anaconda,输入以下命令安装:

conda install -c anaconda line_profiler

2.使用

使用方式非常简单,比如原来我们在读取人脸的代码中,主函数是这样的:

if __name__ == '__main__':
    sourcePath = 'frames/greenbooks'
    targetPath1 = 'target/test'
    read_pic_save_face(sourcePath, targetPath1, '.jpg', '.JPG', 'png', 'PNG') 

我们要测的是read_pic_save_face函数中所有语句的执行时间,只需要这样调用line_profiler:

if __name__ == '__main__':
    sourcePath = 'frames/test'
    targetPath1 = 'target/test'
    # read_pic_save_face(sourcePath, targetPath1, '.jpg')

    profile = LineProfiler(read_pic_save_face)
    profile.runcall(read_pic_save_face, sourcePath, targetPath1, '.jpg')
    profile.print_stats()

这样就可以获得该函数所有语句的执行时间报表。当然,它还有许多其他的调用方法,具体可以看line_profiler说明文档: https://github.com/rkern/line_profiler

3.阅读报告

line_profiler报告包括几个部分:
Line: 语句位于第几行
Hits: 该行被执行的次数
Time: 该语句运行的总时间
Per Hit: 该语句运行一次的平均耗时
% Time: 该语句占总时间的比重

可以看到,我们的这份代码主要是在face_cascade.detectMultiScale 耗时最久,这是opencv的分类器执行效率问题。知道了是这里的效率问题,优化就有一个目标了。

这一部分的优化,我们可以从硬件方面入手,让OpenCV在GPU上运行算法,这样做性能将远超在CPU上运行的性能,这是绝招。其次就是利用多线程计算(没试过,不确定是否有用,或许下次可以试一下)。

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


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

Python 绘制悼念的词云蜡烛

谨以此文悼念伟大的李文亮医生。

《有的人》— 臧克家
有的人活着,他已经死了。
有的人死了,他还活着。
有的人,骑在人民头上:“啊,我多伟大!”。
有的人,俯下身子给人民当牛马。
有的人,把名字刻入石头,想“不朽”。
有的人,情愿作野草,等着地下的火烧。
有的人,他活着别人就不能活。
有的人,他活着为了多数人更好地活。
骑在人民头上的,
人民把他摔垮。
给人民作牛马的,
人民永远记住他!
把名字刻入石头的,
名字比尸首烂得更早;
只要春风吹到的地方,
到处是青青的野草。
他活着别人就不能活的人,
他的下场可以看到;
他活着为了多数人更好地活着的人,
群众把他抬举得很高,很高。

无奈才学疏浅,无法用更多的语言描述我对他的敬意。但是作为程序员,我也有我的悼念方式:用代码绘制词云组成的蜡烛用以悼念。

1.准备

基于Python,绘制悼念的词云蜡烛我们需要用到的包有:

  • pip install matplot
  • pip install scipy==1.2.1
  • pip install wordcloud
  • pip install jieba
  • pip install codecs
  • pip install pandas
  • pip install numpy

打开CMD/Terminal 输入以上命令即可安装。如果你还没有安装Python,可以阅读此篇文章:超详细Python安装指南

然后需要找到生成词云的文本和相关图片,这里我用的是BBC的一篇报道,还有这张蜡烛图片:

来源:图品汇

2.编写代码

整体代码如下,我编写了非常详细的注释,大家不懂得可以根据注释的提示进行查询和学习。

# coding:utf-8
import jieba
import numpy
import codecs
import pandas
import matplotlib.pyplot as plt
from scipy.misc import imread
import matplotlib.pyplot as plt
from wordcloud import WordCloud, ImageColorGenerator
from wordcloud import WordCloud
  
def load_file_segment():
    # 加载我们自己的词典
    jieba.load_userdict("mywords.txt")
    # 读取文本文件并分词
    f = codecs.open(u"text.txt",'r',encoding='utf-8')
    # 打开文件
    content = f.read()
    # 读取文件到content中
    f.close()
    # 关闭文件
    segment=[]
    # 保存分词结果
    segs=jieba.cut(content) 
    # 对整体进行分词
    for seg in segs:
        if len(seg) > 1 and seg != '\r\n':
            # 如果说分词得到的结果非单字,且不是换行符,则加入到数组中
            segment.append(seg)
    return segment
 
def get_words_count_dict():
    segment = load_file_segment()
    # 获得分词结果
    df = pandas.DataFrame({'segment':segment})
    # 将分词数组转化为pandas数据结构
    words_count = df.groupby(by=['segment'])['segment'].agg({"计数":numpy.size})
    # 按词分组,计算每个词的个数
    words_count = words_count.reset_index().sort_values(by="计数",ascending=False)
    # reset_index是为了保留segment字段,排序,数字大的在前面
    return words_count
 
words_count = get_words_count_dict()
# 获得词语和频数

bimg = imread('candle.jpeg')
# 读取我们想要生成词云的模板图片
wordcloud = WordCloud(background_color='white', mask=bimg, font_path='simsun.ttc')
# 获得词云对象,设定词云背景颜色及其图片和字体
 
# 如果你的背景色是透明的,请用这两条语句替换上面两条 
# bimg = imread(candle.jpeg')
# wordcloud = WordCloud(background_color=None, mode='RGBA', mask=bimg, font_path='simhei.ttc')
 

words = words_count.set_index("segment").to_dict()
# 将词语和频率转为字典
wordcloud = wordcloud.fit_words(words["计数"])
# 将词语及频率映射到词云对象上
bimgColors = ImageColorGenerator(bimg)
# 生成颜色
plt.axis("off")
# 关闭坐标轴
plt.imshow(wordcloud.recolor(color_func=bimgColors))
# 绘色
plt.show()

其中candle.jpeg是位于当前文件夹的蜡烛文件,simhei.ttc是位于当前文件夹的字体文件,mywords.txt是我自己生成的词表,text.txt便是用于生成词云的文本。

以上全部文件和源代码我都已上传到公众号后台,回复:悼念蜡烛 即可下载。

3.生成蜡烛词云

我将这份源代码命名为candle.py, 通过在命令行中运行:

python candle.py

即可获得该蜡烛词云

中华民族需要永远记住李文亮医生。


​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实用宝典

Python 监控文件增加、修改、删除等变化

现在有一个应用场景,需要对文件系统进行监控,发生变化时产生日志,对新增的文件做一些相应的操作。比如说应用到我们之前的高潮提取器:若当前文件夹下增加了一个音乐文件,监控器就调用高潮提取器提取该音乐文件的高潮部分。

这样的监控器写起来也不难,但是很花时间,有许多情况要考虑。不过幸好我们是写Python的,有许多轮子可以使用。

1.安装”看门狗”

“看门狗”模块就是用于监控文件事件变化的一个Python”轮子”,代码架构优秀,可以注册许多事件处理器,方便用户做自定义操作。如果你还没有安装Python,请看这篇文章《Python详细安装指南》,在终端输入以下命令即可安装看门狗:

pip install watchdog

2.基本使用

看门狗的使用其实不复杂,请认真看以下代码和注释:

import sys
import time
import logging
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s - %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')
    path = sys.argv[1] if len(sys.argv) > 1 else '.'

    # 生成事件处理器对象
    event_handler = LoggingEventHandler()

    # 生成监控器对象
    observer = Observer()
    # 注册事件处理器,配置监控目录
    observer.schedule(event_handler, path, recursive=True)
    # 监控器启动——创建线程
    observer.start()

    # 以下代码是为了保持主线程运行
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()

    # 主线程任务结束之后,进入阻塞状态,一直等待其他的子线程执行结束之后,主线程再终止
    observer.join()

可以看到代码中有几个关键步骤,1.配置各项信息;2.生成事件处理器、监控器;3.注册事件处理器、配置目录、递归执行(即同时监控子文件夹);4.启动。

其实,看门狗的observer是基于 threading.Thread 对象的,所以observer很多属性都继承了 threading.Thread 的属性。

如果你不带参数地运行该脚本,就是要监控脚本文件所在的文件夹,如果要监控其他文件夹,记得运行时带文件夹的路径参数,如:

python obserber.py /data/home/ckend/

我们来试着运行看看:

可以看到,我在当前文件夹下做的所有操作都被记录下来了。接下来我们就试试怎么自定义一些操作。

3.监控提取音乐高潮

如果你不知道怎么提取音乐文件的高潮部分,请看这篇文章:《Python自动提取音乐文件高潮》

要实现这样的功能,我们有几种方法,一个是在原来log的处理器上做一些新增修改,比如多增一个函数调用音乐高潮提取器。第二个是重新继承 FileSystemEventHandler 类,并做相应的修改。这里我们还是要保留log的样式,只是在log的时候顺便提取音乐高潮,因此采用第一个方法。

看看LoggingEventHandler源代码中的on_created,这就是当文件创建时监控器的操作:

class LoggingEventHandler(FileSystemEventHandler):
    """Logs all the events captured."""

    # ...省略其他源代码...

    def on_created(self, event):
        super(LoggingEventHandler, self).on_created(event)

        what = 'directory' if event.is_directory else 'file'
        logging.info("Created %s: %s", what, event.src_path)

我们仅需要继承这个类并对on_created进行修改,就能完成我们想要的功能:

# Python实用宝典
# 2019/12/29

import sys
import time
import logging
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler
from pychorus import find_and_output_chorus


class extractor(LoggingEventHandler):

    def on_created(self, event):
        super(LoggingEventHandler, self).on_created(event)
        what = 'directory' if event.is_directory else 'file'
        logging.info("Created %s: %s", what, event.src_path)
        NameExt = event.src_path.split('.')
        if NameExt[-1] == 'mp3':
            logging.info("mp3文件, 提取音乐高潮中...")
            output_path = "."+"".join(NameExt[:-1])+'_high.wav'
            find_and_output_chorus(event.src_path, output_path, 30)


if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s - %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')
    path = sys.argv[1] if len(sys.argv) > 1 else '.'

    # 生成事件处理器对象
    event_handler = extractor()

    # 生成监控器对象
    observer = Observer()
    # 注册事件处理器
    observer.schedule(event_handler, path, recursive=True)
    # 监控器启动——创建线程
    observer.start()

    # 以下代码是为了保持主线程运行
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()

    # 主线程任务结束之后,进入阻塞状态,一直等待其他的子线程执行结束之后,主线程再终止
    observer.join() 

首先声明一个类,继承LoggingEventHandler,然后重载on_created函数,在这个函数中不仅记录文件事件变化,还要对mp3文件做一次音乐高潮提取。最后别忘了,生成事件处理器时要用我们新的类名。

看看效果,将小永远.mp3复制过来:

成功监控文件变化并提取到音乐高潮,生成高潮文件。

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


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

Python 一个超快的公共情报搜集爬虫

Photon是一个由s0md3v开源的情报搜集爬虫,其主要功能有:

1.爬取链接(内链、外链)。
2.爬取带参数的链接,如(pythondict.com/test?id=2)。
3.文件(pdf, png, xml)。
4.密钥(在前端代码中不小心被释放出来的)。
5.js文件和Endpoint(spring中比较重要的监视器)
6.匹配自定义正则表达式的字符串。
7.子域名和DNS相关数据。

你可以用它来干很多事,比如爬图片、找漏洞、找子域名、爬数据等等。而且提取出来的数据格式非常整洁:

不仅如此,它甚至支持json格式 ,仅需要在输入命令的时候加上json参数:

python photon.py -u "http://example.com" --export=json

为什么能用来做情报搜集呢?耐心往后看哦。

1.下载安装

你可以上photon的github下载完整项目:
https://github.com/s0md3v/Photon

或者关注下方Python实用宝典公众号在后台回复photon获得国内网盘下载地址。下载后解压到你想要使用的地方。如果你还没有安装Python,建议阅读这篇文章:超详细Python安装指南,进行Python的安装。

安装完Python后,打开CMD(windows)/Terminal(macOS),下面简称这两种为终端,进入你刚解压的文件夹,然后输入以下命令安装Photon的依赖:

pip install -r requirements.txt

如图所示:

2.简单使用

注意,使用的时候要在Photon文件夹下。比如我们随便提取一个网站的URL试一下,在终端输入以下命令:

python photon.py -u https://bk.tencent.com/

结果如下:

它会在当前目录下产生一个你测试的域名的文件夹,比如在我这里是 bk.tencent.com:

嘻嘻,让我们看看里面有什么东西,有没有程序员留下的小彩蛋,打开external.txt,这是该网站的外链的存放位置。可以看到,这里不仅仅是只有网站页面,连CDN文件地址都会放在这里,所以external可能是个藏宝哦。

还能一下找出该网站上链接的全部开源项目:

3.扩展

这个项目的价值,不仅在于能够快速拉取你想要得到的数据,还在于能够构建一个牛逼轰轰的情报系统(如果你技术够强的话)。因为它是能不断延伸下去的,比如从外链出发,你能找到很多和这个网站相关的讯息:

相比于搜索引擎搜索的结果,实际上这些信息更符合情报要求。因为不是所有的信息都能在搜索引擎搜索得到,而通过这个Photon,你可以顺藤摸瓜找到那些隐藏在互联网世界的它们。试想一下,如果你搜集了很多这样的网站…然后用正则表达式搭建一个属于你自己的搜索引擎,这样的感觉是不是很棒?

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


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

Python 来算算一线城市的二手房价格指数相关性

Python中有很多方法计算相关性,scipy中有自带的分析工具,pandas里也有非常方便的多变量相关性分析。我们今天就讲讲这两个工具的用法。

1.数据收集

本文北上广深的数据采集自东方财富网,以二手房价格指数为例:

数据从2011年1月1日开始,每个数据点是当时一个月的价格指数,采集方法是用开发者工具找到请求发回来的JSON数据,方法如下:

数据如下(2011/1/1-2019/10/1):

# 北京:
bj = [100.3,100.4,99.9,100.1,99.8,99.9,100.1,100,99.6,99.5,99.3,99.2,99.1,99.8,100.2,100.4,99.9,100.2,100.3,100.3,100.1,100,100.3,101,101,102.2,103.1,102,101.7,101.3,101.4,101.2,101.3,101.1,101.2,100.6,99.9,100,100.2,99.8,99.1,98.7,99.2,99.1,98.6,100.3,100.7,100.2,100,99.9,100.5,102.1,104.3,102.3,102.6,102,101.4,101.1,101.4,101.7,102.3,103.2,106.3,103.7,102.3,101.4,101.6,103.9,105.7,101.1,100.2,100.2,100.8,101.3,102.2,100,99.1,98.9,99.2,99.1,99.4,99.5,99.5,99.6,99.4,99.5,99.8,99.9,100.3,100.1,100.4,100,99.8,99.8,99.4,99.8,99.9,100.2,100.4,100.6,100,100,99.7,99.6,99.5,99.4]
# 广州:
gz = [101.2,100.6,99.5,101,99.8,100.1,100.2,100.7,100.6,99.5,99.2,99.6,99.6,99.6,99.8,99.6,99.9,100.5,100.7,100.9,100.6,100.4,100.5,100.5,100.4,101.7,101.5,100.7,101.1,100.9,101,101,100.4,101,101.2,100.6,101,100.3,100.2,100.7,100.1,99.7,98.9,98.6,98.7,100,100,100.2,99.8,99.7,100,101.1,102.3,101.8,101.3,101,101.2,101.1,100.7,101,101.3,101.2,103.5,102.6,101.9,101.6,101.4,102.8,103.3,101.6,100.8,101.3,101.6,102.7,103.3,101,100.5,100.8,100.1,100,100.2,99.7,100.1,99.6,99.9,100.2,100.2,100.5,101,100.3,100.3,100.6,100.2,99.8,99.7,99.6,99.7,99.8,99.5,99.6,99.7,100,100.4,100,99.7,99.9]
# 上海: 
sh = [100.5,100.4,100.4,100.6,100.2,100.2,100.3,100.1,100.1,99.8,99.5,99.6,99.3,99.7,99.5,100.1,100.3,100.2,100.2,100.3,100.2,100.2,100.2,100.4,100.8,101.6,102.6,101.3,100.9,101.1,100.8,100.8,101,100.9,100.7,100.5,100.1,100.6,100.2,100,99.8,99.3,99.1,99.3,99.2,100,100,100.4,100.3,100.1,100,100.6,102.2,101.2,101.6,101.1,101,100.8,101,101.2,102.7,105.3,106.2,102.5,101.4,102.2,102,103.7,103.4,100.3,99.8,99.5,99.6,100.2,100.7,100.8,100,99.9,99.6,99.8,99.9,100.3,99.7,99.9,100.1,99.6,99.4,99.8,99.7,99.7,99.9,99.9,99.8,99.8,99.9,99.7,100,99.9,100.3,100.5,100.1,99.9,100.4,100,100.6,99.8]
# 深圳:
sz = [100.6,102.6,100.6,100.5,100.3,100,99.5,100,99.8,100,99.2,99.6,99.2,100,100.1,100,100,100.2,100.2,100.1,100.1,100.4,100.3,100.6,100.5,101.4,102.3,101.1,101,101.3,101,101.6,101.3,100.9,100.8,100.7,100.8,100.8,101.1,100.1,100.2,99.4,99.4,99.5,99.3,100,100.4,100.7,100.6,100.3,100.5,102.4,106.3,106.9,105.3,104.4,103.3,101,101.9,103.3,105.7,103.3,104.7,99.6,100,100.8,101.8,102,101.8,99.4,99.3,99.8,99.9,99.3,100.3,100.8,100.3,99.7,100.6,99.8,99.9,100.4,100.1,100.4,100.9,101.3,100.7,100.2,100.8,100.3,100.6,101.1,100,99.4,99.8,99.7,99.7,100.5,100.7,101.1,100,99.9,100.7,100.2,101.3,101] 

2.准备工作

首先,你要确保你的电脑安装了Python,如果没有可以看这篇文章:超详细安装Python指南

然后,打开CMD(开始-运行-cmd),或者Terminal(macOS) 输入以下指令安装scipy和pandas.

pip install scipy 
pip install pandas

3.编写代码

3.1 scipy计算相关性

scipy计算相关性其实非常简单,引入包的stats模块:

import scipy.stats as stats 

然后调用函数进行计算:

# 计算广州和深圳二手房价格指数相关性
print(stats.pearsonr(gz, sz))

结果如下:

F:\push\20191130>python 1.py
(0.4673289851643741, 4.4100775485723706e-07)

什么?!!广州和深圳的二手房价格指数相关性竟然才0.46?那其他一线城市和深圳对比呢?

不过,stats麻烦的地方就在于,它一次只能对比两个值,不能一次性两两对比四个一线城市,不过,有个模块可以。

3.2 pandas一次性两两对比计算相关性

首先引入pandas:

import pandas as pd

创建DataFrame存放四个数据:

df = pd.DataFrame()
df['北京'] = bj
df['上海'] = sh
df['广州'] = gz
df['深圳'] = sz 

最后相关性计算:

print(df.corr()) 

来看看结果:

wow,看来深圳的二手房价还真是与众不同,不过从下面这个图看,确实,深圳的二手房价格和北京的二手房价格已经出现了背离的情况。

个人认为,这个背离和最近的一系列政策及香港局势有关,但当前严峻的金融形势下,不会持续太久。

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


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

Blender, 用Python绘制宇宙飞船的3D建模软件

见过用Python进行3D建模操作的么?下面给你演示一下:

强不强?这就是Blender,一款能用Python进行建模的软件。

Blender是一个免费的开源3D计算机图形软件工具集,用于创建动画电影视觉效果,艺术品,3D打印模型,动态图形,交互式3D应用程序和计算机游戏

不仅如此,它还提供了一个Python与Blender交互的API: https://docs.blender.org/api/2.81/ ,使Python进行3D建模成为一种可能。

下面介绍一下这个宇宙飞船项目。这是一个比赛作品,作者用它参与了reddit的一个2016年6月的挑战赛。实现的原理并不复杂,就是从一个立方体开始建造船体,利用随机数增加船体的不确定性。然后慢慢地往船体增加细节,比如引擎、天线、炮塔、照明灯等等。

项目地址: https://github.com/a1studmuffin/SpaceshipGenerator

快来生成你的宇宙飞船

要想运行这个项目,你需要做如下准备:

1. 安装Blender 2.76以上:
https://www.blender.org/download/

2. 下载作者的生成代码(也就是已经和Blender做好API联调的代码)。
如果你访问不了Github, 可在公众号后台回复 宇宙飞船 下载这些代码。

3. 将下载好的代码( add_mesh_SpaceshipGenerator.zip, 以压缩包的形式)载入到blender中:

3.1 点击菜单栏里的 Edit — 选择Preferences.

3.2 选择左侧的Add-ons,然后点击install,选择刚刚下载下来的压缩包。

3.3 载入后记得勾选插件。

4. 使用快捷键shift+F5进入3D视图

5. 使用快捷键shift+A,这时候鼠标右键会弹出选项,在mesh中选择 Spaceship即可生成你的宇宙飞船!

怎么样,够不够帅?记得自己实践一下生成一个哦!

自己用Python进行DIY

如果你想自己再进行一下DIY,让飞船变得更帅气,那也是可以的!把下载下来的压缩包解压,里面会有一个文件叫spaceship_generator.py的,这个就是主要的模型生成代码。你能在里面看到作者的许多参数设置,稍微修改一下会有惊喜哦!

你也可以阅读完作者的这份源代码(也不多,就800行),自己学着做一个有别于宇宙飞船的3D模型!

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


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

Python 超简单3行代码提取音乐高潮(批量提取实战教程)

有些时候,为了设定手机铃声或者发抖音视频,我们会耗费大量时间在剪辑音乐高潮部分上。那么这个音乐高潮的提取能不能自动化呢?当然可以。

1.原理简介

不知道大家有没有这样的体会,大部分时候,歌曲的高潮部分通常是重复次数最多的部分。因此我们可以根据这一个特征,提出我们的算法

1.遍历整首歌曲。

2.将选定长度的部分与其他部分比较并计算相似度,以查看是否重复。

3.寻找重复次数较大、且间隔长的片段。

2.代码编写

为了避免造轮子,我们找到了别人已经做过的类似的项目:

https://github.com/vivjay30/pychorus

我们只需要分析这个源代码中最核心的部分,即求相似区段的源代码:

def compute_similarity_matrix_slow(self, chroma):
    """
    虽然慢,但是直接的方法来计算区段相似矩阵
    """
    num_samples = chroma.shape[1]
    time_time_similarity = np.zeros((num_samples, num_samples))
    for i in range(num_samples):
        for j in range(num_samples):
        # 检测每一段的相似度
            time_time_similarity[i, j] = 1 - (np.linalg.norm(chroma[:, i] - chroma[:, j]) / sqrt(12))
    return time_time_similarity 

可以看到,这部分代码就是做了我们算法的第二步,进行了片段与片段之间的相似度计算。检测时用到的相似函数是这样的:

这主要是因为歌曲由12个基本音符的帧的集合而组成,v1和v2是任意两段音乐的音符矢量,如果说两段音乐非常相似,那么右边的式子将接近于0. 如果说 1-右边的式子 得分非常高,则说明两段音乐非常相似

下面我们看看怎么使用这个项目求音乐高潮部分,其实非常简单。

2.1 安装所需要的项目

你可以通过pip安装该项目,如果你还没有安装好Python相关环境,建议阅读这篇文章:Python安装

pip install pychorus

2.2 编写代码

实际上,这个包用起来可是相当简单,如果我们只是想单纯提取歌曲高潮部分:

from pychorus import find_and_output_chorus
chorus_start_sec = find_and_output_chorus("你的音乐文件", "输出高潮部分文件", 要多少秒的高潮部分) 

没错,两行代码就解决了。下面让我们检验一下效果。

3.效果检验

以《孤芳自赏》 为例,让我们试试这个提取器的功力。

原曲:

https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/11/2019112414210248.mp3

编写代码:

# 提取音乐高潮部分
from pychorus import find_and_output_chorus
chorus_start_sec = find_and_output_chorus("孤芳自赏.mp3", "孤芳自赏_high.wav", 40)

效果如下:

https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/11/2019112414230277.wav

非常优秀!提取了我心目中想要的部分。大家也可以根据我们今天的教程,试着提取一下自己喜欢的音乐的高潮部分哦!

4.批量提取

刚刚,只是完成了单首歌曲的高潮提取,如果你想提取整个文件夹下的音乐的高潮部分,可以这样做:

# Python 实用宝典
# 提取音乐高潮部分
# 2020/06/11

import os
import sys
from pychorus import find_and_output_chorus


def extract_all_file(files_path):
    """
    批量提取音乐高潮

    Args:
        files_path (str): 文件夹路径
    """

    # 文件夹路径
    modpath = os.path.dirname(os.path.abspath(sys.argv[0]))

    for filepath in os.listdir(files_path):

        # 路径处理
        datapath = os.path.join(modpath, files_path + filepath)

        # output文件夹是否存在
        targets = f"{modpath}\\output\\"
        if not os.path.exists(targets):
            os.makedirs(targets)

        # 提取音乐高潮至当前output文件夹下
        find_and_output_chorus(
            datapath, f"{targets}{filepath.split('.')[0]}_high.wav", 40
        )


extract_all_file("F:\\push\\20200611\\music\\")

这样就可以实现批量提取音乐高潮的功能。

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

音乐相关教程:

Python 批量下载网易云音乐歌单

Python 制作音乐高潮副歌提取器

Python Django快速开发音乐高潮提取网(1)

Python Django快速开发音乐高潮提取网(2)

Python Django快速开发音乐高潮提取网(3)

Python 超方便超快速剪辑音乐

Python 提取音乐频谱并可视化


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