图像相似性比较实践

2008年TinEye上线了图片搜索,开始是注册制,后来逐步放开。2011年, Google也上线了相似图片搜索,通过用户上传的图片,可以搜索相似的图片。
参考文档中提供了一些介绍图像搜索的一些文章, 尤其是阮一峰2011年和2013年两篇普及性的文章,可以帮助你了解图像相似搜索的原理。

图像相似性搜索应用广泛、除了使用搜索引擎搜索类似图片外,像淘宝可以让顾客直接拍照搜索类似的商品信息、应用在商品购物上。也可以应用物体识别比如拍图识花等领域。目前我在调研图片鉴权的方案,通过一张图片和图片库中的图片进行比对,来确定这张图片是否侵权,或者退一步讲,图片库中是否包含和这张图片类似。 这个需求和目前深度学习应用中的图像识别还不一样, 图像识别是需要将图像中的物体识别出来, 猫啊狗啊什么的,而我所要做的就是一个查找相似图片的东西。

Neal Krawetz博士看到了一些关于TinEye原理的询问, 虽然他并不知道TinEye是怎么实现的,但是根据搜索结果,他判断是基于感知哈希算法(Perceptual hash algorithm)的变种,他于2011年5月写了一篇文章,介绍相关的技术。

阅读全文

区块链中的共识算法

先占个坑, 慢慢整理。

本文是正在整理,当你看不到这句话的时候,意味着整理完成了。

最近101blockchains 列举了常用的区块链的公式算法,并且详细介绍了这些算法的思想、好处和坏处,当然其它文章中还介绍了一些公式算法。正如文章中所说,没有一个共识算法是完美的,采用哪种算法是一个tradeoff的过程。

本文整理了区块链的公式算法,包括算法思想介绍、好处和不好的地方。

阅读全文

给 iTerm 设置代理

如果你用SS FQ的话, Shadow-Socks设置的系统代理是socks5代理,在iTerm中访问一些https还是不能用, 比如用go get下载一些依赖的库。一个办法就是使用Privoxy将socks5代理转换成http代理。

Privoxy

MacOS安装Privoxy比较简单。

1
2
3
4
5
6
7
8
9
10
11
12
13
-> brew install privoxy
==> Downloading https://homebrew.bintray.com/bottles/privoxy-3.0.26.sierra.bottl
######################################################################## 100.0%
==> Pouring privoxy-3.0.26.sierra.bottle.1.tar.gz
==> Caveats
To have launchd start privoxy now and restart at login:
brew services start privoxy
Or, if you don't want/need a background service you can just run:
privoxy /usr/local/etc/privoxy/config
==> Summary
? /usr/local/Cellar/privoxy/3.0.26: 52 files, 1.8MB

你可以使用brew services start privoxy启动privoxy服务,或者手工临时启动privoxy /usr/local/etc/privoxy/config也可以。

如果中间需要brew link privoxy按照提示创建文件夹,比如/usr/local/sbin,设置对应的权限即可。

启动服务前先编辑vim /usr/local/etc/privoxy/config

1
2
3
4
5
6
listen-address 127.0.0.1:8087
forward-socks5 / 127.0.0.1:1080 .
forward 192.168.*.*/ .
forward 10.*.*.*/ .
forward 127.*.*.*/

8087是本机要监听的http代理地址, 1080是SS的socks5代理地址,还设置本地地址。

配置http代理

通过下面的环境变量就可以设置http代理。

1
2
export http_proxy=http://127.0.0.1:8087
export https_proxy=$http_proxy

你可以把它们写在 ~/.zshrc 或者 ~/.bash_profile中,随时切换。

1
2
alias goproxy='export http_proxy=http://127.0.0.1:8087 https_proxy=http://127.0.0.1:8087'
alias disproxy='unset http_proxy https_proxy'

参考

  1. https://segmentfault.com/a/1190000008848001
  2. https://honglu.me/2015/11/06/给iTerm终端设置代理/

C和Go相互调用

C可以调用Go,并且Go可以调用C, 如果更进一步呢, C-->Go-->C 或者 Go-->C-->Go的调用如何实现?

本文通过两个简单的例子帮助你了解这两种复杂的调用关系。本文不涉及两者之间的复杂的数据转换,官方文章C? Go? Cgo!wiki/cgocmd/cgo有一些介绍。

阅读全文

跳出Go module的泥潭

说明: go module增在快速的成长中,最近每个版本中(1.11 ~ 1.13)都有很大的变动。 建议你阅读官方的wiki了解go module最新的知识: go/wiki/Modules

最新扩展阅读(go 1.13):Go module 再回顾

Go 1.11 前天已经正式发布了,这个版本包含了两个最重要的feature就是 moduleweb assembly。虽然也有一些简单的教程介绍了go module的特性,但是基本上都是hello world的例子,在实践的过程中, 很多人都在“拼命的挣扎”,包括我自己, 从一些qq群、github的issue, twitter上都可以看到大家茫然或者抱怨的语句。

虽然有三个帮助文件go help modgo help modulesgo help module-get可以了解一些go module的用法,但是感觉Go开发组对module这一特性还是没有很好的做一个全面的介绍,很多情况还得靠大家看源代码或者去猜,比如module下载的文件夹、版本格式的完整声明,module的最佳实践等,并且当前Go 1.11的实现中还有一些bug,给大家在使用的过程中带来了很大的困难。

我也在摸索中前行, 记录了摸索过程中的一些总结,希望能给还在挣扎中的Gopher一些帮助。

Introduction to Go Modules 是一篇很好的go module 入门介绍, 如果你仔细阅读了它,应该就不需要看本文了。

阅读全文

局部敏感哈希介绍

传统的Hash当源数据有些许的变化的时候生成的哈希值差异也非常的大, 比如:

1
2
3
4
5
6
7
8
9
10
func main() {
s1 := []byte("你好世界")
s2 := []byte("你好,世界")
hash1 := md5.Sum(s1)
hash2 := md5.Sum(s2)
fmt.Println(hex.EncodeToString(hash1[:]))
fmt.Println(hex.EncodeToString(hash2[:]))
}

s1的哈希值是65396ee4aad0b4f17aacd1c6112ee364、s2的哈希值是27444ee2d245c3e8e11ed8b9b035c43b,源数据仅仅是一个逗号的区别,但是哈希值完全不一样。这是我们使用Hash的常见的场景,输出的哈希值经常被称为消息摘要(message digest)或摘要(digest)。

局部敏感哈希(Locality-sensitive hashing, 简称LSH)则不同, LSH则希望相似的源数据计算出来的哈希值越相近越好。
LSH经常用在判重、文章摘要、聚类、相似搜索、近邻查找等场景, 用来减少高维度的数据的维度,相近的数据放在同一个桶中。 比如大规模异常滥用检测:基于局部敏感哈希算法——来自Uber Engineering的实践

阅读全文

创建最小的Go docker 镜像

虽然曾有一些文章介绍了如何创建一个最小的Go Docker镜像,我也曾写过一篇文章,但是随着Go的新的版本的发布, 以及docker本身的进化,有些技巧已经发生了变化, 本文介绍了最新的创建超小的Go镜像的方法。

阅读全文