六月 25th, 2017 by lanxinxichen@126.com

一、 使用ffmpeg找出视频插入的关键帧

起因:某天晚上看一个科技评测节目,该节目宣称只要能够在视频中找到视频中插入的某一帧无关内容,就可以获得相应的奖品。我想了想应该是可以用代码实现的:

  1. 拿到该视频的文件

使用python3的一个工具you-get就能够做到。不过稍有曲折,我使用you-get去下载B站和优酷的视频都下载失败了,好在在该测评节目微博上找到了另外一个视频资源链接,使用you-get顺利下载下来,视频是640×360的,十分钟内容一共60M的MP4格式。

  1. 将视频逐帧抽离成为图片。

我先按照原样抽离,即抽离成640×360的图片,一共生成了8,988个文件,大小1.80 GB,不禁感慨视频压缩格式确实厉害啊,这压缩了多少倍啊,另外我考虑到可能更小的缩略图应该也拥有足够的分辨特征,所以也按照64×36的分辨率抽离了更小的缩略图
大图抽帧
640×360逐帧抽离的图片截图
小图抽帧
64×36逐帧抽离的图片截图

  1. 对比任意相邻图片的相似度。

图像相似度算法我没具体研究过,直接用的github上面的项目:https://github.com/MashiMaroLjc/Learn-to-identify-similar-images
一共有有四种算法,具体中文的文章可以参看链接:
https://segmentfault.com/a/1190000004467183 
我使用了不同的算法得到的不同的结果:
由于之前excel的制图删掉了,只能用当时程序计算的文本信息凑合了,计算出来的相似度大致就是如下的数字列表。
照片相似度对比结果

  1. 绘图寻找关键帧

其实就是根据特征去拟合一条折线,能够正确反映出异常的关键帧在哪里。
关键帧表格绘制
其实这一步,我做了两三个小时,为了选择最佳的算法和最佳的效果,只有下图能够直截了当的反映出异常的帧在哪里,后来我想了想,如果加入跳帧的对比,比如第一帧和第三帧的特征,就能够更加准确的找到关键帧的位置。
 
http://mp.weixin.qq.com/s/K2YCm8QwnpI7dNTs048Jbg
 

二、 ffmpeg做音频剪辑命令

叠加两个声音,并按照第一个声音的长度截取音乐,然后输出16k,单声道,声音质量为4的音乐:

ffmpeg -i example1.wav -i example2.wav -filter_complex amix=inputs=2:duration=first -ar 16k -ac 1 -q:a 4 output.wav

 
参考:https://ffmpeg.org/ffmpeg-filters.html
 
重复某个音频文件4次并截取80秒的音频数据

ffmpeg -stream_loop 4 –I example.wav -c copy -t 80 output.wav

 
从00:00:15开始截取音频、视频,截取5s,然后原样输出到文件中

ffmpeg -ss 00:00:15 -t 00:00:05 –I example.mp4 -vcodec copy -acodec copy output.mp4

 
pcm(已知pcm文件格式为16k 16bit 单声道)转换到固定格式的wav文件中

ffmpeg -f s16le -ar 16k -ac 1 -i tts_file_119.pcm -ar 16k -ac 1 tts_file_119.wav

对音频文件增加渐入渐出过滤效果(淡入从0秒开始,持续10秒,淡出从50秒开始,持续10秒,设定音乐音量为2, -y为覆盖已存在文件)

ffmpeg -i input.mp3 -af “afade=t=in:ss=0:d=10,afade=t=out:st=50:d=10,volume=volume=0.2” -t 60 output.mp3 –y

更多声音过滤器:http://ffmpeg.org/ffmpeg-filters.html
 
设定背景音乐,循环播放并增加淡入淡出效果

ffmpeg -stream_loop 4 -iinput.wav -af “afade=t=in:ss=0:d=10,afade=t=out:st=50:d=10,volume=volume=0.2” -t 80 output.wav

 
一般来讲 ffmpeg的文件后缀都是自适应的,比如你设置的输出格式是mp3,那么文件就能自动转换成该格式的文件,具体的采样率等参数需要单独去设置调整。

Posted in Coding, Python Tagged with: ,

一月 14th, 2017 by lanxinxichen@126.com

TypeError: not enough arguments for format string

使用Python连接数据库的时候,采用的非常非常轻量级的torndb,甚至于事务都不支持,所以用”select * from table where condition=’%s'” % (condition,)

