这篇文章主要介绍Mac下常用的效率工具,也许正是你所需要的或者使用后对你的工作有很大的效率提升,废话不多说,看下面介绍的五款常用效率工具。

Alfred

 
Alfred

Alfred 作为神器的霸主地位可谓实至名归,它不仅可以帮我们快速打开切换应用、打开网址,使用计算器、词典、剪贴板增强等功能,还可以通过Workflow模块实现功能的扩展,下面详细介绍一下此神器的一些功能。

首先我们定义调出 Alfred 的快捷键,这里我设置的是 Command + Space ,可以启动输入框。

Alfred

在输入框中我们可以输入想要打开或切换的应用:

Alfred

也可以输入基本的数学公式,计算结果:

Alfred

或者去 Google 搜索:

Alfred

打开 Terminal 执行命令:

Alfred

在 Web Search 中配置自定义打开的网址:

Alfred

调出剪贴板历史,我设置的快捷键是 Option + Command + C:

Alfred

默认回车会执行第一个结果,或打开网址,或将结果复制到剪贴板,这样可以极大地提高我们操作的效率。
 
当然这些默认的功能是不能够满足我们的,还可以通过 Worklow 去扩展效率工具,这里是自己做的一个效率工具箱 xyzUtils :

Alfred

Github 地址: https://github.com/noogel/Alfred-Workflow

这里我做了一些开发中常用的数据转换功能,时间戳与时间的互相转换、Unicode码中文转换、随机字符串生成、IP查询、base64编码解码、MD5生成等,回车复制结果到剪贴板,举例如下:

Alfred

网友们还提供了更多的 自定义功能,可自行知乎。

Jietu

Jietu

这个是腾讯提供的免费截图工具,可进行区域截图或者屏幕录制功能,可以快捷编辑截图,也是我常用的一个神器。配置信息如下图:

Jietu

截好图后可以按 空格键 进行快速编辑,很是方便,截图后会自动放到剪贴板,可直接粘贴到微信、QQ、Slack等应用的对话框中。

Jietu

 

Hammerspoon

Hammerspoon

这款神器和上面的 Alfred 功能点有些重合,可以提供快速启动应用、调整窗口大小等功能。通过自定义 Lua 脚本实现所需的功能,这些功能主要通过绑定快捷键实现功能出发,当然也会绑定一些系统事件触发脚本功能。

目前在网上搜集了一些基本功能,调整窗口比例,连接到办公区网络自动静音等功能。

Hammerspoon

 

Time Out

Time Out

这款工具主要是可以帮助久用电脑的人每隔一段时间暂停一下,我这里设置的每隔 50分钟暂停 3分钟,就是在这 3分钟时间这个软件会弹出屏保提醒你稍事休息一下再工作,当然暂停期间是可以随之取消的,暂停的时候就是这个样子的。

Time Out

Reeder

这是一款 Mac 上知名度很高的 RSS 阅读器,简洁的外观与便捷的操作方式可以省去了去个站点看文章。结合Mac 触控板的左右滑动操作还是很方便的。

Reeder

Reeder

最后,来还有一些常用效率工具会在在后面的文章继续介绍,或许正是你所需要的,敬请期待!

开发工程师常用工具箱

全局预览

1

支持的命令

2

  • ntime 时间戳转换,支持标准时间格式与时间戳自动检测转换,回车复制结果到剪贴板
  • nb64d Base64 解码
  • nb64e Base64 编码
  • nmd5 MD5 生成
  • ncny 数字转人民币大写
  • nu2c Unicode 码转中文
  • nc2u 中文转 Unicode 码
  • nip IP 地址查询
  • nrdm 随机字符串生成,输入长度
  • nhelp 列出所有支持的命令

欢迎大家补充。

个人博客

知一的指纹

Github

Noogel’s github Alfred-Workflow

Update at 2017-08-17

先上两张桌面和开发环境见下图
桌面
开发环境

系统优化

更新源

更新前先设置源为aliyun的,国内访问速度快。

更新源

1
2
sudo apt-get update
sudo apt-get upgrade

删除Amazon的链接

1
sudo apt-get remove unity-webapps-common

主题美化

先装 Unity 图形管理工具

1
sudo apt-get install unity-tweak-tool

然后安装 Flatabulous 主题

