如何从OpenCV image_hash模块PHashImpl获取哈希并转为字符串表示?
嘿,刚好之前用Emgu CV做过pHash的相关开发,给你详细说说这两个问题的解决思路:
1. 从PHashImpl获取哈希值
Emgu CV里的PHashImpl的Compute方法接收的IOutputArray参数,其实可以直接用Mat来承接(因为Mat实现了IOutputArray接口)。具体步骤如下:
- 首先实例化pHash算法对象:
using Emgu.CV; using Emgu.CV.ImageHash; var pHashAlgorithm = new PHashImpl(); - 准备好输入图像(如果你的图像是彩色的,pHash内部会自动转为灰度处理,但如果遇到异常,也可以手动转灰度:
CvInvoke.CvtColor(colorImg, grayImg, ColorConversion.Bgr2Gray);) - 创建一个
Mat来存储哈希结果,然后调用Compute方法:
这里的Mat hashMat = new Mat(); pHashAlgorithm.Compute(grayImg, hashMat);hashMat就是存储pHash结果的矩阵,它是一个8x8的单通道矩阵,每个元素的值是0或255(对应哈希的0和1)。
2. 将哈希转为字符串表示
有两种常见的字符串表示方式:二进制字符串或十六进制字符串,你可以根据需求选择:
方式一:转为二进制字符串
遍历hashMat的每个像素,将大于阈值(比如127)的像素视为1,否则视为0,拼接成字符串:
using System.Text; StringBuilder binaryHashBuilder = new StringBuilder(); for (int y = 0; y < hashMat.Rows; y++) { for (int x = 0; x < hashMat.Cols; x++) { // 获取当前像素的字节值 byte pixelValue = hashMat.GetData(y, x)[0]; binaryHashBuilder.Append(pixelValue > 127 ? "1" : "0"); } } string binaryHash = binaryHashBuilder.ToString();
方式二:转为十六进制字符串
先把二进制哈希转为64位无符号整数,再转成十六进制字符串,这样更简洁:
ulong hashValue = 0; for (int y = 0; y < hashMat.Rows; y++) { for (int x = 0; x < hashMat.Cols; x++) { byte pixelValue = hashMat.GetData(y, x)[0]; if (pixelValue > 127) { // 计算当前位的偏移量,将对应位设为1 hashValue |= 1UL << (y * 8 + x); } } } // 转为16位大写十六进制字符串,小写用"x16" string hexHash = hashValue.ToString("X16");
注意事项
- 确保你引用了正确的Emgu CV NuGet包,比如
Emgu.CV和Emgu.CV.ImageHash,版本要匹配 - 如果
hashMat的通道或尺寸不对,可以检查输入图像是否正确,或者手动转为灰度图后再计算
内容的提问来源于stack exchange,提问作者Diego
相关产品推荐
相关产品推荐