因为用的比较原生,所以各种问题接连不断,最最恶心的就是字符串转义造成的一些列原因.

先采用

condition = re.escape(condition)

能对特殊字符进行转义,但是还是有问题,又报错TypeError: not enough arguments for format string 直到认真看输入的condition字符串的时候,才发现问题所在之处: condition中有% 需要替换%为%%才能正常执行,

condition= condition.replace('\%', '%%')

其实标题有问题,不只是操作数据库,只不过在操作数据库时候,忽略的字符串本身的内容,一直在错误的寻找解决方案.

Posted in Coding, Python, 数据库 Tagged with: ,

四月 8th, 2016 by lanxinxichen@126.com

从今天开始,准备更一个读书笔记系列的博客,一方面把看到书中有用的东西记录下来,方便自己日后查阅,另一方面也是为了自我监督,多读书,多学习.

第1章       机器学习基础

机器学习如何解决分类问题?
机器学习如何解决分类问题,它的主要任务是将实例数据划分到合适的分类中。机器学习的另一项任务是回归,它主要用于预测数值型数据。大多数人可能都见过回归的例子——数据拟合曲线:通过给定数据点的最优拟合曲线。分类和回归属于监督学习,之所以称之为监督学习,是因为这类算法必须知道预测什么,即目标变量的分类信息。
用于执行分类、回归、聚类和密度估计的机器学习算法

监督学习的用途
k-近邻算法 线性回归
朴素贝叶斯算法 局部加权线性回归
支持向量机 Ridge 回归
决策树 Lasso 最小回归系数估计
无监督学习的用途
K-均值 最大期望算法
DBSCAN Parzen窗设计

如何选择合适的算法?
首先考虑使用机器学习算法的目的。如果想要预测目标变量的值,则可以选择监督学习算法,否则可以选择非监督学习算法。确定选择监督学习算法之后,需要进一步确定目标变量类型,如果目标变量是离散型,如是/否、1/2/3、A/B/C或者红/黄/黑等,则可以选择分类算法;如果目标变量是连续型的数值,如0.0~100.00、-999~999或者+∞~-∞等,则需要选择回归算法。
如果不想预测目标变量的值,则可以选择非监督学习算法。进一步分析是否需要将数据划分为离散的组。如果这是唯一的需求,则使用聚类算法;如果还需要估计数据与每个分组的相似程度,则需要使用密度估计算法。
其次需要考虑的是数据问题。我们应该充分了解数据,对实际数据了解得越充分,越容易创建符合实际需求的应用程序。主要应该了解数据的以下特性:特征值是离散型变量还是连续型变量,特征值中是否存在缺失的值,何种原因造成缺失值,数据中是否存在异常值,某个特征发生的频率如何(是否罕见得如同海底捞针),等等。充分了解上面提到的这些数据特性可以缩短选择机器学习算法的时间。
 
开发机器学习应用程序的步骤

  1. 收集数据。我们可以使用很多方法收集样本数据,如:制作网络爬虫从网站上抽取数据、从RSS反馈或者API中得到信息、设备发送过来的实测数据(风速、血糖等)。提取数据的方法非常多,为了节省时间与精力,可以使用公开可用的数据源。
  2. 准备输入数据。得到数据之后,还必须确保数据格式符合要求,本书采用的格式是Python语言的List。使用这种标准数据格式可以融合算法和数据源,方便匹配操作。本书使用Python语言构造算法应用,不熟悉的读者可以学习附录A。

此外还需要为机器学习算法准备特定的数据格式,如某些算法要求特征值使用特定的格式,一些算法要求目标变量和特征值是字符串类型,而另一些算法则可能要求是整数类型。后续章节我们还要讨论这个问题,但是与收集数据的格式相比,处理特殊算法要求的格式相对简单得多。

  1. 分析输入数据。此步骤主要是人工分析以前得到的数据。为了确保前两步有效,最简单的方法是用文本编辑器打开数据文件,查看得到的数据是否为空值。此外,还可以进一步浏览数据,分析是否可以识别出模式;数据中是否存在明显的异常值,如某些数据点与数据集中的其他值存在明显的差异。通过一维、二维或三维图形展示数据也是不错的方法,然而大多数时候我们得到数据的特征值都不会低于三个,无法一次图形化展示所有特征。本书的后续章节将会介绍提炼数据的方法,使得多维数据可以压缩到二维或三维,方便我们图形化展示数据。

