通过select查询语句引入

1
2
3
4
5
6
from model.db.tb1 import Tb1
query = Tb1.select().where(Tb1.id > 0)
print "select query:", query.sql()[0] % tuple(query.sql()[1])
print "query result:"
for item in query.dicts().execute():
print item
select query: SELECT `t1`.`id`, `t1`.`name`, `t1`.`age`, `t1`.`create_time` FROM `tb1` AS t1 WHERE (`t1`.`id` > 0)
query result:
{'age': 12, 'create_time': datetime.datetime(2017, 2, 5, 0, 14, 6), 'id': 1, 'name': u'test'}
{'age': 20, 'create_time': datetime.datetime(2017, 2, 5, 0, 14, 55), 'id': 2, 'name': u'zhang'}

分析每一次调用

peewee_select_query
其中Tb1是我们定义的一个Model

1
2
3
4
5
6
7
8
9
10
11
12
13
class Tb1(XYZ_DB.Model):
"""
"""
id = PrimaryKeyField()
name = CharField()
age = IntegerField()
create_time = DateTimeField()

class Meta(object):

"""表配置信息
"""
db_table = "tb1"

peewee对Model类指定BaseModel元类

1
class Model(with_metaclass(BaseModel)):

未完待续

Jupyter Markdown

1
%matplotlib inline
1
2
import numpy as np
import matplotlib.pyplot as plt
1
plt.figure(figsize=(8,4))
<matplotlib.figure.Figure at 0x7f0c740ccd90>




<matplotlib.figure.Figure at 0x7f0c740ccd90>

figure创建一个绘图对象,figsize参数可以指定绘图对象的宽度和高度,单位为英寸。

1
2
3
x = np.linspace(0, 10, 1000)
y = np.sin(x)
z = np.cos(x**2)
1
2
plt.plot(x,y,label="$sin(x)$",color="red",linewidth=2)
plt.plot(x,z,"b--",label="$cos(x^2)$")
[<matplotlib.lines.Line2D at 0x7f0c73e2ea90>]

png

plot函数的调用方式很灵活,第一句将x,y数组传递给plot之后,用关键字参数指定各种属性:

  • label : 给所绘制的曲线一个名字,此名字在图示(legend)中显示。只要在字符串前后添加”$”符号,matplotlib就会使用其内嵌的latex引擎绘制的数学公式。
  • color : 指定曲线的颜色
  • linewidth : 指定曲线的宽度

第二句直接通过第三个参数”b–”指定曲线的颜色和线型。其中b表示蓝色,”–”表示线型为虚线。

