谷歌百度以图搜图 "感知哈希算法" C#简单实现

本文涉及的产品
图像搜索,7款服务类型 1个月
简介: /// /// 感知哈希算法 /// public class ImageComparer { /// /// 获取图片的Hashcode /// /// /// public static string GetImageHashCode(string imageName) { int width = 8; int height = 8; // 第一步 // 将图片缩小到8x8的尺寸,总共64个像素。

 

	/// <summary>
	/// 感知哈希算法
	/// </summary>
	public class ImageComparer
	{		
		/// <summary>
		/// 获取图片的Hashcode
		/// </summary>
		/// <param name="imageName"></param>
		/// <returns></returns>
		public static string GetImageHashCode(string imageName)
		{
			int width = 8;
			int height = 8;

			//	第一步
			//	将图片缩小到8x8的尺寸,总共64个像素。这一步的作用是去除图片的细节,
			//	只保留结构、明暗等基本信息,摒弃不同尺寸、比例带来的图片差异。
			Bitmap bmp = new Bitmap(Thumb(imageName));
			int[] pixels = new int[width * height];

			//	第二步
			//	将缩小后的图片,转为64级灰度。也就是说,所有像素点总共只有64种颜色。
			for (int i = 0; i < width; i++)
			{
				for (int j = 0; j < height; j++)
				{
					Color color = bmp.GetPixel(i, j);
					pixels[i * height + j] = RGBToGray(color.ToArgb());
				}
			}

			//	第三步
			//	计算所有64个像素的灰度平均值。
			int avgPixel = Average(pixels);

			//	第四步
			//	将每个像素的灰度,与平均值进行比较。大于或等于平均值,记为1;小于平均值,记为0。
			int[] comps = new int[width * height];
			for (int i = 0; i < comps.Length; i++)
			{
				if (pixels[i] >= avgPixel)
				{
					comps[i] = 1;
				}
				else
				{
					comps[i] = 0;
				}
			}

			//	第五步
			//	将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图片的指纹。组合的次序并不重要,只要保证所有图片都采用同样次序就行了。
			StringBuilder hashCode = new StringBuilder();
			for (int i = 0; i < comps.Length; i += 4)
			{
				int result = comps[i] * (int)Math.Pow(2, 3) + comps[i + 1] * (int)Math.Pow(2, 2) + comps[i + 2] * (int)Math.Pow(2, 1) + comps[i + 2];
				hashCode.Append(BinaryToHex(result));
			}
			bmp.Dispose();
			return hashCode.ToString();
		}

		/// <summary>
		/// 计算"汉明距离"(Hamming distance)。
		/// 如果不相同的数据位不超过5,就说明两张图片很相似;如果大于10,就说明这是两张不同的图片。
		/// </summary>
		/// <param name="sourceHashCode"></param>
		/// <param name="hashCode"></param>
		/// <returns></returns>
		public static int HammingDistance(String sourceHashCode, String hashCode)
		{
			int difference = 0;
			int len = sourceHashCode.Length;

			for (int i = 0; i < len; i++)
			{
				if (sourceHashCode[i] != hashCode[i])
				{
					difference++;
				}
			}
			return difference;
		}

		/// <summary>
		/// 缩放图片
		/// </summary>
		/// <param name="imageName"></param>
		/// <returns></returns>
		private static Image Thumb(string imageName)
		{
			return Image.FromFile(imageName).GetThumbnailImage(8, 8, () => { return false; }, IntPtr.Zero);
		}

		/// <summary>
		/// 转为64级灰度
		/// </summary>
		/// <param name="pixels"></param>
		/// <returns></returns>
		private static int RGBToGray(int pixels)
		{
			int _red = (pixels >> 16) & 0xFF;
			int _green = (pixels >> 8) & 0xFF;
			int _blue = (pixels) & 0xFF;
			return (int)(0.3 * _red + 0.59 * _green + 0.11 * _blue);
		}

		/// <summary>
		/// 计算平均值
		/// </summary>
		/// <param name="pixels"></param>
		/// <returns></returns>
		private static int Average(int[] pixels)
		{
			float m = 0;
			for (int i = 0; i < pixels.Length; ++i)
			{
				m += pixels[i];
			}
			m = m / pixels.Length;
			return (int)m;
		}

		private static char BinaryToHex(int binary)
		{
			char ch = ' ';
			switch (binary)
			{
				case 0:
					ch = '0';
					break;
				case 1:
					ch = '1';
					break;
				case 2:
					ch = '2';
					break;
				case 3:
					ch = '3';
					break;
				case 4:
					ch = '4';
					break;
				case 5:
					ch = '5';
					break;
				case 6:
					ch = '6';
					break;
				case 7:
					ch = '7';
					break;
				case 8:
					ch = '8';
					break;
				case 9:
					ch = '9';
					break;
				case 10:
					ch = 'a';
					break;
				case 11:
					ch = 'b';
					break;
				case 12:
					ch = 'c';
					break;
				case 13:
					ch = 'd';
					break;
				case 14:
					ch = 'e';
					break;
				case 15:
					ch = 'f';
					break;
				default:
					ch = ' ';
					break;
			}
			return ch;
		}
	}

  

 

