所有由Python实用宝典发布的文章

Python 免登录微博数据爬虫(仅研究使用)

微博数据是非常有价值的数据,这些数据可以用作我们进行一些系统开发时的数据源, 比如前段时间发过的:Python 短文本识别个体是否有自杀倾向,在此文中,我们使用微博绝望树洞的数据,利用SVM做了一个简单的自杀倾向识别模型。

当然,微博数据的应用还不仅如此,如果你大胆详细,大胆猜测,将会有许多可以利用这些数据进行研究的机会。不过, 技术是把双刃剑,有好有坏,我不希望各位拿着这个爬虫去做一些违反道德、法律的事情,应用于好的事务,才是技术诞生的初衷。

本文讲的是以用户为单位的爬虫,如果你希望能够定制自己需要的爬虫,请看这篇教程:Python 爬取微博树洞详细教程

1.准备

其实免登录的原理很简单,就是通过手机版的微博绕过其登录验证,大家可以用手机网页打开这个网址,你会发现其实大部分微博在你不登录的情况下都是可见的:
https://m.weibo.cn/u/2075686772

可见即可爬。因此,我们只需要调用这个微博数据的json接口即可获取到数据。不过我们不要一上来就直接撸代码,要善于利用Python开源社区的特点,上网上找相关的现成的成熟轮子,而不是自己动手做一个半成熟版,这样能节省许多时间。

经过一番搜索,我找到了这个免Cookie版的微博爬虫,dataabc开发的:
https://github.com/dataabc/weibo-crawler

其代码思路与我想的差不多,只需要调用json的数据接口即可获取数据:

下载该开源项目,可以上该网页直接Download, 也可以使用git:

git clone https://github.com/dataabc/weibo-crawler.git

如果你两个都不会,没关系,Python实用宝典后台回复 微博采集工具 即可下载。

2.配置采集参数

在开始采集数据前,你需要确保电脑上已经安装了Python,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

安装完Python后,Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal).

进入我们刚下载好的文件夹,输入以下命令安装所需要的模块:

pip install -r requirements.txt

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

2.1 找到你需要爬的用户ID

点开你希望爬取的用户主页,然后查看此时的url,你会发现有一串数字在链接中,这个就是我们要用到的userID, 复制即可。

如果不是一串数字,可以点开任一条微博评论的页面,这时候上面的链接一定会有串数字,如果还是没有,就上手机版的微博页面找,这种时候就需要耐心和多尝试了。

2.2 修改config.json

获得用户的userID后,需要将ID写入到config.json的user_id_list数组中,如图所示:

其他参数如:
filter:控制爬取范围,值为1代表爬取全部原创微博,值为0代表爬取全部微博(原创+转发)
since_date: 爬取该日期之后的时间
write_mode: 写入的文件格式

下面的分别是:是否下载原创微博图片、是否下载转发微博图片、是否下载原创视频、是否下载转发的视频,如果为1则是,为0则为否。再往后如果你需要写入数据库,还可以配置MySQL或MongoDB的连接参数。

3.开始采集

配置好了以后,采集就很简单了,你只需要用CMD或Terminal进入该文件夹,输入:

python weibo.py

即可进行数据采集。采集结束后,如果你设定的是保存为csv文件,则会在当前文件夹下的weibo文件夹里产生一个名为该微博用户名的数字.csv文件,如:

weibo\阿森纳足球俱乐部\2075686772.csv

这个文件里就是你想要的数据。

该开源模块设计的功能其实非常完善,你看看下面这个列表就知道了。

真的太贴心辣,必须得感谢这位开源作者,如果你喜欢的话,记得上去他的仓库给他点个star哦!

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


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

Python 一键吸猫!找出磁盘里所有猫照

最近在整理我磁盘上的照片,发现不少猫照,突然觉得若能把这些猫照都挑出来,观察它们的成长轨迹也是一件不错的事情。一张一张的找实在是太费劲了,能不能自动化地找出来呢?

目标检测,是许多计算机视觉应用的重中之重,比如说我们上次的实例分割:Python 20行代码批量自动抠图,人体关键点提取、人脸识别等。而我们这一次,是要识别猫照。由于时间不多,我们没有时间收集训练集,那么有没有已经训练好的目标检测模型呢?

这时候就要搬出paddlehub了,puddlehub有一个模型叫做YOLOv3,基于 Joseph Redmon和Ali Farhadi提出的单阶段检测器。该检测器与达到同样精度的传统目标检测方法相比,推断速度能达到接近两倍。