1
2
3
sudo add-apt-repository ppa:noobslab/themes
sudo apt-get update
sudo apt-get install flatabulous-theme

和配套图标

1
2
3
sudo add-apt-repository ppa:noobslab/icons
sudo apt-get update
sudo apt-get install ultra-flat-icons

更换操作如下图:


至此主题美化完成

System Load Indicator(系统状态指示器)

1
2
3
sudo add-apt-repository ppa:indicator-multiload/stable-daily
sudo apt-get update
sudo apt-get install indicator-multiload

微软雅黑

字体下载

1
2
3
tar zxvf YaHeiConsolas.tar.gz
sudo mv YaHeiConsolas.ttf /usr/share/fonts
sudo chmod 755 /usr/share/fonts/YaHeiConsolas.ttf

安装zsh

1
2
3
sudo apt-get install zsh
zsh --version
sudo chsh -s $(which zsh)

然后再重新注销登录就好了

必装软件

下面介绍的软件有一部分是通过 deb 文件安装的,具体安装方式见 系统使用技巧。

系统软件

  • 浏览器: Chrome
  • 搜狗输入法: sougoupinyin
  • 为知笔记: wiznote
  • 系统状态指示器: System Load Indicator
  • SS你懂得: Shadowsocks-Qt5
  • Unity图形管理工具: unity tweak tool
  • 图片编辑工具: gimp
  • 思维导图: xmind
  • EPUB文件编辑: sigil
  • Linux下的Dash: zeal
  • Linux下Albert: albert
  • 网易云音乐播放器
  • Robomongo

数据库及工具

  • mysql
  • mongodb
  • redis
  • MySQL Workbench

开发环境

  • Python IDE: Pycharm

命令行工具

  • zsh
  • oh-my-zsh
  • vim
  • git

系统使用技巧

DEB软件安装

  • 安装命令

sudo dpkg -i xxx.deb

  • 安装过程中可能会报缺少依赖的错,执行下面命令自动安装依赖

sudo apt-get install -f

  • 再次执行安装命令

sudo dpkg -i xxx.deb

卸载不再依赖的包 命令

sudo apt-get autoremove

未完待续,欢迎大家发送你的优化点到我的邮箱 noogel@163.com

交易过程:

  1. 客户下单
  2. 客户完成支付
  3. 商家接单
  4. 商家发货

从软件开发角度, 还有一些非功能性需求需要实现:

  1. 性能: 特别是秒杀的时候,如何满足高频率的支付需求?
  2. 可靠性:不用说,系统能达到几个9,是衡量软件设计功力的重要指标。 99%是基础, 99.999%是目标,更多的9哪就是神了。
  3. 易用性:支付中多一个步骤,就会流失至少2%的用户。 产品经理都在削尖脑袋想想怎么让用户赶紧掏钱。
  4. 可扩展性: 近年来支付业务创新产品多,一元购、红包、打赏等,还有各种的支付场景。 怎么能够快速满足产品经理的需求,尽快上线来抢占市场,可扩展性对支付系统设计也是一个挑战。
  5. 可伸缩性:为了支持公司业务,搞一些促销活动是必须的。 那促销带来的爆发流量,最佳应对方法就是加机器了。 平时流量低,用不了那么多机器,该释放的就释放掉了, 给公司省点钱。

典型支付系统架构:

某旅游公司:

京东金融:

支付系统一般会提供如下子系统:

  1. 支付应用和产品.(应用层): 这是针对各端(PC Web端、android、IOS)的应用和产品。 为各个业务系统提供收银台支持,同时支付作为一个独立的模块,可以提供诸如银行卡管理、理财、零钱、虚拟币管理、交易记录查阅、卡券等功能;
  2. 支付运营系统(应用层): 支付系统从安全的角度来说,有一个重要的要求是,懂代码的不碰线上,管运营的不碰代码。这对运营系统的要求就很高,要求基本上所有线上的问题,都可以通过运营系统来解决。
  3. 支付BI系统(应用层): 支付中产生大量的数据,对这些数据进行分析, 有助于公司老板们了解运营状况,进行决策支持。
  4. 风控系统(应用层):这是合规要求的风险控制、反洗钱合规等。
  5. 信用信息管理系统(应用层):用来支持对信用算法做配置,对用户的信用信息做管理。
    支付系统一般会提供如下子系统:
  6. 支付应用和产品.(应用层): 这是针对各端(PC Web端、android、IOS)的应用和产品。 为各个业务系统提供收银台支持,同时支付作为一个独立的模块,可以提供诸如银行卡管理、理财、零钱、虚拟币管理、交易记录查阅、卡券等功能;
  7. 支付运营系统(应用层): 支付系统从安全的角度来说,有一个重要的要求是,懂代码的不碰线上,管运营的不碰代码。这对运营系统的要求就很高,要求基本上所有线上的问题,都可以通过运营系统来解决。
  8. 支付BI系统(应用层): 支付中产生大量的数据,对这些数据进行分析, 有助于公司老板们了解运营状况,进行决策支持。
  9. 风控系统(应用层):这是合规要求的风险控制、反洗钱合规等。
  10. 信用信息管理系统(应用层):用来支持对信用算法做配置,对用户的信用信息做管理。