目录
相关文章
|
2月前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
54 3
|
15天前
|
算法 安全
散列值使用相同的哈希算法
当使用相同的哈希算法对相同的数据进行散列时,所产生的散列值(也称为哈希值或摘要)总是相同的。这是因为哈希算法是一种确定性的函数,它对于给定的输入将始终产生相同的输出。 例如,如果你用SHA-256算法对字符串"hello world"进行哈希处理,无论何时何地,只要输入是完全一样的字符串,你都会得到相同的160位(40个十六进制字符)的SHA-256散列值。 但是,需要注意的是,即使是输入数据的微小变化也会导致产生的散列值完全不同。此外,不同的哈希算法(如MD5、SHA-1、SHA-256等)会对相同的数据产生不同的散列值。 哈希算法的一个关键特性是它们的“雪崩效应”,即输入中的一点小小
27 4
|
1月前
|
算法 测试技术 量子技术
时隔5年,谷歌再创量子霸权里程碑!RCS算法让电路体积增加一倍
谷歌在量子计算领域取得重大突破,通过随机电路采样(RCS)算法,成功将量子电路体积翻倍,实现了量子霸权的里程碑。这一成果发表于《自然》杂志,展示了量子动力学与噪声交互作用下的相变现象,推动了量子计算在密码学、材料科学等领域的应用潜力。尽管如此,量子计算仍面临错误率高、可扩展性差等挑战。
40 3
|
1月前
|
算法 测试技术 量子技术
时隔5年,谷歌再创量子霸权里程碑!RCS算法让电路体积增加一倍
谷歌在量子计算领域取得新突破,其研究人员在《自然》杂志上发表论文《随机电路采样中的相变》,介绍了一种名为随机电路采样(RCS)的算法。该算法通过优化量子关联速度、防止经典简化和利用相变现象,使量子电路体积在相同保真度下增加一倍,为量子计算的发展树立了新的里程碑。实验结果显示,RCS算法在67个量子比特和32个周期的条件下,实现了1.5×10^-3的保真度。这一成果不仅提升了量子计算的效率,也为解决噪声问题提供了新思路。
80 3
|
2月前
|
存储 算法 C#
C#哈希查找算法
C#哈希查找算法
|
2月前
|
算法 安全 Go
Python与Go语言中的哈希算法实现及对比分析
Python与Go语言中的哈希算法实现及对比分析
46 0
|
2月前
|
存储 算法 C++
【算法】哈希映射(C/C++)
【算法】哈希映射(C/C++)
|
4月前
|
算法 安全 JavaScript
安全哈希算法:SHA算法
安全哈希算法:SHA算法
86 1
安全哈希算法:SHA算法
|
4月前
|
JSON 算法 API
京东以图搜图功能API接口调用算法源码python
京东图搜接口是一款强大工具,通过上传图片即可搜索京东平台上的商品。适合电商平台、比价应用及需商品识别服务的场景。使用前需了解接口功能并注册开发者账号获取Key和Secret;准备好图片的Base64编码和AppKey;生成安全签名后,利用HTTP客户端发送POST请求至接口URL;最后解析JSON响应数据以获取商品信息。
|
4月前
|
算法
基于多路径路由的全局感知网络流量分配优化算法matlab仿真
本文提出一种全局感知网络流量分配优化算法,针对现代网络中多路径路由的需求,旨在均衡分配流量、减轻拥塞并提升吞吐量。算法基于网络模型G(N, M),包含N节点与M连接,并考虑K种不同优先级的流量。通过迭代调整每种流量在各路径上的分配比例,依据带宽利用率um=Σ(xm,k * dk) / cm来优化网络性能,确保高优先级流量的有效传输同时最大化利用网络资源。算法设定收敛条件以避免陷入局部最优解。