使用开源PolarDB和imgsmlr进行高效的图片存储和相似度搜索

本文涉及的产品
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
简介: 使用开源PolarDB和imgsmlr进行高效的图片存储和相似度搜索

PolarDB的云原生架构提供高性价比的数据存储、可扩展的灵活性、高效的并行计算能力以及快速的数据搜索和处理能力。PolarDB通过结合计算算法,挖掘业务数据的价值,将其转化为生产力。


本文介绍如何使用开源PolarDB和imgsmlr存储图像特征值,并快速进行图像相似度搜索。


本演示的测试环境为 macOS + Docker。关于部署PolarDB的详细说明,请参考以下文章:


PolarDB的简单部署


原则

有多种方法可以对图像进行数字化,例如将其划分为正方形,并用原色和灰度表示每个正方形。然后将图像逐层逐渐缩小(例如,从 81 个正方形缩小到 9 个正方形)并压缩成一个较小的正方形,形成另一个正方形阵列。N^2N^2


在图像相似性搜索过程中,将比较两个方形数组之间的向量距离。N^2


通过使用GIST索引接口,可以实现向量相似性搜索的快速收敛。这涉及使用中心点作为存储桶的数据分区,并采用多层缩略图压缩搜索算法(请参阅本文的后面部分)。


本文介绍如何使用开源的PolarDB和imgsmlr来存储图像特征值,并高效进行图像相似度搜索。


1. 介绍两种数据类型:细节向量和特征向量。特征向量占用的空间更小,查询效率更高,通常用于初始数据过滤,而细节向量则用于更细致的过滤。

数据类型 存储长度 描述
模式 16388 字节 Haar小波变换在图像上的结果
签名 64 字节 使用 GiST 索引进行快速搜索的模式的简短表示


2、介绍几种图像转换功能接口。

功能 返回类型 描述
jpeg2pattern(bytea) 模式 将jpeg图像转换为图案
png2pattern(bytea) 模式 把png图像转换为图案
GIF2模式(bytea) 模式 将gif图像转换为图案
pattern2signature(模式) 签名 从模式创建签名
shuffle_pattern(模式) 模式 随机播放模式,降低对图像偏移的敏感度


3. 引入两种向量距离计算算子和索引排序支持。

算子 左型 正确类型 返回类型 描述
<-> 模式 模式 浮点8 两种模式之间的欧克里得距离
<-> 签名 签名 浮点8 两个特征之间的欧克里底距离


在PolarDB上部署imgsmlr

1. 安装 png 和 jpeg 的图片库依赖。

sudo yum install -y libpng-devel  
sudo yum install -y libjpeg-turbo-devel  
  
  
  
sudo vi /etc/ld.so.conf  
# add  
/usr/lib64  
  
sudo ldconfig  

2. 安装gd库,用于jpeg、png、gif等图片格式的序列化转换。

git clone --depth 1 https://github.com/libgd/libgd  
  
cd libgd/  
  
mkdir build  
  
cd build  
  
cmake -DENABLE_PNG=1 -DENABLE_JPEG=1 ..  
  
make  
  
sudo make install  
  
...  
-- Installing: /usr/local/lib64/libgd.so.3.0.16  
-- Installing: /usr/local/lib64/libgd.so.3  
...  
  
  
  
sudo vi /etc/ld.so.conf  
# add  
/usr/local/lib64  
  
sudo ldconfig  
  
  
export LD_LIBRARY_PATH=/usr/local/lib64:$LD_LIBRARY_PATH  

3. 安装 imgsmlr。

git clone --depth 1 https://github.com/postgrespro/imgsmlr  
  
  
cd imgsmlr/  
USE_PGXS=1 make  
  
USE_PGXS=1 make install  
ldd /home/postgres/tmp_basedir_polardb_pg_1100_bld/lib/imgsmlr.so  
  linux-vdso.so.1 =>  (0x00007ffc25d52000)  
  libgd.so.3 => /usr/local/lib64/libgd.so.3 (0x00007fd7a4463000)  
  libc.so.6 => /lib64/libc.so.6 (0x00007fd7a3ee5000)  
  libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007fd7a3bdd000)  
  libm.so.6 => /lib64/libm.so.6 (0x00007fd7a38db000)  
  libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fd7a36c5000)  
  /lib64/ld-linux-x86-64.so.2 (0x00007fd7a42b3000)  

