0

0

C# 文件内容的P-Hash C#如何计算图片的感知哈希来查找相似图片

星降

星降

发布时间:2026-03-11 17:17:15

|

277人浏览过

|

来源于php中文网

原创

imagesharp实现p-hash需三步:缩放至32×32并用box重采样、按亮度公式转灰度、对8×8 dct子块取中位数生成64位哈希,推荐存为ulong并用popcount快速比对。

c# 文件内容的p-hash c#如何计算图片的感知哈希来查找相似图片

GetPerceptualHash 计算图片 P-Hash 在 C# 里不直接存在

标准 .NET 没有内置的 GetPerceptualHash 或类似方法。你得自己实现,或依赖第三方库。最常用、最稳的是 ImageSharp + 手写 P-Hash 算法逻辑——它比 System.Drawing 更安全、跨平台,且不会因 GDI+ 崩溃或抛出 OutOfMemoryException

别碰 System.Drawing.Common 在 Linux/macOS 上的非官方支持,尤其在容器或高并发场景下,System.ArgumentException: Parameter is not valid 出现频率极高。

  • ImageSharp 加载图片后缩放到 32x32(P-Hash 标准尺寸)
  • 转灰度,不是简单取 RGB 平均值,而是用亮度公式:0.299*R + 0.587*G + 0.114*B
  • 做 DCT 变换时,只取左上 8x8 块——这是 P-Hash 的核心压缩步骤,不是全图 DCT
  • 计算这 64 个 DCT 系数的中位数,再逐个比较:≥中位数为 1,否则为 0,拼成 64 位二进制字符串

ImageSharp 下实现 P-Hash 的关键三步

你不需要引入整个图像处理生态,只要 Pomelo.EntityFrameworkCore.MySql 这种“名字吓人但其实很轻”的错觉——ImageSharp 的 P-Hash 实现,核心代码不到 50 行。

常见翻车点:DCT 库选错。MathNet.NumericsDctForward 默认是行优先二维变换,但你要的是对 8×8 子块做二维 DCT,必须确保输入是 double[8,8] 而非 double[64],否则结果全乱。

  • 缩放必须用 ResizeMode.Box(盒式重采样),不是 Lanczos3——后者会引入高频噪声,导致哈希误判
  • 灰度转换必须用 KnownResamplers.Lanczos3 配合 ColorSpaceConversion.ToGrayscale,不能靠 pixel.R * 0.299 + ... 手动算——ImageSharp 的像素结构是 BGRA,顺序错了就全偏
  • 最后生成的哈希建议存为 ulong(64 位),而不是字符串或 byte[]:比对时用 bitCount = System.Numerics.BitOperations.PopCount(a ^ b),比字符串逐字符比较快 20 倍以上

哈希比对时 bitCount > 5 就算明显不相似?不一定

阈值不是拍脑袋定的。同一张图旋转 90°、加 10% JPEG 压缩、裁剪掉右下角 1/4,P-Hash 差异可能在 3~7 位之间浮动。所以 bitCount 才算高度相似,<code>4~7 得人工复核或加二级校验(比如直方图交集)。

纳米漫剧流水线
纳米漫剧流水线

360推出的国内首个工业级AI漫剧生产平台

下载

更麻烦的是缩略图场景:小图(如 100×100)强行放大到 32×32 再算 P-Hash,会产生大量伪边缘,导致哈希完全失真——这时候应该先判断原始尺寸,width 就跳过 P-Hash,改用平均哈希(<code>AHash)。

  • 批量比对 1000 张图时,别用嵌套循环暴力算 O(n²),先按哈希前 16 位分桶,只在同桶内比对
  • 数据库存哈希别用 varchar(64),用 binary(8)ulong 字段,索引效率差 3 个数量级
  • Web API 返回相似图列表时,别把 64 位哈希原样透出给前端——泄露哈希等于变相泄露图片指纹,至少做一次 XXH3.Hash64 单向混淆

为什么不用现成的 OpenCvSharp

因为重。一个 OpenCvSharp4 包带 100MB+ 本地 DLL,部署到 Alpine 容器要额外装 glibclibglib,CI 构建时间翻倍。而纯 C# 的 ImageSharp 实现,发布后单文件只有 12MB,零运行时依赖。

但如果你已经在用 OpenCV 做其他图像任务,那直接调 Cv2.PHash 最省事——注意它返回的是 Mat 类型,得用 mat.GetDouble(0, 0) 提取 64 位整数,不是直接 ToString()。

  • Cv2.PHash 默认用 32×32+8×8 流程,和标准一致,但底层用的是浮点 DCT,和整数版略有差异,跨库比对前务必统一实现
  • Windows 上 OpenCvSharpcv2.pHash Python 绑定名不同,C# 里是 Cv2.PHash,别搜错函数名
  • 如果发现哈希总一样(全是 0 或全是 1),大概率是图片加载失败,Cv2.ImRead 返回 null 但没判空——这种错误不抛异常,只会静默填零

P-Hash 看似只是“算个哈希”,但缩放方式、DCT 实现、灰度转换顺序、甚至像素内存布局,任意一环偏差都会让结果不可比。真正上线前,一定要拿同一张图的 JPEG/WEBP/PNG 三种格式各生成 10 组哈希,看它们两两之间的汉明距离是否稳定在 0~2 位。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
mysql修改数据表名
mysql修改数据表名

MySQL修改数据表:1、首先查看数据库中所有的表,代码为:‘SHOW TABLES;’;2、修改表名,代码为:‘ALTER TABLE 旧表名 RENAME [TO] 新表名;’。php中文网还提供MySQL的相关下载、相关课程等内容,供大家免费下载使用。

686

2023.06.20

MySQL创建存储过程
MySQL创建存储过程

存储程序可以分为存储过程和函数,MySQL中创建存储过程和函数使用的语句分别为CREATE PROCEDURE和CREATE FUNCTION。使用CALL语句调用存储过程智能用输出变量返回值。函数可以从语句外调用(通过引用函数名),也能返回标量值。存储过程也可以调用其他存储过程。php中文网还提供MySQL创建存储过程的相关下载、相关课程等内容,供大家免费下载使用。

513

2023.06.21

mongodb和mysql的区别
mongodb和mysql的区别

mongodb和mysql的区别:1、数据模型;2、查询语言;3、扩展性和性能;4、可靠性。本专题为大家提供mongodb和mysql的区别的相关的文章、下载、课程内容,供大家免费下载体验。

287

2023.07.18

mysql密码忘了怎么查看
mysql密码忘了怎么查看

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql密码忘了怎么办呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

519

2023.07.19

mysql创建数据库
mysql创建数据库

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql怎么创建数据库呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

267

2023.07.25

mysql默认事务隔离级别
mysql默认事务隔离级别

MySQL是一种广泛使用的关系型数据库管理系统,它支持事务处理。事务是一组数据库操作,它们作为一个逻辑单元被一起执行。为了保证事务的一致性和隔离性,MySQL提供了不同的事务隔离级别。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

392

2023.08.08

sqlserver和mysql区别
sqlserver和mysql区别

SQL Server和MySQL是两种广泛使用的关系型数据库管理系统。它们具有相似的功能和用途,但在某些方面存在一些显著的区别。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

542

2023.08.11

mysql忘记密码
mysql忘记密码

MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。那么忘记mysql密码我们该怎么解决呢?php中文网给大家带来了相关的教程以及其他关于mysql的文章,欢迎大家前来学习阅读。

666

2023.08.14

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

3

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 11.1万人学习

C 教程
C 教程

共75课时 | 5.3万人学习

C++教程
C++教程

共115课时 | 21.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号