YOLOv3将输入图像分成S*S个格子,每个格子预测B个bounding box,每个bounding box预测内容包括: Location(x, y, w, h)、Confidence Score和C个类别的概率,因此我们不仅能够找出猫的照片,还能定位它的位置!甚至能自动数出一张照片里有多少只猫!

1.准备

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

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

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

不过虽然它里面写了这么多,大部分人用一句话安装,打开CMD(Win+R)或者Terminal(Command+空格搜索)输入以下命令即可安装:

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

还需要安装paddlehub,这点别忘了:

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

2.编写代码

我们先试试单图片识别,找到猫猫:

新建predict.py文件,存放猫照在当前文件夹的imgs文件夹下,命名为c1.jpg. 输入以下代码:

import paddlehub as hub

# 加载模型
yolov3 = hub.Module(name="yolov3_darknet53_coco2017")

# 图片位置
test_img_path = "imgs/c1.jpg"

# 输入图片
input_dict = {"image": [test_img_path]}

# 输出结果
results = yolov3.object_detection(data=input_dict)
for result in results:
    print(result['path'])
    print(result['data']) 

在终端/CMD输入以下命令运行文件:

>> python predict.py
[{'left': 684.79376, 'right': 2024.4724, 'top': 961.53644, 'bottom': 2299.855, 'label': 'cat', 'confidence': 0.94765514}, {'left': 1461.0829, 'right': 3853.3633, 'top': 621.53064, 'bottom': 2769.5376, 'label': 'cat', 'confidence': 0.8093604}]

可以看到,识别到了两只猫,其中第一只猫顶部位置为961,右部位置为2024,左部位置为684,底部位置为2299。根据这个位置,可以用框框标记出两只猫:

编写代码,用于框出相应位置的猫:

def paint_rect(input_img: str, output_path: str,
               labels: list, position: list):
    """
    画出矩形
        :param input_img: 输入图片
        :param output_path: 输出图片
        :param labels: 标签
        :param positions: 坐标
    """
    img = cv2.imread(input_img)

    for position in positions:
        print(position)
        # 画矩形框, 输入参数分别为图像、左上角坐标、右下角坐标、颜色数组、粗细
        cv2.rectangle(
            img, (position['left'], position['top']),
            (position['right'], position['bottom']),
            (0, 255, 0), thickness=10
        )

    if 'cat' in labels:
        # 若是猫,则存到另一个地方
        shutil.move(input_img, output_path + os.sep + input_img.split('/')[-1])
        cv2.imwrite(output_path + os.sep + 'rect_%s' % input_img.split('/')[-1], img) 

3.批量自动识别

这样,我们就有思路进行自动识别了,首先获得该文件夹下所有的图片,其次,将这些图片都放入分类器中进行分类,最后,再根据分类的标签将其提取出来移动到其他地方。

获得该文件夹下所有图片:

def get_all_path(dirpath, *suffix):
    """
    获得所有路径

    @param dirpath: 目录
    @param *suffix: 后缀
    """

    path_array = []
    for r, ds, fs in os.walk(dirpath):
        for fn in fs:
            if os.path.splitext(fn)[1] in suffix:
                fname = os.path.join(r, fn)
                path_array.append(fname)
    return path_array 
# 获得所有jpg和png图片
image_paths = get_all_path(source_path, '.jpg', '.JPG', 'png', 'PNG') 

放入分类器中分类:

# 加载模型
yolov3 = hub.Module(name="yolov3_darknet53_coco2017")
# 输入图片
input_dict = {"image": image_paths}
# 输出结果
results = yolov3.object_detection(data=input_dict, labels=['cat']) 

根据标签画框并移动:

def paint_rect(input_img: str, output_path: str,
               labels: list, position: list):
    """
    画出矩形
        :param input_img: 输入图片
        :param output_path: 输出图片
        :param labels: 标签
        :param positions: 坐标
    """
    img = cv2.imread(input_img)

    for position in positions:
        # 画矩形框, 输入参数分别为图像、左上角坐标、右下角坐标、颜色数组、粗细
        cv2.rectangle(
            img, (position['left'], position['top']),
            (position['right'], position['bottom']),
            (0, 255, 0), thickness=10
        )

    if 'cat' in labels:
        # 若是猫,则存到另一个地方
        shutil.move(input_img, output_path + os.sep + input_img.split('/')[-1])
        cv2.imwrite(output_path + os.sep + 'rect_%s' % input_img.split('/')[-1], img) 