http://www.bijishequ.com/detail/95641

坑1:浮点数不精确性

1
2
In [1]: 0.1+0.1+0.1-0.3
Out[1]: 5.551115123125783e-17

解决办法:

1
2
3
In [2]: from decimal import Decimal
In [3]: Decimal('0.1') + Decimal('0.1') + Decimal('0.1') - Decimal('0.3')
Out[3]: Decimal('0.0')

坑2:Decimal使用问题

1
2
In [5]: Decimal(0.1) + Decimal(0.1) + Decimal(0.1) - Decimal(0.3)
Out[5]: Decimal('2.775557561565156540423631668E-17')

解决办法:
参照坑1的解决办法,Decimal传入值需要str类型
更多用法查看:https://docs.python.org/2/library/decimal.html

坑3:四舍五入不准确问题

1
2
3
4
5
6
In [3]: '{:.2f}'.format(Decimal(str(1001.8250)))
Out[3]: '1001.82'
In [2]: Decimal('1001.8250').quantize(Decimal('0.01'))
Out[2]: Decimal('1001.82')
In [4]: round(2.55, 1)
Out[4]: 2.5

解决办法:
发现问题原因为在不能正确四舍五入的float数值中都是因为数据存储末位的.5被存储为.4999999…的形式,解决办法是在.5上加.1的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def exact_round(num, exp=2):
"""
准确的四舍五入方法
:param num: 数值
:param exp: 保留精度
:return:
"""
str_num = str(num)
dec_num = Decimal(str_num)
exp_unit = Decimal('0.1') ** exp
mini_unit = Decimal('0.1') ** (exp + 1)
if dec_num % exp_unit == (5 * mini_unit):
dec_num += mini_unit
return Decimal(dec_num).quantize(exp_unit, rounding=ROUND_HALF_EVEN)

为了验证这个方法写了个测试脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
摘 要: exact_round.py
创 建 者: abc
创建日期: 2017-01-05
"""
__author__ = "abc"

from decimal import Decimal, ROUND_HALF_EVEN


def exact_round(num, exp=2):
"""
准确的四舍五入方法
:param num: 数值
:param exp: 保留精度
:return:
"""
str_num = str(num)
dec_num = Decimal(str_num)
exp_unit = Decimal('0.1') ** exp
mini_unit = Decimal('0.1') ** (exp + 1)
raw_num = dec_num
if dec_num % exp_unit == (5 * mini_unit):
dec_num += mini_unit
raw_result = Decimal(raw_num).quantize(exp_unit, rounding=ROUND_HALF_EVEN)
result = Decimal(dec_num).quantize(exp_unit, rounding=ROUND_HALF_EVEN)
if result != raw_result:
print "raw:round({}, {}) = > {}; fixed: round({}, {}) => {}".format(
raw_num, exp, raw_result,
dec_num, exp, result
)
return result

if __name__ == "__main__":
val = 900.0000
while val < 1001.8600:
for exp in range(0, 6):
exact_round(val, exp=exp)
val += 0.0005

脚本中我们将被修正过的数据打印出来,发现被打印出来的都是四舍五入不正确的数值,经过方法处理可以保证准确的输出。

因为我们的测试只是覆盖了部分的数值,精度深度也只到到了6位,也不能保证说方法没有问题。
后来询问了在银行做开发的朋友,他们对于数据的计算都是在数据库的存储过程中运算的,并对上面坑中的数值放到数据库中做四舍五入发现确实没有问题。

于是我将这个方法做的运算与数据库的运算结果做对比写了测试脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
摘 要: test_db_round.py
创 建 者: abc
创建日期: 2017-01-06
"""
__author__ = "abc"
import os
import sys