4. 加载插件。

psql  
  
create extension imgsmlr ;  

场景模拟和架构设计实践

生成测试图像。

cd imgsmlr  
USE_PGXS=1 make installcheck  

图像导入、矢量化和图像相似性搜索测试。

psql
  
  
-- Create a plug-in.
CREATE EXTENSION imgsmlr;  
  
-- Create a table that stores the binary of the original image.
CREATE TABLE image (id integer PRIMARY KEY, data bytea);  
  
-- Create a temporary table for import.
CREATE TABLE tmp (data text);  
  
-- Import images.
\copy tmp from 'data/1.jpg.hex'  
INSERT INTO image VALUES (1, (SELECT decode(string_agg(data, ''), 'hex') FROM tmp));  
TRUNCATE tmp;  
\copy tmp from 'data/2.png.hex'  
INSERT INTO image VALUES (2, (SELECT decode(string_agg(data, ''), 'hex') FROM tmp));  
TRUNCATE tmp;  
\copy tmp from 'data/3.gif.hex'  
INSERT INTO image VALUES (3, (SELECT decode(string_agg(data, ''), 'hex') FROM tmp));  
TRUNCATE tmp;  
\copy tmp from 'data/4.jpg.hex'  
INSERT INTO image VALUES (4, (SELECT decode(string_agg(data, ''), 'hex') FROM tmp));  
TRUNCATE tmp;  
\copy tmp from 'data/5.png.hex'  
INSERT INTO image VALUES (5, (SELECT decode(string_agg(data, ''), 'hex') FROM tmp));  
TRUNCATE tmp;  
\copy tmp from 'data/6.gif.hex'  
INSERT INTO image VALUES (6, (SELECT decode(string_agg(data, ''), 'hex') FROM tmp));  
TRUNCATE tmp;  
\copy tmp from 'data/7.jpg.hex'  
INSERT INTO image VALUES (7, (SELECT decode(string_agg(data, ''), 'hex') FROM tmp));  
TRUNCATE tmp;  
\copy tmp from 'data/8.png.hex'  
INSERT INTO image VALUES (8, (SELECT decode(string_agg(data, ''), 'hex') FROM tmp));  
TRUNCATE tmp;  
\copy tmp from 'data/9.gif.hex'  
INSERT INTO image VALUES (9, (SELECT decode(string_agg(data, ''), 'hex') FROM tmp));  
TRUNCATE tmp;  
\copy tmp from 'data/10.jpg.hex'  
INSERT INTO image VALUES (10, (SELECT decode(string_agg(data, ''), 'hex') FROM tmp));  
TRUNCATE tmp;  
\copy tmp from 'data/11.png.hex'  
INSERT INTO image VALUES (11, (SELECT decode(string_agg(data, ''), 'hex') FROM tmp));  
TRUNCATE tmp;  
\copy tmp from 'data/12.gif.hex'  
INSERT INTO image VALUES (12, (SELECT decode(string_agg(data, ''), 'hex') FROM tmp));  
TRUNCATE tmp;  
  
-- Convert the original image into an image feature vector and an image signature, and import it into a new table.
  
CREATE TABLE pat AS (  
    SELECT  
        id,  
        shuffle_pattern(pattern)::text::pattern AS pattern,  
        pattern2signature(pattern)::text::signature AS signature  
    FROM (  
        SELECT   
            id,  
            (CASE WHEN id % 3 = 1 THEN jpeg2pattern(data)  
                  WHEN id % 3 = 2 THEN png2pattern(data)  
                  WHEN id % 3 = 0 THEN gif2pattern(data)  
                  ELSE NULL END) AS pattern   
        FROM   
            image  
    ) x   
);  
  
-- Add a PK.
ALTER TABLE pat ADD PRIMARY KEY (id);  
  
-- Create an index in the image signature field.
ALTER TABLE pat ADD PRIMARY KEY (id);  
  
