PostgreSQL 图像搜索插件使用篇

简介: ## 1. 插件安装 依赖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

1. 插件安装

依赖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新增了两个数据类型

数据类型 存储长度 描述
pattern 16388 bytes 图片的哈尔小波变换结果
signature 64 bytes 模式的快速索引(GiST)

gist 索引方法(支持pattern和signature类型), 以及KNN操作符,可以用于搜索相似度

操作符 左类型 右类型 返回类型 描述
<-> pattern pattern float8 两个模式的欧几里得距离
<-> signature signature float8 两个特征的欧几里得距离

新增了几个函数
将图像的二进制转换为pattern类型,将pattern中存储的数据转换为signature类型

函数 返回类型 描述
jpeg2pattern(bytea) pattern 生产jpeg图片的模式
png2pattern(bytea) pattern 生产png图片的模式
gif2pattern(bytea) pattern 生产gif图片的模式
pattern2signature(pattern) signature 从模式中提取特征
shuffle_pattern(pattern) pattern 洗牌模式,不敏感图像的转变

2.SQL的导入和测试

2.1 建立图片表
create table image (id serial, data bytea);

2.2 导入图片到数据库
insert into image(data) select pg_read_binary_file('文件路径');

由于我的图片并没有权限上传到PostgreSQL服务端,不能当成本地文件使用。

CREATE TABLE hexdump (hex text); 创建临时表
xxd -p 4.jpg | tr -d '\n' > 4.hex; 图片文件转为16进制文件
psql --host=xx.xx.xx.xx --port=1234 --username=root --dbname=postgres -c "COPY hexdump from STDIN" <4.hex; 通过输出流写入服务端的临时表
insert into image(data) SELECT decode(hex, 'hex') FROM hexdump; 将16进制转为area

2.3 将图片转换成 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 
);

2.4 创建索引

ALTER TABLE pat ADD PRIMARY KEY (id);
CREATE INDEX pat_signature_idx ON pat USING gist (signature);

2.5 近似度查询,例如查询与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

这个smlr是越小越相似,可以试试下面这两张图片。
image.png
image.png

3.JDBC的导出和查询

3.1 注意二方库是和jre环境相关的,不然会报错。

<dependency>
           <groupId>org.postgresql</groupId>
           <artifactId>postgresql</artifactId>
           <version>42.1.4.jre7</version>
</dependency>

3.2 通过输入流写入到bytea类型的字段

Class.forName("org.postgresql.Driver");
connection= DriverManager.getConnection(url, user, password);
FileInputStream in = ImageUtil.readImage(path);
String insertSQL = "insert into image (id,data) values(?,?)";
PreparedStatement ps = connection.prepareStatement(insertSQL);
ps.setInt(1,1);
ps.setBinaryStream(2, in, in.available());
int count = ps.executeUpdate();

3.3 读取text字段

 String sql = "select * from hexdump limit 1";
 statement=connection.createStatement();
 ResultSet resultSet=statement.executeQuery(sql);
 while(resultSet.next()){
      ImageUtil.toFile(hexStringToBytes(resultSet.getString(1)),"/Users/work/1.jpg");
}

3.3.2 读取bytea类型的字段
实际上bytea类型getString 就是hexdump的类型的\x+text,故通过流读取比string合理

 String sql = "select * from image limit 1";
 statement=connection.createStatement();
 ResultSet resultSet=statement.executeQuery(sql);
 while(resultSet.next()){
     ImageUtil.readBin2Image(resultSet.getBinaryStream(2), "/Users/work/2.jpg");
}

4.附录

安装文档:https://github.com/digoal/blog/blob/master/201611/20161126_01.md?file=20161126_01.md

图片流转换工具: http://blog.csdn.net/hikvision_java_gyh/article/details/52670469
hex转byte[]: http://blog.csdn.net/u010350809/article/details/41265379

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
Kubernetes 应用服务中间件 HSF
容器服务 kubernetes(ACK)中应用优雅上下线
容器服务 kubernetes(ACK)中应用优雅上下线
8029 0
|
存储 人工智能 测试技术
图像相似度比较之 CLIP or DINOv2
图像相似度比较之 CLIP or DINOv2
|
Python
用 Python 读取照片的 Exif 信息(顺便说说本人的一些想法)
用 Python 读取照片的 Exif 信息(顺便说说本人的一些想法)
622 2
|
监控 安全 网络安全
100个网络安全中英文术语,太详细了!
【10月更文挑战第22天】
1344 0
100个网络安全中英文术语,太详细了!
|
关系型数据库 分布式数据库 数据库
沉浸式学习PostgreSQL|PolarDB 21,相似图像搜索
传统数据库不支持图像类型, 图像相似计算函数, 图像相似计算操作服, 相似排序操作符. 所以遇到类似的需求, 需要自行编写应用来解决. PG|PolarDB 通过imgsmlr插件, 可以将图像转换为向量特征值, 使用相似距离计算函数得到相似值, 使用索引加速相似度排序, 快速获得相似图片, 实现以图搜图. 也可以通过pgvector插件来存储图片向量特征值, 结合大模型服务(抠图、图像向量转换), 可以实现从图像转换、基于图像的相似向量检索全流程能力.
1294 1
|
存储 缓存 文件存储
如何保证分布式文件系统的数据一致性
分布式文件系统需要向上层应用提供透明的客户端缓存,从而缓解网络延时现象,更好地支持客户端性能水平扩展,同时也降低对文件服务器的访问压力。当考虑客户端缓存的时候,由于在客户端上引入了多个本地数据副本(Replica),就相应地需要提供客户端对数据访问的全局数据一致性。
32620 78
如何保证分布式文件系统的数据一致性
|
机器学习/深度学习 Java TensorFlow
如何在Java中实现图像识别
如何在Java中实现图像识别
|
人工智能 JSON 运维
AI大模型运维开发探索第三篇:深入浅出运维智能体
大模型出现伊始,我们就在SREWorks开源社区征集相关的实验案例。玦离同学提供了面向大数据HDFS集群的智能体案例,非常好地完成了运维诊断的目标。于是基于这一系列的实验和探索。本文详细介绍智能体在运维诊断中的应用探索。
|
XML JSON Java
深入解析 Java 中的 @RequestBody 注解:实现请求体数据的精准处理
在现代 Web 开发中,RESTful API 已经成为了构建应用程序的重要方式,而 Java 中的 `@RequestBody` 注解则是实现请求体数据处理的关键。通过该注解,我们可以将 HTTP 请求中的数据直接映射到 Java 对象,从而实现数据的精准处理和转换。本文将带您深入探索 Java 中的 `@RequestBody` 注解,揭示其原理、用法以及在实际开发中的应用场景。
Java SpringBoot集成WebSocket根据登陆权限认证
Java SpringBoot集成WebSocket根据登陆权限认证