使用 PolarDB 开源版 和 imgsmlr 存储图像特征值以及快速的进行图像相似搜索

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介: PolarDB 的云原生存算分离架构, 具备低廉的数据存储、高效扩展弹性、高速多机并行计算能力、高速数据搜索和处理; PolarDB与计算算法结合, 将实现双剑合璧, 推动业务数据的价值产出, 将数据变成生产力. 本文将介绍使用 PolarDB 开源版 和 imgsmlr 存储图像特征值以及快速的进行图像相似搜索

背景

PolarDB 的云原生存算分离架构, 具备低廉的数据存储、高效扩展弹性、高速多机并行计算能力、高速数据搜索和处理; PolarDB与计算算法结合, 将实现双剑合璧, 推动业务数据的价值产出, 将数据变成生产力.

本文将介绍使用 PolarDB 开源版 和 imgsmlr 存储图像特征值以及快速的进行图像相似搜索

测试环境为macOS+docker, PolarDB部署请参考下文:

原理

图像数字化的方法很多, 例如将图像划分为N^2的宫格, 每个宫格由几个三原色和灰度进行表述, 然后层层缩小(例如从81宫格缩小到9宫格), 把全副图像再压缩到一个格子, 形成另一个更小的N^2宫格数组.

在进行图像相似搜索时, 实际上是比对2个N^2宫格数组的向量距离.

使用GIST索引接口, 可以实现这种向量相似搜索的快速收敛, 例如以中心点为桶的数据划分, 多图层缩略图的压缩搜索算法等. (参考本文后半部分pase)

本文将介绍使用 PolarDB 开源版 和 imgsmlr 存储图像特征值以及快速的进行图像相似搜索.

1、新增2个数据类型, 一个是详图向量, 一个是签名向量(占用空间更小, 查询效率更高). 通常先使用签名向量过滤第一道, 然后再使用详图向量精筛.

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

2、新增几个图像转换函数接口

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

3、新增2个向量距离计算操作符和索引排序支持

Operator Left type Right type Return type Description
<-> pattern pattern float8 Eucledian distance between two patterns
<-> signature signature float8 Eucledian distance between two signatures

部署 imgsmlr on PolarDB

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 EXTENSION imgsmlr;  
  
-- 创建存储原始图像二进制的表  
CREATE TABLE image (id integer PRIMARY KEY, data bytea);  
  
-- 创建临时表用于导入  
CREATE TABLE tmp (data text);  
  
-- 导入图像  
\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;  
  
-- 将原始图像转换为图像特征向量和图像签名, 导入新表中  
  
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   
);  
  
-- 添加PK  
ALTER TABLE pat ADD PRIMARY KEY (id);  
  
-- 在图像签名字段创建索引  
CREATE INDEX pat_signature_idx ON pat USING gist (signature);  
  
-- 自关联, 查询图像相似性(欧氏距离)  
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;  
  
  
-- 使用索引, 快速搜索相似图像  
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+imgsmlr实现了图像特征存储, 快速根据图像特征进行相似图像搜索.

参考

https://github.com/postgrespro/imgsmlr