-- Self-correlate and query image similarity (Euclidean distance).
SELECT p1.id, p2.id, round((p1.pattern <-> p2.pattern)::numeric, 4) FROM pat p1, pat p2 ORDER BY p1.id, p2.id;  
SELECT p1.id, p2.id, round((p1.signature <-> p2.signature)::numeric, 4) FROM pat p1, pat p2 ORDER BY p1.id, p2.id;  
  
  
-- Use the index to quickly search for similar images.
SET enable_seqscan = OFF;  
  
SELECT id FROM pat ORDER BY signature <-> (SELECT signature FROM pat WHERE id = 1) LIMIT 3;  
SELECT id FROM pat ORDER BY signature <-> (SELECT signature FROM pat WHERE id = 4) LIMIT 3;  
SELECT id FROM pat ORDER BY signature <-> (SELECT signature FROM pat WHERE id = 7) LIMIT 3;  
SELECT id FROM pat ORDER BY signature <-> (SELECT signature FROM pat WHERE id = 10) LIMIT 3;  

结果:

SELECT p1.id, p2.id, round((p1.signature <-> p2.signature)::numeric, 4) FROM pat p1, pat p2 ORDER BY p1.id, p2.id;  
 id | id | round    
----+----+--------  
  1 |  1 | 0.0000  
  1 |  2 | 0.5914  
  1 |  3 | 0.6352  
  1 |  4 | 1.1431  
  1 |  5 | 1.3843  
  1 |  6 | 1.5245  
  1 |  7 | 3.1489  
  1 |  8 | 3.4192  
  1 |  9 | 3.4571  
  1 | 10 | 4.0683  
  1 | 11 | 3.3551  
  1 | 12 | 2.4814  
  2 |  1 | 0.5914  
  2 |  2 | 0.0000  
  2 |  3 | 0.7785  
  2 |  4 | 1.1414  
  2 |  5 | 1.2839  
  2 |  6 | 1.4373  
  2 |  7 | 3.2969  
  2 |  8 | 3.5381  
  2 |  9 | 3.5788  
  2 | 10 | 4.4256  
  2 | 11 | 3.6138  
  2 | 12 | 2.7975  
  3 |  1 | 0.6352  
  3 |  2 | 0.7785  
  3 |  3 | 0.0000  
  3 |  4 | 1.0552  
  3 |  5 | 1.3885  
  3 |  6 | 1.4925  
  3 |  7 | 3.0224  
  3 |  8 | 3.2555  
  3 |  9 | 3.2907  
  3 | 10 | 4.0521  
  3 | 11 | 3.2095  
  3 | 12 | 2.4304  
  4 |  1 | 1.1431  
  4 |  2 | 1.1414  
  4 |  3 | 1.0552  
  4 |  4 | 0.0000  
  4 |  5 | 0.5904  
  4 |  6 | 0.7594  
  4 |  7 | 2.6952  
  4 |  8 | 2.9019  
  4 |  9 | 2.9407  
  4 | 10 | 3.8655  
  4 | 11 | 2.9710  
  4 | 12 | 2.1766  
  5 |  1 | 1.3843  
  5 |  2 | 1.2839  
  5 |  3 | 1.3885  
  5 |  4 | 0.5904  
  5 |  5 | 0.0000  
  5 |  6 | 0.7044  
  5 |  7 | 2.9206  
  5 |  8 | 3.1147  
  5 |  9 | 3.1550  
  5 | 10 | 4.0454  
  5 | 11 | 3.2023  
  5 | 12 | 2.3612  
  6 |  1 | 1.5245  
  6 |  2 | 1.4373  
  6 |  3 | 1.4925  
  6 |  4 | 0.7594  
  6 |  5 | 0.7044  
  6 |  6 | 0.0000  
  6 |  7 | 2.8572  
  6 |  8 | 3.0659  
  6 |  9 | 3.1054  
  6 | 10 | 3.7803  
  6 | 11 | 2.7595  
  6 | 12 | 2.0282  
  7 |  1 | 3.1489  
  7 |  2 | 3.2969  
  7 |  3 | 3.0224  
  7 |  4 | 2.6952  
  7 |  5 | 2.9206  
  7 |  6 | 2.8572  
  7 |  7 | 0.0000  
  7 |  8 | 0.6908  
  7 |  9 | 0.7082  
  7 | 10 | 4.3939  
  7 | 11 | 3.5039  
  7 | 12 | 3.2914  
  8 |  1 | 3.4192  
  8 |  2 | 3.5381  
  8 |  3 | 3.2555  
  8 |  4 | 2.9019  
  8 |  5 | 3.1147  
  8 |  6 | 3.0659  
  8 |  7 | 0.6908  
  8 |  8 | 0.0000  
  8 |  9 | 0.0481  
  8 | 10 | 4.6824  
  8 | 11 | 3.7398  
  8 | 12 | 3.5689  
  9 |  1 | 3.4571  
  9 |  2 | 3.5788  
  9 |  3 | 3.2907  
  9 |  4 | 2.9407  
  9 |  5 | 3.1550  
  9 |  6 | 3.1054  
  9 |  7 | 0.7082  
  9 |  8 | 0.0481  
  9 |  9 | 0.0000  
  9 | 10 | 4.6921  
  9 | 11 | 3.7523  
  9 | 12 | 3.5913  
 10 |  1 | 4.0683  
 10 |  2 | 4.4256  
 10 |  3 | 4.0521  
 10 |  4 | 3.8655  
 10 |  5 | 4.0454  
 10 |  6 | 3.7803  
 10 |  7 | 4.3939  
 10 |  8 | 4.6824  
 10 |  9 | 4.6921  
 10 | 10 | 0.0000  
 10 | 11 | 1.8252  
 10 | 12 | 2.0838  
 11 |  1 | 3.3551  
 11 |  2 | 3.6138  
 11 |  3 | 3.2095  
 11 |  4 | 2.9710  
 11 |  5 | 3.2023  
 11 |  6 | 2.7595  
 11 |  7 | 3.5039  
 11 |  8 | 3.7398  
 11 |  9 | 3.7523  
 11 | 10 | 1.8252  
 11 | 11 | 0.0000  
 11 | 12 | 1.2933  
 12 |  1 | 2.4814  
 12 |  2 | 2.7975  
 12 |  3 | 2.4304  
 12 |  4 | 2.1766  
 12 |  5 | 2.3612  
 12 |  6 | 2.0282  
 12 |  7 | 3.2914  
 12 |  8 | 3.5689  
 12 |  9 | 3.5913  
 12 | 10 | 2.0838  
 12 | 11 | 1.2933  
 12 | 12 | 0.0000  