sys.path.append(os.path.dirname(os.path.split(os.path.realpath(__file__))[0]))

from lib.utils import exact_round
from model import Model

def test_db_round(val, exp):
"""
test_db_round
:return:
"""
sql = "SELECT round({}, {}) as val".format(str(val), exp)
db_round = Model().raw(sql)[0]["val"]
exa_round = exact_round(val, exp)
if str(db_round) != str(exa_round):
print "db:{}; ex:{}".format(str(db_round), str(exa_round))

if __name__ == "__main__":
val = 900.0000
while val < 1001.8600:
for exp in range(0, 6):
test_db_round(val, exp=exp)
val += 0.0005

经过测试后发现没有数据被打印出,证明在测试范围内Python方法和数据库的运算结果没有差异。

关于浮点数不精确性的事情相信学过计算机组成原理这门课程的都明白,这里不再赘述,放个链接:
从如何判断浮点数是否等于0说起——浮点数的机器级表示

话说为什么要在Python中做财务相关运算呢,可能最初开发这个系统的人缺乏这方面的经验,然后通过扩展精度保留位数来解决这个问题的,但终究在做四舍五入时可能产生1分的差异。
既然发现这个问题,本着眼里不揉沙子的态度,快速的解决方案是在Python中替换原来的四舍五入函数,长期策略是逐步将计算过程挪到数据库通过存储过程来实现。

  1. Firefox + Firepath、Chrome + XPath Helper
  2. 常用xpath例子
  3. Python 使用XPath匹配页面数据
  4. 参考

Firefox + Firepath、Chrome + XPath Helper

如下图 Firefox下,XPath需要通过Firebug + Firepath来方便的获取。
firefox xpath

Chrome下,通过XPath Helper插件实现,开启和关闭快捷键Ctrl + Shift + X,按住Shift键获取。
chrome xpath heloer

以上两种方式还是Firefox下使用比较方便,更多用法自行发掘。

常用xpath例子

根据字符串匹配节点,通过contains()text()匹配
.//*[@id='detail_all']/div[1]/ul/li[contains(text(), '字 数:')]/text()

节点属性不包含**字符串,通过not()contains()匹配
.//*[@id='con_ListStyleTab4A_1']/p[not(contains(@class, 'title'))]/a[@class='Author']/text()