https://github.com/libgd/libgd

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
1月前
|
存储 SQL 安全
应用案例|开源 PolarDB-X 在互联网安全场景的应用实践
中盾集团采用PolarDB-X云原生分布式数据库开源版本,有效解决了大数据量处理、复杂查询以及历史数据维护等难题,实现了业务的高效扩展与优化。
|
11天前
|
存储 关系型数据库 分布式数据库
使用开源PolarDB和imgsmlr进行高效的图片存储和相似度搜索
使用开源PolarDB和imgsmlr进行高效的图片存储和相似度搜索
|
14天前
|
SQL JSON 关系型数据库
MySQL是一个广泛使用的开源关系型数据库管理系统,它有许多不同的版本
【10月更文挑战第3天】MySQL是一个广泛使用的开源关系型数据库管理系统,它有许多不同的版本
64 5
|
14天前
|
关系型数据库 分布式数据库 数据库
PolarDB 开源:推动数据库技术新变革
在数字化时代,数据成为核心资产,数据库的性能和可靠性至关重要。阿里云的PolarDB作为新一代云原生数据库,凭借卓越性能和创新技术脱颖而出。其开源不仅让开发者深入了解内部架构,还促进了数据库生态共建,提升了稳定性与可靠性。PolarDB采用云原生架构,支持快速弹性扩展和高并发访问,具备强大的事务处理能力及数据一致性保证,并且与多种应用无缝兼容。开源PolarDB为国内数据库产业注入新活力,打破国外垄断,推动国产数据库崛起,降低企业成本与风险。未来,PolarDB将在生态建设中持续壮大,助力企业数字化转型。
56 2
|
1月前
|
关系型数据库 分布式数据库 数据库
开源云原生数据库PolarDB PostgreSQL 15兼容版本正式发布
PolarDB进行了深度的内核优化,从而实现以更低的成本提供商业数据库的性能。
|
1月前
惊世骇俗!开源 PolarDB-X 部署安装大冒险,全程心跳与惊喜不断!
【9月更文挑战第8天】作为技术爱好者的我,近期成功完成了开源 PolarDB-X 的部署安装。尽管过程中遇到不少挑战,但通过精心准备环境、下载安装包、配置参数及启动服务等步骤,最终顺利实现部署。本文将详细介绍部署全过程及可能遇到的问题,为您的 PolarDB-X 探索之旅提供参考与启发,希望能让大家在技术海洋里畅游得更加顺利!
93 2
|
1月前
|
Cloud Native 关系型数据库 分布式数据库
PolarDB开源项目未来展望:技术趋势与社区发展方向
【9月更文挑战第5天】随着云计算技术的发展,阿里云推出的云原生分布式数据库PolarDB受到广泛关注。本文探讨PolarDB的未来展望,包括云原生与容器化集成、HTAP及实时分析能力提升、智能化运维与自动化管理等技术趋势;并通过加强全球开源社区合作、拓展行业解决方案及完善开发者生态等措施推动社区发展,目标成为全球领先的云原生数据库之一,为企业提供高效、可靠的服务。
74 5
|
1月前
|
关系型数据库 MySQL 分布式数据库
PolarDB开源社区动态:最新版本功能亮点与更新解读
【9月更文挑战第6天】随着云计算技术的发展,分布式数据库系统成为企业数据处理的核心。阿里云的云原生数据库PolarDB自开源以来备受关注,近日发布的最新版本在内核稳定性、性能、分布式CDC架构及基于时间点的恢复等方面均有显著提升,并新增了MySQL一键导入功能。本文将解读这些新特性并提供示例代码,帮助企业更好地利用PolarDB处理实时数据同步和离线分析任务,提升数据安全性。未来,PolarDB将继续创新,为企业提供更高效的数据处理服务。
125 3
|
2月前
|
Cloud Native 关系型数据库 分布式数据库
PolarDB开源项目未来展望:技术趋势与社区发展方向
随着云计算的飞速发展,作为核心组件的分布式数据库作用愈发关键。阿里云的PolarDB,一款云原生分布式数据库,自开源后备受瞩目。未来,PolarDB将深化云原生特性,强化容器化支持;发展HTAP能力,融合事务处理与实时分析;运用AI技术实现智能运维。同时,加强全球开源社区合作,拓展多行业应用场景,并构建全面的开发者生态系统,旨在成为领先的云原生数据库解决方案。
67 4
|
2月前
|
关系型数据库 MySQL 分布式数据库
PolarDB开源社区动态:最新版本功能亮点与更新解读
随着云计算的发展,阿里云的云原生分布式数据库PolarDB受到广泛关注。最新版本通过X-Paxos等先进算法优化了内核稳定性和性能,增强了分布式CDC架构以支持实时数据同步和离线分析,并引入了基于时间点的恢复功能(PITR)确保数据安全。此外,新增MySQL一键导入PolarDB-X功能简化迁移流程。这些改进将进一步提升PolarDB在企业级数据处理中的竞争力。
155 1

相关产品

  • 云原生数据库 PolarDB