(144 rows)  
  
  
postgres=# SELECT id FROM pat ORDER BY signature <-> (SELECT signature FROM pat WHERE id = 1) LIMIT 3;  
 id   
----  
  1  
  2  
  3  
(3 rows)  
  
postgres=# SELECT id FROM pat ORDER BY signature <-> (SELECT signature FROM pat WHERE id = 4) LIMIT 3;  
 id   
----  
  4  
  5  
  6  
(3 rows)  
  
postgres=# SELECT id FROM pat ORDER BY signature <-> (SELECT signature FROM pat WHERE id = 7) LIMIT 3;  
 id   
----  
  7  
  8  
  9  
(3 rows)  
  
postgres=# SELECT id FROM pat ORDER BY signature <-> (SELECT signature FROM pat WHERE id = 10) LIMIT 3;  
 id   
----  
 10  
 11  
 12  
(3 rows)  
postgres=# explain SELECT id FROM pat ORDER BY signature <-> (SELECT signature FROM pat WHERE id = 10) LIMIT 3;
                                     QUERY PLAN                                     
------------------------------------------------------------------------------------
 Limit  (cost=8.29..10.34 rows=3 width=8)
   InitPlan 1 (returns $0)
     ->  Index Scan using pat_pkey on pat pat_1  (cost=0.14..8.15 rows=1 width=64)
           Index Cond: (id = 10)
   ->  Index Scan using pat_signature_idx on pat  (cost=0.13..8.37 rows=12 width=8)
         Order By: (signature <-> $0)
