背景
图片搜索是继文字搜索后又一个比较常用的搜索引擎。
市面上常见的搜索引擎有谷歌、百度、搜狗等图片搜索引擎。
http://image.baidu.com/
http://images.google.com.hk
例如在搜索引擎提供的接口中上层了一张雪人的图片,搜出来一堆和雪人近似的图片。

图片搜索是怎么做到的呢?
万能的PostgreSQL绝不落下这么好玩的东东,通过PG万能的API,可以扩展它的图片搜索功能。
如果你对PostgreSQL扩展开发感兴趣,可以参考我写的文章
《找对业务G点, 体验酸爽 - PostgreSQL内核扩展指南》
https://yq.aliyun.com/articles/55981
PostgreSQL 图像搜索插件背景技术
PostgreSQL的图像搜索插件使用了非常主流的Haar wavelet技术对图像进行变换后存储,可以参考WIKI和一篇关于HW的文献。
https://en.wikipedia.org/wiki/Haar_wavelet
http://www.cs.toronto.edu/~kyros/courses/320/Lectures.2013s/lecture.2013s.10.pdf
截取几页,注意烧脑。




PostgreSQL 图像搜索插件介绍
依赖gd.h
# yum install -y gd-devel
下载安装imgsmlr
$ git clone https://github.com/postgrespro/imgsmlr
$ cd imgsmlr
$ export PGHOME=/home/digoal/pgsql9.5
$ export PATH=$PGHOME/bin:$PATH:.
$ make USE_PGXS=1
$ make USE_PGXS=1 install
安装插件
$ psql
psql (9.5.3)
Type "help" for help.
postgres=# create extension imgsmlr;
CREATE EXTENSION
imgsmlr新增了两个数据类型
Datatype |
Storage length |
Description |
pattern |
16388 bytes |
Result of Haar wavelet transform on the image |
signature |
64 bytes |
Short representation of pattern for fast search using GiST indexes |
gist 索引方法(支持pattern和signature类型), 以及KNN操作符,可以用于搜索相似度
Operator |
Left type |
Right type |
Return type |
Description |
<-> |
pattern |
pattern |
float8 |
Eucledian distance between two patterns |
<-> |
signature |
signature |
float8 |
Eucledian distance between two signatures |
新增了几个函数
将图像的二进制转换为pattern类型,将pattern中存储的数据转换为signature类型
Function |
Return type |
Description |
jpeg2pattern(bytea) |
pattern |
Convert jpeg image into pattern |
png2pattern(bytea) |
pattern |
Convert png image into pattern |
gif2pattern(bytea) |
pattern |
Convert gif image into pattern |
pattern2signature(pattern) |
signature |
Create signature from pattern |
shuffle_pattern(pattern) |
pattern |
Shuffle pattern for less sensitivity to image shift |
PostgreSQL 图像搜索插件测试
导入一些图片,例如(越多越好)

建立图片表
create table image (id serial, data bytea);
导入图片到数据库
insert into image(data) select pg_read_binary_file('文件路径');
将图片转换成 patten 和 signature
CREATE TABLE pat AS (
SELECT
id,
shuffle_pattern(pattern) AS pattern,
pattern2signature(pattern) AS signature
FROM (
SELECT
id,
jpeg2pattern(data) AS pattern
FROM
image
) x
);
创建索引
ALTER TABLE pat ADD PRIMARY KEY (id);
CREATE INDEX pat_signature_idx ON pat USING gist (signature);
近似度查询,例如查询与id = :id的图像相似的图像,按相似度排行,取出前10条
SELECT
id,
smlr
FROM
(
SELECT
id,
pattern <-> (SELECT pattern FROM pat WHERE id = :id) AS smlr
FROM pat
WHERE id <> :id
ORDER BY
signature <-> (SELECT signature FROM pat WHERE id = :id)
LIMIT 100
) x
ORDER BY x.smlr ASC
LIMIT 10
这里可以用到KNN索引,快速按相似度排行输出结果。
小结
- PostgreSQL是一个非常强大的数据库,功能高度可定制。而且不需要动到PostgreSQL的内核。 安全可靠。
- 使用图像搜索的技术就是PostgreSQL功能扩展的例子,速度杠杠的,还记得我以前给出的关于地理位置近邻查询的性能指标吗。
《PostgreSQL 百亿地理位置数据 近邻查询毫秒级反馈》
https://yq.aliyun.com/articles/2999
- 如果你对PostgreSQL扩展开发感兴趣,可以参考我写的文章
《找对业务G点, 体验酸爽 - PostgreSQL内核扩展指南》
https://yq.aliyun.com/articles/55981
祝大家玩得开心,欢迎随时来 阿里云促膝长谈 业务需求 ,恭候光临。
阿里云的小伙伴们加油,努力做 最贴地气的云数据库 。