截取字符串匹配
substring-before(//div[@class='content']/ul/li[6],',')
substring(.//h2/../p/span[contains(text(), '字数:')]/text(), '4')

索引匹配末尾节点,通过last()匹配
.//div[last()]/div[@class='show_info_right max_width']/text()

通过..向上级查找匹配
.//h1/../div[@class='booksub']/span/span/text()

获取过个节点下的内容,通过//node()/text()可以获取当前节点及其子节点的内容。
.//*[@id='job_detail']/dd[@class='job-advantage']//node()/text()

有的时候页面中一系列数据下面并不一定包含某些字段,这时我们通过contains()来匹配包含某些关键字的节点来寻找对应的另一个节点。
.//div[@class='infobox']//node()[contains(text(), '户型')]/../node()/text()

这里总结一点使用技巧,更多的关于XPath的方法可以看参考中的链接,足以解决大部分问题。

Python 使用XPath匹配页面数据

对于爬虫抓取中XPath是一种比较高效的获取数据的方式,在各个爬虫框架中也很多的使用到,具体的用法大致相同,细微之处可自行摸索。以下是最简单的一种方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#! /usr/bin/python
# -*- coding:utf-8 -*-
"""
@author: abc
@file: xpath_demo.py
@date: 2017-02-04
"""
__author__ = "abc"

import lxml.html

import requests


if __name__ == "__main__":
url = "http://noogel.xyz"
res = requests.get(url)
doc = lxml.html.document_fromstring(res.content)
title_xpath = ".//header[@id='header']//a[@class='brand']/span[@class='site-title']"
print doc.xpath(title_xpath)[0].text

XPath是我在做爬虫任务时接触的,这只是整个环节中的一小部分,关于爬虫的一些抓取技巧(动态页面抓取、数据清洗、任务调度等)请关注博客后续更新的文章。


参考

http://www.cnblogs.com/barney/archive/2009/04/17/1438062.html
http://www.w3school.com.cn/xpath/xpath_functions.asp

基本操作

Hexo:简单、快速、强大的Node.js静态博客框架

NPM:NodeJS包管理工具

淘宝NPM镜像

https://npm.taobao.org/

直接使用:npm install -g cnpm --registry=https://registry.npm.taobao.org

alias使用:

1
2
3
4
5
6
7
8
9
10
alias cnpm="npm --registry=https://registry.npm.taobao.org \
--cache=$HOME/.npm/.cache/cnpm \
--disturl=https://npm.taobao.org/dist \
--userconfig=$HOME/.cnpmrc"

# Or alias it in .bashrc or .zshrc
$ echo '\n#alias for cnpm\nalias cnpm="npm --registry=https://registry.npm.taobao.org \
--cache=$HOME/.npm/.cache/cnpm \
--disturl=https://npm.taobao.org/dist \
--userconfig=$HOME/.cnpmrc"' >> ~/.zshrc && source ~/.zshrc

Hexo安装,-g全局安装

1
npm install hexo -g

博客创建

1
hexo init noogel

扩展插件安装

1
2
3
4
5
6
7
8
sudo npm install hexo-server --save --registry=https://registry.npm.taobao.org
sudo npm install hexo-admin --save --registry=https://registry.npm.taobao.org
sudo npm install hexo-generator-archive --save --registry=https://registry.npm.taobao.org
sudo npm install hexo-generator-feed --save --registry=https://registry.npm.taobao.org
sudo npm install hexo-generator-search --save --registry=https://registry.npm.taobao.org
sudo npm install hexo-generator-tag --save --registry=https://registry.npm.taobao.org
sudo npm install hexo-deployer-git --save --registry=https://registry.npm.taobao.org
sudo npm install hexo-generator-sitemap --save --registry=https://registry.npm.taobao.org

之后新的机器部署环境可以直接 sudo npm install --registry=https://registry.npm.taobao.org
会自动读取 package.json 文件进行安装

服务启动,两种命令

1
2
hexo serve
hexo s -g

一键发布到git

  1. 修改_config.yml配置
    1
    2
    3
    4
    5
    6
    7
    8
    ## Docs: https://hexo.io/docs/deployment.html
    deploy:
    # 类型
    type: git
    # 仓库
    repo: git@github.com:noogel/noogel.github.io.git
    # 分支
    branch: master
  2. 发布命令
    1
    hexo d -g
  3. 清除发布结果
    1
    hexo clean

组合命令:alias hexod="hexo d -g && hexo clean"

添加tags

执行hexo new page "tags",然后编辑source/tags/index.md

配置修改

博客配置修改_config.yml,主题配置修改themes/<themes>/_config.yml

hexo自动提交命令

这里设置了一个自动提交的命令,源码自动提交到 sources 分支

alias hexodp="hexo d -g && git add --all && git commit -am 'auto commit' && git push origin sources"

hexo-admin 管理文章

安装

1
npm install --save hexo-admin --registry=https://registry.npm.taobao.org

打开 http://localhost:4000/admin/

然后可以在里面配置登录账号密码,并添加到 _config.yml 文件中

1
2
3
4
5
# hexo-admin authentification
admin:
username: noogel
password_hash: $2a$10$CMR/GX.e6TuoGGOYOF7ks.R.WmSUC8RvelPPXIH5wV3S6hPLYPnx6
secret: a33x8sd83ndfus82jrfi8sj28djk438ds

预览界面如下:
hexo-admin

hexo常见问题解决办法

https://hexo.io/docs/troubleshooting.html
http://shenzekun.cn/hexo%E7%9A%84next%E4%B8%BB%E9%A2%98%E4%B8%AA%E6%80%A7%E5%8C%96%E9%85%8D%E7%BD%AE%E6%95%99%E7%A8%8B.html
https://donlex.cn/archives/55e73569.html

简单解释:采用测量不同特征值之间距离的方法进行分类的算法。
主要优点是精度高,缺点是计算和空间负责度高,适用于数值型和标称型。
已下是通过Python实现的k-近邻算法,大致思路是计算样本数据data_set中的点与待分类点的距离,按距离递增排序,然后取出前K个点,计算这些点所属标签的数量,计数最高的标签为分类结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#! /data/server/python/bin/python
# -*- coding:utf-8 -*-
"""
k-近邻算法
"""
import math
import operator
from collections import Counter


def knn(position, data_set, labels, k):
"""
k-近邻算法
:param position: 待分类点
:param data_set: 数据样本
:param labels: 标签集合
:param k: 取值
:return: 所属标签
"""
distance_list = []
for index, item in enumerate(data_set):
distance_list.append((
labels[index],
math.sqrt(reduce(operator.add, [(v - position[i]) ** 2 for i, v in enumerate(item)]))
))
distance_list = sorted(distance_list, key=lambda x: x, reverse=True)
result = Counter([val[0] for val in distance_list[:k]])
result_labels = sorted(result.items(), lambda x, y: cmp(x[1], y[1]), reverse=True)
return result_labels[0][0]


if __name__ == "__main__":
point = [0.2, 0.3]
data_set = [[1, 1.1], [1, 1], [0, 0], [0, 0.1]]
labels = ['A', 'A', 'B', 'B']
k = 3
print knn(point, data_set, labels, k)

k-d tree算法

http://www.cnblogs.com/eyeszjwang/articles/2429382.html


k近邻法 给定一个训练数据集,对新输入的实例,在训练的数据集中找到与该实例最近邻的k个实例,这k个实例的多数属于某个类,就把该输入实例分为这个类。

kd树 是一种对k维空间中的实例点进行存储以便对其进行快速检索的树形数据结构。

算法:(构造平衡kd树)

输入:k维空间数据集
$$ T={x_1,x_2,…,x_N} $$,
$$ x_i=(x_i^{(1)},x_i^{(2)},…,x_i^{(k)})^T, i=1,2,…,N; $$

输出:kd树。

生成:

从深度为0的结点开始。重复对深度为j的结点,选择x(l)为切分的坐标轴,l=j(mode k) + 1,以该结点的区域中所有实例的x(l)坐标的中位数为切分点,将该结点对应的超矩形区域切分为两个子区域。切分由通过切分点并与坐标轴x(l)垂直的超平面实现。由该结点生成深度为j+1的左、右子结点:左子节点对应坐标x(l)小于切分点的子区域,右子节点对应坐标x(l)大于切分点的子区域。

实例:

对以下给定二维数据集构造一个平衡kd树
$$ T= {(2,3)^T, (5,4)^T, (9,6)^T, (4,7)^T, (8,1)^T, (7,2)^T } $$

计算余弦值公式
$$cos\theta = \frac{x_1y_1+x_2y_2+…+x_ny_n}{\sqrt{x_1^2+x_2^2+…+x_n^2}\sqrt{y_1^2+y_2^2+…+y_n^2}}$$

样本和待分类图像

样本和待分类图像

执行结果

执行结果

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

#! /usr/bin/python
# -*- coding:utf-8 -*-
"""
@author: abc
@file: euclidean_distance.py
@date: 2016-12-09
@desc: 余弦相似度
"""
__author__ = "abc"

import cv2
import numpy as np

w_fg = 20
h_fg = 15
pic_flag = 3


def read_pic(fn):
"""
read_pic
:param fn:
:return:
"""
fnimg = cv2.imread(fn)
img = cv2.resize(fnimg, (800, 600), interpolation=cv2.INTER_AREA)
w = img.shape[1]
h = img.shape[0]
w_interval = w / w_fg
h_interval = h / h_fg

alltz = []
alltz.append([])
alltz.append([])
alltz.append([])

for now_h in xrange(0, h, h_interval):
for now_w in xrange(0, w, w_interval):
b = img[now_h:now_h + h_interval, now_w:now_w + w_interval, 0]
g = img[now_h:now_h + h_interval, now_w:now_w + w_interval, 1]
r = img[now_h:now_h + h_interval, now_w:now_w + w_interval, 2]
btz = np.mean(b)
gtz = np.mean(g)
rtz = np.mean(r)

alltz[0].append(btz)
alltz[1].append(gtz)
alltz[2].append(rtz)

return alltz


def get_cossimi(x, y):
"""
get_cossimi
:param x:
:param y:
:return:
"""
myx = np.array(x)
myy = np.array(y)
cos1 = np.sum(myx * myy)
cos21 = np.sqrt(sum(myx * myx))
cos22 = np.sqrt(sum(myy * myy))
return cos1 / float(cos21 * cos22)


if __name__ == "__main__":
# 提取特征
train_x = []
d = []

for ii in xrange(1, pic_flag + 1):
smp_x = []
b_tz = np.array([0, 0, 0])
g_tz = np.array([0, 0, 0])
r_tz = np.array([0, 0, 0])
mytz = np.zeros((3, w_fg * h_fg))
for jj in xrange(1, 3):
fn = '/home/abc/Projects/machine_learning/img/base/p' + str(ii) + '-' + str(jj) + '.jpg'
print fn
tmptz = read_pic(fn)
mytz += np.array(tmptz)
mytz /= 3
train_x.append(mytz[0].tolist() + mytz[1].tolist() + mytz[2].tolist())

for index in xrange(1, 5):
fn = '/home/abc/Projects/machine_learning/img/base/test{}.jpg'.format(index)
testtz = np.array(read_pic(fn))
simtz = testtz[0].tolist() + testtz[1].tolist() + testtz[2].tolist()
maxtz = 0
nowi = 0

for i in xrange(pic_flag):
nowsim = get_cossimi(train_x[i], simtz)
if nowsim > maxtz:
maxtz = nowsim
nowi = i

print '%s属于第%d类' % (fn, nowi + 1)

http://www.cnblogs.com/chaosimple/archive/2013/06/28/3160839.html

算法描述:将当前像素与邻接的下边和右边像素进行比较,如果相似设置为白色,否则设置为黑色。

欧氏距离算法,如果两个像素的欧氏距离小于某个常数的阀值则认定为相似。

两个n维向量a(x11, x12, ..., x1n)b(x21, x22, ..., x2n)间的欧氏距离如下公式:

$$d=\sqrt{\sum_{k=1}^n(x_{1k}-x_{2k})^2}$$

Python代码实现

1
2
3
4
5
6
7
8
9
10
11
12

def get_euclidean_distance(x, y):
"""
计算欧氏距离
:param x:
:param y:
:return:
"""
myx = np.array(x)
myy = np.array(y)
return np.sqrt(np.sum((myx - myy) * (myx - myy)))

阀值设置为16

原始图片
原始图片

描边图片
描边图片

完整代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#! /usr/bin/python
# -*- coding:utf-8 -*-
"""
@author: abc
@file: euclidean_distance.py
@date: 2016-12-09
@desc: 欧氏距离
"""
__author__ = "abc"

import cv2
import numpy as np


def get_euclidean_distance(x, y):
"""
计算欧氏距离
:param x:
:param y:
:return:
"""
myx = np.array(x)
myy = np.array(y)
return np.sqrt(np.sum((myx - myy) * (myx - myy)))


def handle_img(imgpath):
"""
handle_img
:param imgpath:
:return:
"""
myimg1 = cv2.imread(imgpath)

cv2.namedWindow('img1')
cv2.imshow('img1', myimg1)
cv2.waitKey()
cv2.destroyAllWindows()

w = myimg1.shape[1]
h = myimg1.shape[0]

sz1 = w
sz0 = h

flag = 16

myimg2 = np.zeros((sz0, sz1, 3), np.uint8)
black = np.array([0, 0, 0])
white = np.array([255, 255, 255])
centercolor = np.array([125, 125, 125])
for y in xrange(sz0 - 1):
for x in xrange(sz1 - 1):
myhere = myimg1[y, x, :]
mydown = myimg1[y + 1, x, :]
myright = myimg1[y, x + 1, :]

lmyhere = myhere
lmyright = myright
lmydown = mydown

if get_euclidean_distance(lmyhere, lmydown) > flag and get_euclidean_distance(lmyhere, lmyright) > flag:
myimg2[y, x, :] = black
elif get_euclidean_distance(lmyhere, lmydown) <= flag and get_euclidean_distance(lmyhere, lmyright) <= flag:
myimg2[y, x, :] = white
else:
myimg2[y, x, :] = centercolor

cv2.namedWindow('img2')
cv2.imshow('img2', myimg2)
cv2.waitKey()
cv2.destroyAllWindows()


if __name__ == "__main__":
imgpath = "/home/abc/Projects/machine_learning/img/test4.png"
handle_img(imgpath)

http://blog.sina.com.cn/s/blog_52510b1d01015nrg.html