(6 rows)
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
3月前
|
存储 SQL 安全
应用案例|开源 PolarDB-X 在互联网安全场景的应用实践
中盾集团采用PolarDB-X云原生分布式数据库开源版本,有效解决了大数据量处理、复杂查询以及历史数据维护等难题,实现了业务的高效扩展与优化。
|
5月前
|
关系型数据库 分布式数据库 PolarDB
PolarDB 开源部署体验评测
PolarDB 开源部署体验评测
106 3
|
27天前
|
数据库
|
2月前
|
SQL JSON 关系型数据库
MySQL是一个广泛使用的开源关系型数据库管理系统,它有许多不同的版本
【10月更文挑战第3天】MySQL是一个广泛使用的开源关系型数据库管理系统,它有许多不同的版本
154 5
|
2月前
|
关系型数据库 分布式数据库 数据库
PolarDB 开源:推动数据库技术新变革
在数字化时代,数据成为核心资产,数据库的性能和可靠性至关重要。阿里云的PolarDB作为新一代云原生数据库,凭借卓越性能和创新技术脱颖而出。其开源不仅让开发者深入了解内部架构,还促进了数据库生态共建,提升了稳定性与可靠性。PolarDB采用云原生架构,支持快速弹性扩展和高并发访问,具备强大的事务处理能力及数据一致性保证,并且与多种应用无缝兼容。开源PolarDB为国内数据库产业注入新活力,打破国外垄断,推动国产数据库崛起,降低企业成本与风险。未来,PolarDB将在生态建设中持续壮大,助力企业数字化转型。
96 2
|
3月前
|
关系型数据库 分布式数据库 数据库
开源云原生数据库PolarDB PostgreSQL 15兼容版本正式发布
PolarDB进行了深度的内核优化,从而实现以更低的成本提供商业数据库的性能。
|
3月前
惊世骇俗!开源 PolarDB-X 部署安装大冒险,全程心跳与惊喜不断!
【9月更文挑战第8天】作为技术爱好者的我,近期成功完成了开源 PolarDB-X 的部署安装。尽管过程中遇到不少挑战,但通过精心准备环境、下载安装包、配置参数及启动服务等步骤,最终顺利实现部署。本文将详细介绍部署全过程及可能遇到的问题,为您的 PolarDB-X 探索之旅提供参考与启发,希望能让大家在技术海洋里畅游得更加顺利!
159 2
|
3月前
|
Cloud Native 关系型数据库 分布式数据库
PolarDB开源项目未来展望:技术趋势与社区发展方向
【9月更文挑战第5天】随着云计算技术的发展,阿里云推出的云原生分布式数据库PolarDB受到广泛关注。本文探讨PolarDB的未来展望,包括云原生与容器化集成、HTAP及实时分析能力提升、智能化运维与自动化管理等技术趋势;并通过加强全球开源社区合作、拓展行业解决方案及完善开发者生态等措施推动社区发展,目标成为全球领先的云原生数据库之一,为企业提供高效、可靠的服务。
105 5
|
3月前
|
关系型数据库 MySQL 分布式数据库
PolarDB开源社区动态:最新版本功能亮点与更新解读
【9月更文挑战第6天】随着云计算技术的发展,分布式数据库系统成为企业数据处理的核心。阿里云的云原生数据库PolarDB自开源以来备受关注,近日发布的最新版本在内核稳定性、性能、分布式CDC架构及基于时间点的恢复等方面均有显著提升,并新增了MySQL一键导入功能。本文将解读这些新特性并提供示例代码,帮助企业更好地利用PolarDB处理实时数据同步和离线分析任务,提升数据安全性。未来,PolarDB将继续创新,为企业提供更高效的数据处理服务。
192 3
|
4月前
|
Cloud Native 关系型数据库 分布式数据库
PolarDB开源项目未来展望:技术趋势与社区发展方向
随着云计算的飞速发展,作为核心组件的分布式数据库作用愈发关键。阿里云的PolarDB,一款云原生分布式数据库,自开源后备受瞩目。未来,PolarDB将深化云原生特性,强化容器化支持;发展HTAP能力,融合事务处理与实时分析;运用AI技术实现智能运维。同时,加强全球开源社区合作,拓展多行业应用场景,并构建全面的开发者生态系统,旨在成为领先的云原生数据库解决方案。
94 4