results = yolov3.object_detection(data=input_dict, labels=['cat'])
for result in results:
    path = result['path']
    labels = []
    positions = []
    for target in result['data']:
        labels.append(target.get('label', ''))
        positions.append({
            'left': target.get('left', -1),
            'top': target.get('top', -1),
            'right': target.get('right', -1),
            'bottom': target.get('bottom', -1)
        })
    paint_rect(path, target_path, labels, positions)  

完整代码如下,希望大家都能成功提取出自己的“猫片”:

import paddlehub as hub
import cv2
import os
import shutil


def get_all_path(dirpath, *suffix):
    """
    获得所有路径

    @param dirpath: 目录
    @param *suffix: 后缀
    """

    path_array = []
    for r, ds, fs in os.walk(dirpath):
        for fn in fs:
            if os.path.splitext(fn)[1] in suffix:
                fname = os.path.join(r, fn)
                path_array.append(fname)
    return path_array


def paint_rect(input_img: str, output_path: str,
               labels: list, position: list):
    """
    画出矩形
        :param input_img: 输入图片
        :param output_path: 输出图片
        :param labels: 标签
        :param positions: 坐标
    """
    img = cv2.imread(input_img)

    for position in positions:
        # 画矩形框, 输入参数分别为图像、左上角坐标、右下角坐标、颜色数组、粗细
        cv2.rectangle(
            img, (position['left'], position['top']),
            (position['right'], position['bottom']),
            (0, 255, 0), thickness=10
        )

    if 'cat' in labels:
        # 若是猫,则存到另一个地方
        shutil.move(input_img, output_path + os.sep + input_img.split('/')[-1])
        cv2.imwrite(output_path + os.sep + 'rect_%s' % input_img.split('/')[-1], img)


if __name__ == '__main__':
    source_path = './imgs/'
    target_path = './target/'

    # 获得所有jpg和png图片
    image_paths = get_all_path(source_path, '.jpg', '.JPG', 'png', 'PNG')

    # 加载模型
    yolov3 = hub.Module(name="yolov3_darknet53_coco2017")

    # 输入图片
    input_dict = {"image": image_paths}

    # 输出结果
    results = yolov3.object_detection(data=input_dict, labels=['cat'])
    for result in results:
        path = result['path']
        labels = []
        positions = []
        for target in result['data']:
            labels.append(target.get('label', ''))
            positions.append({
                'left': target.get('left', -1),
                'top': target.get('top', -1),
                'right': target.get('right', -1),
                'bottom': target.get('bottom', -1)
            })
        paint_rect(path, target_path, labels, positions)

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


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

AO3被封的冤不冤?可视化数据分析《下坠》

AO3是一个外网自由创作网站,全称为 Archive of Our Own 其在Alexa的世界排名居于第690名,是雨果最佳相关作品奖的获得者。作为一个非盈利性的开源同人小说数据库网站,站内的文章均由网友贡献,因此也没有核查机制。

1月30日,网友“博君一肖”在AO3发布并连载了一篇同人文《下坠》,并在微博同步上传了这篇文章,而且自设了预警,希望接受不了的人不要点开。

几天后,这篇文章连载到12章,而且微博原文包含了ao3网站和lofter app链接,引起了大量博肖cp粉热转。

26日,许多粉丝觉得该cp文中含有侮辱性文字,无法接受这样的文字,于是开始撕X,网上举报阵营和lof阵营开始对线,互相口吐芬芳,展现了中华民族几千年来的文化底蕴。

事件持续发酵,最终闹到了某办,某办一看,我X,原来还有这个漏网之鱼,顺手就给他封了。真的太冤了,不过也不能说人家乱封,为什么呢?因为同人文大多是读者在原作的基础上把某些作品里的人物放在新的环境里,以展现自己和原作不同的观念,而大多数时候,这些观念最终都会掺杂色情因素。看看我们下文对《下坠》的分析就知道了。

本文完整分析代码可在公众号后台回复:下坠 获得。本文不详细分析代码,不过这份代码的知识,你可以在这两篇文章里学习到:

1. Python 情人节超强技能 导出微信聊天记录生成词云

2. Python 识别文本情感就这么简单

1.词频统计

我们利用Python里的jieba分词、matplotlib模块分析整篇文章词汇,并提取词频前20的词语,得到结果如下:

确实,涉及到两位明星的词语是最多的,其次是阿丽姐(不知道是不是作者的化身)。赞赞在其中是女性角色,难怪粉丝们暴跳如雷。这样分析,似乎看不出太多的内含,我们把维度细化一点。

从敏感角度看,这个词汇频率会是怎样的呢?由于纯洁的我实在是接受不了,因此打了点马赛克(如果这样你都能猜出是什么词….嗯…建议多看看天线宝宝):

经过统计,文章出现一共20367个非黄色词汇,284个涉黄词汇。涉黄词汇出现概率约为1.4%,也就是说每100个词汇里就会出现一次黄词,这个概率相当高了,感觉《挪威的森林》略逊一筹,《失乐园》大可一战。

最后,来个词云结束这一部分:

2.句型分析

我们使用Lstm,按行对整片文章进行分析,看看这些句子呈现的情感特点是否有某边倒的倾向,其中,当分为正面信度大于0.7,或负面信度大于0.7的时候分别分到正面分类和负面分类,其他情况为中性:

得到结果如下:

>>{‘neg’: 988, ‘pos’: 332, ‘mid’: 471}

负面的句子占了55%,文章负面情绪较多。负面情绪只是衡量一篇文章的情感倾向,无法说明什么。

接下来才是关键,识别句子的涉黄程度,同样地,设定概率置信度大于0.7的时候进行分类:

获得结果如下:

>> {‘porn’: 280, ‘not_porn’: 1511}

1800条句子中,280条语句涉黄,概率高达16%. 每100条句子中就有约16条黄色片段,《失乐园》可能都甘拜下风啊。到这里,大家可能都会觉得这篇同人文被举报是非常正常的(尽管粉丝们不满的是某位明星被当成女性角色)。

当然,大家如果感兴趣还可以用词法分析工具分析文章中的攻防次数,非常有意思,但是涉及到敏感词汇,我这里就不再展开了(逃)。本文完整分析代码可在公众号后台回复:下坠 获得。

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


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

你的10W块放哪里能赚最多钱?

现在许多人都想学会理财并进行适当的投资,从而增加“睡后收入”,迈向财务自由。说到投资,最经典的当然是股市了,但股市对于大部分人而言是烫手山芋,无法从中获得稳定的收益。因此,对于大部分人而言,最好的投资产品还是基金。

​基金分为好几种,因此收益的计算公式也分许多种,我们这里介绍三种最常见的收益计算方式,从而找到收益最高的那种基金:

第一种是七日年化收益。最常见的是余某宝和一些理财基金。

第二种是每日万份收益。许多产品可能会用它作为指标。

第三种是定投基金。大多是一些股票投资组合基金,比理财基金风险高,但也是最值得投资的,请往后看。

1.余某宝

我们先尝试利用七日年化收益算算余某宝现在的收益,这可是这些年的明星产品啊,今天2020年2月27日的七日年化收益率为2.306%:

觉得我穷的就赞赏一个吧,嘻嘻

七日年化收益的计算方法是这样的:
当日收益 = 金额 X 7日年化 ÷ 360。

Python 计算代码计算最终收益:

假设我们投入10W元,放180天:

>> profit_7_days(100000, 0.023, 180)
(101156.60076153441, 1156.6007615344133)

最终利润为1156元,太少了,这个利润绝对跑不过CPI,要知道,2020年1月份CPI同比上涨5.4%哦。当然,还是比放银行活期好得多。

2.活期理财

市面上还有许多保守型活期/定期理财,我们选最高利率的一种来试一下,这一个采用万份收益来计算:

万份收益的计算公式如下:
当日收益 = 金额 ÷ 10000 X 当日万份收益。

Python代码如下:

假设我们投入10W元,放180天:

>> profit_10_thousand(100000, 1.0485, 180)
(101905.12125702304, 1905.1212570230418)

哎,比余额宝好不了多少嘛,那我还不如继续用余额宝。

3.定投基金

定投基金比较有意思,是我们今天的主角。它属于“保守版”的​高风险投资,因为分散投资能够有效规避风险,面对股市无常的变化,定投的基金并不会产生太大的影响,所以相对安全,收益也相对稳定。

它的计算公式如下:

M=a(1+b)[-1+(1+b)^n]/b

其中:
1. M表示定投n年后总金额(包括收益和本金);
2. a表示每年投入的金额(比如每月投入1200元,a=14400元);
3. b表示年收益率(比如年收益为50%,其b=0.5);
4. ^n表示n次方。