1
# plt.plot?
1
2
3
4
5
plt.xlabel("Time(s)")
plt.ylabel("Volt")
plt.title("PyPlot First Example")
plt.ylim(-1.2,1.2)
plt.legend()
/usr/lib/python2.7/dist-packages/matplotlib/axes/_axes.py:519: UserWarning: No labelled objects found. Use label='...' kwarg on individual plots.
  warnings.warn("No labelled objects found. "

png

  • xlabel : 设置X轴的文字
  • ylabel : 设置Y轴的文字
  • title : 设置图表的标题
  • ylim : 设置Y轴的范围
  • legend : 显示图示

最后调用plt.show()显示出我们创建的所有绘图对象。

1
plt.show()

配置属性

1
2
3
4
x = np.arange(0, 5, 0.1)
line, = plt.plot(x, x*x) # plot返回一个列表,通过line,获取其第一个元素
# 调用Line2D对象的set_*方法设置属性值
line.set_antialiased(False)

png

1
2
3
4
# 同时绘制sin和cos两条曲线,lines是一个有两个Line2D对象的列表
lines = plt.plot(x, np.sin(x), x, np.cos(x))
# 调用setp函数同时配置多个Line2D对象的多个属性值
plt.setp(lines, color="r", linewidth=2.0)
[None, None, None, None]

png

调用Line2D对象line的set_antialiased方法,关闭对象的反锯齿效果。或者通过调用plt.setp函数配置多个Line2D对象的颜色和线宽属性。

1
2
3
line.get_linewidth()
plt.getp(lines[0], "color") # 返回color属性
plt.getp(lines[1]) # 输出全部属性
    agg_filter = None
    alpha = None
    animated = False
    antialiased or aa = True
    axes = Axes(0.125,0.125;0.775x0.775)
    children = []
    clip_box = TransformedBbox(Bbox([[0.0, 0.0], [1.0, 1.0]]), Co...
    clip_on = True
    clip_path = None
    color or c = r
    contains = None
    dash_capstyle = butt
    dash_joinstyle = round
    data = (array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6, ...
    drawstyle = default
    figure = Figure(432x288)
    fillstyle = full
    gid = None
    label = _line1
    linestyle or ls = -
    linewidth or lw = 2.0
    marker = None
    markeredgecolor or mec = r
    markeredgewidth or mew = 0.5
    markerfacecolor or mfc = r
    markerfacecoloralt or mfcalt = none
    markersize or ms = 6.0
    markevery = None
    path = Path(array([[ 0.        ,  1.        ],        [ 0...
    path_effects = []
    picker = None
    pickradius = 5
    rasterized = None
    sketch_params = None
    snap = None
    solid_capstyle = projecting
    solid_joinstyle = round
    transform = CompositeGenericTransform(TransformWrapper(Blended...
    transformed_clip_path_and_affine = (None, None)
    url = None
    visible = True
    xdata = [ 0.   0.1  0.2  0.3  0.4  0.5]...
    xydata = [[ 0.          1.        ]  [ 0.1         0.995004...
    ydata = [ 1.          0.99500417  0.98006658  0.95533649  ...
    zorder = 2

绘制多轴图

1
2
3
for idx, color in enumerate("rgbyck"):
plt.subplot(320+idx+1, axisbg=color)
plt.show()

png

subplot将整个绘图区域等分为numRows行 * numCols列个子区域,然后按照从左到右,从上到下的顺序对每个子区域进行编号,左上的子区域的编号为1。如果numRows,numCols和plotNum这三个数都小于10的话,可以把它们缩写为一个整数,例如subplot(323)和subplot(3,2,3)是相同的。subplot在plotNum指定的区域中创建一个轴对象。如果新创建的轴和之前创建的轴重叠的话,之前的轴将被删除。

1
2
3
4
plt.subplot(221) # 第一行的左图
plt.subplot(222) # 第一行的右图
plt.subplot(212) # 第二整行
plt.show()

png


绘制散列图

1
2
3
4
fig = plt.figure()
ax = fig.add_subplot(111)
t = ax.scatter(np.random.rand(20), np.random.rand(20))
fig.show()
/usr/lib/python2.7/dist-packages/matplotlib/figure.py:397: UserWarning: matplotlib is currently using a non-GUI backend, so cannot show the figure
  "matplotlib is currently using a non-GUI backend, "

png

http://old.sebug.net/paper/books/scipydoc/index.html

  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

(二叉)堆是一个数组,它可以被看成一个近似完全二叉树。二叉堆可以分为两种形式:最大堆和最小堆。在最大堆中所有节点的值都大于等于子节点。在最小堆中所有节点的值都小于等于子节点。
其中max_heapify是一个维护最大堆的方法,时间复杂度为O(lgn),max_heapify是一个建立最大堆的方法。

我们从列表的一半位置开始,如果节点比子节点小则交换位置,如果交换后的子节点比其子节点小继续交换。一直遍历到根节点,这样就建立好了一个最大堆。

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
def parrent_node(index):
"""父节点"""
return abs(index / 2)


def left_node(index):
"""左子节点"""
return 2 * index


def right_node(index):
"""右子节点"""
return 2 * index + 1


def max_heapify(array, index):
"""维护最大堆"""
left = left_node(index)
right = right_node(index)
if left <= len(array) and array[left - 1] > array[index - 1]:
largest = left
else:
largest = index
if right <= len(array) and array[right - 1] > array[largest - 1]:
largest = right
if largest != index:
array[index - 1], array[largest - 1] = array[largest - 1], array[index - 1]
max_heapify(array, largest)


def build_max_heap(array):
"""建最大堆"""
for index in range(len(array) / 2, 0, -1):
max_heapify(array, index)

执行

1
2
3
4
array = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7]
print array
build_max_heap(array)
print array

结果
[4, 1, 3, 2, 16, 9, 10, 14, 8, 7]
[16, 14, 10, 8, 7, 9, 3, 2, 4, 1]

基本操作

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

Kaggle Titanic问题

[技能get点]

  • Pandas基本操作
  • [√] 随机森林算法 ——> 数学原理、算法思想
  • [√] kaggle竞赛的一个项目完成参与流程
  • [√] 特征功能 ——> 特征提取

随机森林算法

kaggle竞赛参与流程

特征提取

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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#! /usr/bin/python
# -*- coding:utf-8 -*-
"""
@author: abc
@file: xyzforest.py
@date: 2017-01-06
"""
__author__ = "abc"

import numpy as np
import pandas as pd
import csv
from sklearn.ensemble import RandomForestClassifier


class Titanic(object):
"""
Titanic
"""
def __init__(self):
"""
__init__
"""
self.train_path = "/home/abc/Projects/kaggle/Titanic/train.csv"
self.test_path = "/home/abc/Projects/kaggle/Titanic/test.csv"

def load_data(self, path):
"""
加载数据
:param path:
:return:
"""
return pd.read_csv(path, header=0)

def wash_train_data(self, train_data):
"""
清洗训练数据
:param train_data:
:return:
"""
# PassengerId,Survived,Pclass,Name,Sex,Age,SibSp,Parch,Ticket,Fare,Cabin,Embarked
# 性别数值化
train_data.Sex = train_data.Sex.map({'female': 0, 'male': 1}).astype(int)

# Embarked 数值化, 补充众数
if len(train_data.Embarked[train_data.Embarked.isnull()]) > 0:
train_data.Embarked[train_data.Embarked.isnull()] = train_data.Embarked.dropna().mode().values
ports_dict = {name: index for index, name in enumerate(set(train_data.Embarked))}
train_data.Embarked = train_data.Embarked.map(ports_dict).astype(int)

# 年龄补充平均数
if len(train_data.Age[train_data.Age.isnull()]) > 0:
train_data.Age[train_data.Age.isnull()] = train_data.Age.dropna().median()

# 删除多余字段
train_data = train_data.drop(self.drop_label(), axis=1)

self.data_concat(train_data)

return train_data.values

def wash_test_data(self, test_data):
"""
清洗测试数据
:param test_data:
:return:
"""
# PassengerId,Pclass,Name,Sex,Age,SibSp,Parch,Ticket,Fare,Cabin,Embarked
test_data.Sex = test_data.Sex.map({'female': 0, 'male': 1}).astype(int)

if len(test_data.Embarked[test_data.Embarked.isnull()]) > 0:
test_data.Embarked[test_data.Embarked.isnull()] = test_data.Embarked.dropna().mode().values
ports_dict = {name: index for index, name in enumerate(np.unique(test_data.Embarked))}
test_data.Embarked = test_data.Embarked.map(ports_dict).astype(int)

if len(test_data.Age[test_data.Age.isnull()]) > 0:
test_data.Age[test_data.Age.isnull()] = test_data.Age.dropna().median()

if len(test_data.Fare[test_data.Fare.isnull()]) > 0:
median_fare = np.zeros(3)
for f in range(0, 3): # loop 0 to 2
median_fare[f] = test_data[test_data.Pclass == f + 1]['Fare'].dropna().median()
for f in range(0, 3): # loop 0 to 2
test_data.loc[(test_data.Fare.isnull()) & (test_data.Pclass == f + 1), 'Fare'] = median_fare[f]

test_data = test_data.drop(self.drop_label(), axis=1)

self.data_concat(test_data)

return test_data.values

def drop_label(self):
"""
drop_label
:return:
"""
return ['Name', 'Ticket', 'PassengerId']

def data_concat(self, raw_data):
"""
data_concat
:param raw_data:
:return:
"""
# 根据年龄优化
raw_data.loc[raw_data.Age < 18, "Age"] = 0
raw_data.loc[raw_data.Age >= 18, "Age"][raw_data.Age < 45] = 1
raw_data.loc[raw_data.Age >= 45, "Age"] = 2
# 根据父母孩子数量优化
raw_data.loc[raw_data.Parch > 0, "Parch"] = 1
raw_data.loc[raw_data.Cabin.isnull(), "Cabin"] = 1
raw_data.loc[raw_data.Cabin.notnull(), "Cabin"] = 0

def rediction_model(self, train_data, label_data, test_data):
"""
预测模型
:param train_data:
:param test_data:
:return:
"""
forest = RandomForestClassifier(n_estimators=2000)
forest = forest.fit(train_data, label_data)
return forest.predict(test_data).astype(int)

def save_result(self, path, head, data):
"""
save_result
:param path:
:param head:
:param data:
:return:
"""
with open(path, "wb") as wbf:
csv_obj = csv.writer(wbf)
csv_obj.writerow(head)
for item in data:
csv_obj.writerow(list(item))

def run(self):
"""
运行
:return:
"""
# 加载数据
train_data = self.load_data(self.train_path)
test_data = self.load_data(self.test_path)
passenger_id = test_data.PassengerId.values
# 清洗数据
train_data = self.wash_train_data(train_data)
test_data = self.wash_test_data(test_data)
train_data, label_data = train_data[0::, 1::], [val for val in train_data[0::, 0]]
head = ["PassengerId", "Survived"]
data = zip(passenger_id, self.rediction_model(train_data, label_data, test_data))
self.save_result("xyzforest.csv", head, data)

if __name__ == "__main__":
tt = Titanic()
print tt.run()

参考

pandas documentation

【原】十分钟搞定pandas

机器学习系列(3)_逻辑回归应用之Kaggle泰坦尼克之灾

Kaggle系列——Titanic 80%+精确度纪录

简单解释:采用测量不同特征值之间距离的方法进行分类的算法。
主要优点是精度高,缺点是计算和空间负责度高,适用于数值型和标称型。
已下是通过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