这一步的主要作用是确保数据集中没有垃圾数据。如果是在产品化系统中使用机器学习算法并且算法可以处理系统产生的数据格式,或者我们信任数据来源,可以直接跳过第3步。此步骤需要人工干预,如果在自动化系统中还需要人工干预,显然就降低了系统的价值。

  1. 训练算法。机器学习算法从这一步才真正开始学习。根据算法的不同,第4步和第5步是机器学习算法的核心。我们将前两步得到的格式化数据输入到算法,从中抽取知识或信息。这里得到的知识需要存储为计算机可以处理的格式,方便后续步骤使用。

如果使用非监督学习算法,由于不存在目标变量值,故而也不需要训练算法,所有与算法相关的内容都集中在第5步。

  1. 测试算法。这一步将实际使用第4步机器学习得到的知识信息。为了评估算法,必须测试算法工作的效果。对于监督学习,必须已知用于评估算法的目标变量值;对于非监督学习,也必须用其他的评测手段来检验算法的成功率。无论哪种情形,如果不满意算法的输出结果,则可以回到第4步,改正并加以测试。问题常常会跟数据的收集和准备有关,这时你就必须跳回第1步重新开始。
  2. 使用算法。将机器学习算法转换为应用程序,执行实际任务,以检验上述步骤是否可以在实际环境中正常工作。此时如果碰到新的数据问题,同样需要重复执行上述的步骤。

 

第2章       k-近邻算法

k-近邻算法概述:
k近邻算法采用测量不同特征值之间的距离方法进行分类。
优点:精度高、对异常值不敏感、无数据输入假定。
缺点:计算复杂度高、空间复杂度高。 适用数据范围:数值型和标称型。
 
k近邻算法的一般流程

  1. 收集数据:可以使用任何方法。
  2. 准备数据:距离计算所需要的数值,最好是结构化的数据格式。
  3. 分析数据:可以使用任何方法。
  4. 训练算法:此步骤不适用于k近邻算法。
  5. 测试算法:计算错误率。
  6. 使用算法:首先需要输入样本数据和结构化的输出结果,然后运行k近邻算法判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理。

实施kNN分类算法:
对未知类别属性的数据集中的每个点依次执行以下操作:

  1. 计算已知类别数据集中的点与当前点之间的距离;
  2. 按照距离递增次序排序;
  3. 选取与当前点距离最小的k个点;
  4. 确定前k个点所在类别的出现频率;
  5. 返回前k个点出现频率最高的类别作为当前点的预测分类。

 
kNN使用想法:
分别使用书中提供的kNN算法和scikit中的KneighborsClassifier算法进行运算,相同参数下,书中的kNN算法准度和时间都优于scikit的算法,本来以为K值的设置是没有什么意思的,仔细阅读代码发现,kNN的思想是找到一个点的周围邻居,然后画一个圈,这个圈中最多的分类就是预测的分类.故此算法有一定的去噪能力.至于kNN的实用性,感觉不是很大,因为计算太频繁了,而且没有累计,下次的新数据依然需要大量计算, 我个人很在意机器学习的累积效果,如果没有累积效果,那就是普通的算法.
 
推荐阅读: http://www.cnblogs.com/zichun-zeng/p/3995040.html

Posted in 机器学习 Tagged with: ,

十一月 26th, 2015 by lanxinxichen@126.com

python以其强大和简洁的语言让人折服,那么究竟有多强大,多简洁呢?在今天学习python的过程中,我来举个例子。
in:将以下列表转化成{‘a’:1,’b’:2}的形式

var = [('a','A',1),
       ('b','B',2),
       ('c','C',3)]

方法1:

tmp1 = []
tmp2 = []
for i in range(3):
 val1 = var[i][0]
 val2 = var[i][2]
 tmp1.append(val1)
 tmp2.append(val2)
tmpdict = {}.formatkeys(tmp1,0)
for i in range(3)
 tmpdict[tmpdict.keys()[i]] = tmp2[i]

当然我有意的拉长了代码。
方法2:

tmp1 = []
tmp2 = []
for i in range(3):
 tmp1.append(var[i][0])
 tmp2.append(var[i][2])
tmpdict = dict(zip(tmp1,tmp2))

采用zip压缩数组,然后转换成dict
方法3:

 tmpdict = {i[0]:i[2] for i in var}