比如这一款基金,最近三年涨跌幅分别为:69.07%, 51.3%, 66.3%. 平均下来年涨跌幅为62%,非常可怕:

不过今年由于疫情影响,估计最终收益会低许多,我们算40%的年收益率吧。

Python代码如下:

假设我们每个月投一万块钱,持续一年:

>> profit_investment_plan(10000, 0.40, 1)
(167999.99999999994, 47999.99999999994, 0.8117274492919773)

没错,最终赚了约4.8W,其第一年真实的年化收益率为 81%,如果第一年结束取出来,其总利率达到了 47999/167999 = 28.5%.

原来,基金定投才是投资的最好姿势啊!不过,收益越高,风险越高,虽然基金定投能够很好地避免股市波动,但是它还是存在不小的风险的。

如果想获得稳健的收益,个人建议你需要将钱放在不同的篮子里以规避风险,比如每月收入的30%定投基金,20%理财基金,10%指数型基金,20%债券基金,20%活期基金(如余额宝之类)。当然,最适合的搭配要根据个人收入进行组合。

市面上有许多可靠的基金定投,只要选择那种最近几年没有负收益的,遇到市场形式较好的时候,基本上收益都能跑得过CPI,微X的某财通里就有很多,为了避免广告嫌疑,这里就不再多介绍啦。本文全部的计算代码,可在公众号后台回复 基金投资计算 获得。

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


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

编程零基础如何在半年内熟练掌握python?

这个问题是在知乎上遇到的,我觉得特别有意义,所以单独发篇推送来讲讲我的看法。不过这个问题得看我们如何定义熟练掌握了,如果你只是想会写爬虫,独立编写办公小程序,按照我下面的步骤进行学习,半年是有可能的。

如果是想用Python来找工作的话,半年还是有难度的,需要多做点项目,熟练掌握Python的一些特点,尤其是一些面向对象的编程方法。

学Python最重要的就是学会用别人已经造好的轮子进行快速而又高效的开发,可以从应用练习入手,再到一些数据分析的项目,最后如果能自己学会熟练使用TensorFlow或PyTorch或者Web开发框架Django,基本超越了绝大部分人了。

1.基础学习

阅读《Think Python》或者廖雪峰的Python教程。 读完前八章,到面向对象编程即可,后续的知识可以在不断的实操训练中学习。

不过,如果你的目标是找到工作,那建议全部阅读完,而且还要加增学习:《Python核心编程》。如果你访问不了github,可以关注Python实用宝典公众号,后台回复:核心编程

2.应用练习

基础学习完毕后,就要开始练习一些简单的实操性项目巩固学习,Python实用宝典过去的许多文章其实都是这样的简单实操性项目,非常适合大家用来熟练掌握一些包的应用。

比如打水印:超简单Python安全批量打水印教程!

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

文献搜索工具:你不得不知道的python超级文献搜索工具

向手机发送通知:教你如何使用Python向手机发送通知(IFTTT)

爬虫练习:Python 爬取“微博树洞”详细教程

然后是用微博树洞做数据分析:Python 短文本自动识别个体是否有自杀倾向

哄哄女朋友:Python导出微信聊天记录并生成词云

3.进阶学习

进阶学习,就要深入学习一些框架。深度学习的,有TensorFlow和pyTorch,甚至Keras也是不错的选择。当然,也可以尝试一些更上层的框架,比如paddlehub:

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

Web开发,可以考虑Django和Flask框架,我们有用过Django开发一个简单的网站:
Django:Python 快速开发高潮音乐提取网

如果你只是想成为超级极客,可以看看这些文章: 

树莓派+智能音箱:Python声控普通风扇Python声控开机

树莓派+摄像头:Python人脸识别开机

Python 深度学习图像风格迁移