一句话循环并组成字典。
同样的还有很多地方用到,比如lambda,reduced,filter,cmp等这类函数的应用。能大大减少代码量。更有意思的可以查看:一行 Python 能实现什么丧心病狂的功能?
 
 

Posted in Python Tagged with:

十一月 25th, 2015 by lanxinxichen@126.com

目标:在不删除python环境的情况下,安装一些常用的python库到windows中。
安装
VCForPython27 :windows下面vc库的安装软件。
Numpy : numpy windows下面的exe文件
scipy : scipy 的exe文件
matplotlib : pip 环境下的 whl 安装包,需要使用pip install 这个文件.whl 安装
 
下面工具还不熟悉,先不写描述了。
setuptools
python_dateutil
pyparsing
 
 
 

Posted in Python, 机器学习 Tagged with: ,

十一月 24th, 2015 by lanxinxichen@126.com

最近做项目使用scrapy,采用的是script的形式去写爬虫的,使用crawlspider去定义爬虫规则。
我先从数据库里面把我要读取的规则拿出来,采用的是单个频道写规则的形式,对每个列表页写一套规则,所以有next_page的规则。

sql = """SELECT id, weburl_id, name, allow_domains, start_urls, next_page,
      allow_url, extract_from, title_xpath, body_xpath, publish_time_xpath, source_site_xpath, enable
      FROM leiju_rules WHERE enable > 0"""

next_page分析形式是xpath提取链接,使用Rule不跟随(follow = False)。我的需求是我应该采集所有的页面,但是由于我想做成定时任务,就需要下次还使用这一套规则来运行爬虫,做到增量爬。这样的话就涉及到了内容的去重。开发的最开始,我才用的是pipline 通道去重,也就是当我产生一个request之后才开始判断这个内容我需要不需要,这样是很浪费服务器资源的。

if self.Redis.exists('url:%s' % item['url']):
    raise DropItem("Duplicate item found: %s" % item['url'])
else:
    self.Redis.set('url:%s' % item['url'], 1)
    return item

然后我修改成采用downloadMiddleware下载中间件去控制访问,因为downloadMiddleware是可以控制在request访问之前的,加上Redis的过滤。

if Redis.exists('url:%s' % response.url):
    raise IgnoreRequest("IgnoreRequest : %s" % response.url)
else:
    Redis.set('url:%s' % response.url, 1)
    return response

这时候又有一个问题了,就是我会把所有的访问都给记录下来,下次我连我写的起始start_urls都进不去了。本来寄托于从以下代码入手:

rule_list.append(Rule(LinkExtractor(restrict_xpaths=rule['next_page'])))

即希望通过next_page拿到下一页的链接,然后把这些链接排除掉,已经准备好了一个Redis库去存储这些url。

Filter = redis.StrictRedis(host='127.0.0.1', port=6379, db=2, password='pass123456')

然而实际在使用的时候发现我通过:

rule_list.append(Rule(LinkExtractor(restrict_xpaths=rule['next_page'])))

拿到的根本不是URL列表,而是一个Rule对象,里面包括了LinkExtarctor的Xpath规则。我甚至想通过response和xpath拿到链接之后在用redis存起来进行排除。
 
解决方法:
配合使用pipline和downloadMiddleware来轻松完成以上功能。
我先定义一个downloadMiddleware,用来拦截url,防止重复访问。

class IngoreHttpRequestMiddleware(object):
    """ 从下载器处开始拦截/过滤URL """
    def process_response(self, request, response, spider):
        if Redis.exists('url:%s' % response.url):
            raise IgnoreRequest("IgnoreRequest : %s" % response.url)
        else:
            # Redis.set('url:%s' % response.url, 1)
            return response

然后定义一个pipline,用来保存最终流入pipline的item URL。

class FilterUrlPipline(object):
    """ use redis to fileter url """
    def __init__(self):
        self.Redis = config.Redis
    def process_item(self, item, spider):
        self.Redis.set('url:%s' % item['url'], 1)
        return item

这样一来,我的一个列表页面的所有链接都进入到了downloadMiddleware中,但是通过pipline拿到了最终我要的终极页面,通过pipline保存item URL,然后下次的时候redis里面有了数据,就可以排除所有的符合的终极页面访问请求,这样就解决了。
 
已开源在github上面:https://github.com/fengxiaochuang/ScrapyDemo

Posted in Python Tagged with: , , ,