我们的文章到此就结束啦,如果你希望我们今天的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] > 1] = 1
    # 饱和度
    hlsCopy[:, :, 2] = (1.0 + saturation / float(MAX_VALUE)) * hlsCopy[:, :, 2]
    hlsCopy[:, :, 2][hlsCopy[:, :, 2] > 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] > 1] = 1
    # 饱和度
    hlsImg[:, :, 2] = (1.0 + saturation / float(MAX_VALUE)) * hlsImg[:, :, 2]
    hlsImg[:, :, 2][hlsImg[:, :, 2] > 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实用宝典曾写过一篇文章(《短文本分类识别自杀倾向》),教你从构建数据集到训练数据,再到测试数据,整个流程确实需要耐心的人才能成功走通。

不过现在有了paddlehub,我们可以先省略掉构建数据集和训练数据这两个步骤,直接拿模型过来文本分类

一旦简单版的分类成功了,你就会有动力继续前进,继续学习如何训练属于自己的模型。

今天我们用paddlehub中比较简单的情感倾向分析模型 senta_lstm 来对文本做一个简单的积极和消极的分类。

1.准备

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

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

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

不过虽然它里面写了这么多,大部分人用一句话安装,打开CMD(Win+R)或者Terminal(Command+空格搜索)输入以下命令即可安装:

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 paddlehub as hub

# 加载模型
senta = hub.Module(name="senta_lstm")

# 待分类文本
test_text = [
    "你长得真好看",
    "《黑色四叶草》是部不错的番"
]

# 情感分类
results = senta.sentiment_classify(data={"text": test_text})

# 得到结果
for result in results:
    print(result)

将这份代码保存为 code.py, (如果你懒得打一遍,可以再公众号后台回复 识别文本情感 获得代码)在CMD或Terminal中进入该文件文件夹运行以下命令执行脚本: python code.py

就能得到以下结果:

{‘text’: ‘你长得真好看’, ‘sentiment_label’: 1, ‘sentiment_key’: ‘positive’, ‘positive_probs’: 0.9866, ‘negative_probs’: 0.0134}
{‘text’: ‘《黑色四叶草》是部不错的番’, ‘sentiment_label’: 1, ‘sentiment_key’: ‘positive’, ‘positive_probs’: 0.9401, ‘negative_probs’: 0.0599}

其中:
1.sentiment_key 代表分类结果,postive是 积极 ,negative是 消极 。
2.sentiment_label 是分类结果标签,1代表 积极 ,0代表 消极 。
3. positive_probs 是积极分类的置信度,0.9866即模型判断98.66%的可能性是正面。
4. negative_probspositive_probs 相对,是消极分类的置信度。

3.结果分析

这么看,你会发现其实在有明显的积极消极词汇面前,这个模型的分类效果还是不错的。那在特殊的例子面前效果又如何呢?我们去微博随便取一条试一下,比如银教授的段子:

分类结果:

{‘text’: ‘他们都网上办公、网上学习了,你什么时候跟我网恋?’, ‘sentiment_label’: 0, ‘sentiment_key’: ‘negative’, ‘positive_probs’: 0.0507, ‘negative_probs’: 0.9493}

竟然意外的分对了。虽然是句段子,但是明显有对方不跟自己网恋的消极态度。再试试有潜在含义的句子:

{‘text’: ‘不想说什么了,听首歌吧。’, ‘sentiment_label’: 0, ‘sentiment_key’: ‘negative’, ‘positive_probs’: 0.0321, ‘negative_probs’: 0.9679}

{‘text’: ‘我忘了世界还有一种人火星人,你从那来的吧。’, ‘sentiment_label’: 1, ‘sentiment_key’: ‘positive’, ‘positive_probs’: 0.7261, ‘negative_probs’: 0.2739}

这里第一句分对了,第二句没分对。确实,第二句太隐晦了,机器可能分不出来。不过,置信度并不高,如果真的需要应用这个模型,可以通过置信度过滤掉一些分类。

总的而言,这个模型效果还是不错的,在网上那么多情感分类开源的模型中,百度的这个应该可以打80分左右。

而且,它支持你自己做一些微调(Fine-tune),也就是能够使用自定义的训练集调整模型到你需要的样子,详见github:
https://github.com/PaddlePaddle/models/tree/develop/PaddleNLP/sentiment_classification

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


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

有趣,用Python算算哪个星座富豪最多!

最近经常看到关于星座的推送,我其实不信这个,但是由于推送得太多了,总有几篇会让我好奇地点进去看看。然后想想其实用Python写一篇星座相关的文章也不错。

正好,Python计算一个人的星座特别简单,因为每个星座的日期是固定的。我们只需要四行代码就能计算:

def cal_constellation(month, day):
    constellation = (u'摩羯座',u'水瓶座',u'双鱼座',u'白羊座',u'金牛座',u'双子座',u'巨蟹座',u'狮子座',u'处女座',u'天秤座',u'天蝎座',u'射手座')
    start_day = ((1,20),(2,19),(3,21),(4,21),(5,21),(6,22),(7,23),(8,23),(9,23),(10,23),(11,23),(12,23))
    return constellation[len(list(filter(lambda y:y<=(month,day), start_day)))%12]

把出生的月份和日期传入这个函数,就能得到对应的星座了。当然,这只是非常简单的第一步,接下来让我们计算2012全球富豪榜前一百名中,哪个星座的人最多,嘻嘻,期待吗?

1.获得数据

豆瓣上有个帖子帮我们列出了相应的数据,不过是以文本的形式:https://www.douban.com/group/topic/28671832/

幸好有统一的格式,我们能用正则表达式把出生日期提取出来:

(\d+) ?月 ?(\d+) ?日

在Vscode中还能直接用模式替换,变成我们想要的元组形式:

最后发现有出生月日的只有88条,没关系,够我们用了。

2.放入代码计算

将前面获得的所有日期放入数组中,然后调用我们一开始说的星座计算函数即可,当然,需要用一个字典来计算每次星座的出现:

birth_day = [
    (1, 28), (10, 28), (8, 30), (3, 5), (3, 28), (8, 17), (11, 3), (10, 4), (7, 29), (2, 20), (11, 1),
    (5, 3), (8, 4), (10, 21), (7, 7), (10, 7), (10, 28), (4, 19), (2, 14), (6, 15), (8, 12), (4, 26),
    (8, 21), (3, 26), (1, 12), (4, 2), (9, 9), (3, 7), (2, 20), (2, 9), (3, 28), (11, 5), (4, 16), (1, 14),
    (4, 12), (6, 12), (9, 1), (5, 14), (9, 21), (8, 26), (2, 23), (5, 7), (7, 24), (3, 24), (9, 26), (1, 3),
    (2, 24), (1, 21), (7, 8), (2, 16), (8, 16), (10, 10), (9, 1), (4, 21), (5, 3), (4, 28), (8, 21), (12, 1),
    (12, 14), (10, 6), (1, 27), (4, 14), (6, 4), (10, 24), (5, 11), (8, 26), (1, 1), (6, 14), (8, 11), (5, 22),
    (5, 10), (4, 10), (5, 9), (12, 22), (12, 11), (3, 20), (3, 8), (9, 22), (12, 19), (11, 17), (9, 15), (3, 25),
    (2, 7), (4, 4), (4, 1), (6, 2), (2, 13), (11, 8)
]
def cal_constellation(month, day):
    constellation = (u'摩羯座',u'水瓶座',u'双鱼座',u'白羊座',u'金牛座',u'双子座',u'巨蟹座',u'狮子座',u'处女座',u'天秤座',u'天蝎座',u'射手座')
    start_day = ((1,20), (2,19), (3,21), (4,21), (5,21), (6,22), (7,23), (8,23), (9,23), (10,23), (11,23), (12,23))
    return constellation[len(list(filter(lambda y:y<=(month,day), start_day)))%12]

result = {}
for birth in birth_day:
    constel = cal_constellation(birth[0], birth[1])
    if constel not in result:
        result[constel] = 0
    else:
        result[constel] += 1
print(result)

结果如下:

{‘水瓶座’: 7, ‘天蝎座’: 7, ‘处女座’: 8, ‘双鱼座’: 7, ‘白羊座’: 12, ‘狮子座’: 8, ‘天秤座’: 5, ‘金牛座’: 9, ‘巨蟹座’: 1, ‘双子座’: 5, ‘摩羯座’: 3, ‘射手座’: 4}

排个序吧:

print(sorted(result.items(), key=lambda item: item[1]))

结果:

[(‘巨蟹座’, 1), (‘摩羯座’, 3), (‘射手座’, 4), (‘天秤座’, 5), (‘双子座’, 5), (‘水瓶座’, 7), (‘天蝎座’, 7), (‘双鱼座’, 7), (‘处女座’, 8), (‘狮子座’, 8), (‘金牛座’, 9), (‘白羊座’, 12)]

白羊座惊为天人达到了12位。12/88 = 14%啊,这个比例相当牛皮了。然而我的巨蟹座只有1位,枯了,难道我没有成为富豪的天赋??

不过,大家也不要伤心。我们只取了88名富豪的数据还不够多,像这样的数据分析大概要8888名富豪的出生日期才能得到一个比较靠谱的结果。

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


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号: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实用宝典