请先参考我写到java这章

原理讲解

参考Neal Krawetz博士的这篇文章, 实现这种功能的关键技术叫做"感知哈希算法"(Perceptual Hash Algorithm), 意思是为图片生成一个指纹(字符串格式), 两张图片的指纹越相似, 说明两张图片就越相似. 但关键是如何根据图片计算出"指纹"呢? 下面用最简单的步骤来说明一下原理:

第一步 缩小图片尺寸

将图片缩小到8x8的尺寸, 总共64个像素. 这一步的作用是去除各种图片尺寸和图片比例的差异, 只保留结构、明暗等基本信息.

第二步 转为灰度图片

将缩小后的图片, 转为64级灰度图片.

第三步 计算灰度平均值

计算图片中所有像素的灰度平均值

第四步 比较像素的灰度

将每个像素的灰度与平均值进行比较, 如果大于或等于平均值记为1, 小于平均值记为0.

第五步 计算哈希值

将上一步的比较结果, 组合在一起, 就构成了一个64位的二进制整数, 这就是这张图片的指纹.

第六步 对比图片指纹

得到图片的指纹后, 就可以对比不同的图片的指纹, 计算出64位中有多少位是不一样的. 如果不相同的数据位数不超过5, 就说明两张图片很相似, 如果大于10, 说明它们是两张不同的图片.

代码实现 (C#版本)

下面我用C#代码根据上一节所阐述的步骤实现一下.

using System;
using System.IO;
using System.Drawing; namespace SimilarPhoto
{
class SimilarPhoto
{
Image SourceImg; public SimilarPhoto(string filePath)
{
SourceImg = Image.FromFile(filePath);
} public SimilarPhoto(Stream stream)
{
SourceImg = Image.FromStream(stream);
} public String GetHash()
{
Image image = ReduceSize();
Byte[] grayValues = ReduceColor(image);
Byte average = CalcAverage(grayValues);
String reslut = ComputeBits(grayValues, average);
return reslut;
} // Step 1 : Reduce size to 8*8
private Image ReduceSize(int width = , int height = )
{
Image image = SourceImg.GetThumbnailImage(width, height, () => { return false; }, IntPtr.Zero);
return image;
} // Step 2 : Reduce Color
private Byte[] ReduceColor(Image image)
{
Bitmap bitMap = new Bitmap(image);
Byte[] grayValues = new Byte[image.Width * image.Height]; for(int x = ; x<image.Width; x++)
for (int y = ; y < image.Height; y++)
{
Color color = bitMap.GetPixel(x, y);
byte grayValue = (byte)((color.R * + color.G * + color.B * ) / );
grayValues[x * image.Width + y] = grayValue;
}
return grayValues;
} // Step 3 : Average the colors
private Byte CalcAverage(byte[] values)
{
int sum = ;
for (int i = ; i < values.Length; i++)
sum += (int)values[i];
return Convert.ToByte(sum / values.Length);
} // Step 4 : Compute the bits
private String ComputeBits(byte[] values, byte averageValue)
{
char[] result = new char[values.Length];
for (int i = ; i < values.Length; i++)
{
if (values[i] < averageValue)
result[i] = '';
else
result[i] = '';
}
return new String(result);
} // Compare hash
public static Int32 CalcSimilarDegree(string a, string b)
{
if (a.Length != b.Length)
throw new ArgumentException();
int count = ;
for (int i = ; i < a.Length; i++)
{
if (a[i] != b[i])
count++;
}
return count;
}
}
}

转:http://www.cnblogs.com/technology/archive/2012/07/12/2588022.html

找出相似的图片--C#的更多相关文章

  1. 【CTF MISC】隐写术wireshark找出图片-“强网杯”网络安全挑战赛writeup

    这场CTF中有一道题是分析pcap包的.. 13.大黑阔: 从给的pcap包里把图片提取出来,是一张中国地图. 题目提示是黑阔在聊天,从数据里可以找出几段话. 思路:主要考察wireshark的过滤规 ...

  2. 机器学习进阶-项目实战-信用卡数字识别 1.cv2.findContour(找出轮廓) 2.cv2.boudingRect(轮廓外接矩阵位置) 3.cv2.threshold(图片二值化操作) 4.cv2.MORPH_TOPHAT(礼帽运算突出线条) 5.cv2.MORPH_CLOSE(闭运算图片内部膨胀) 6. cv2.resize(改变图像大小) 7.cv2.putText(在图片上放上文本)

    7. cv2.putText(img, text, loc, text_font, font_scale, color, linestick) # 参数说明:img表示输入图片,text表示需要填写的 ...

  3. Linux运维之批量下载指定网站的100个图片文件,并找出大于200KB的文件

    题目为:  有一百个图片文件,它们的地址都是http://down.fengge.com/img/1.pnghttp://down.fengge.com/img/2.png…一直到http://dow ...

  4. c#封装DBHelper类 c# 图片加水印 (摘)C#生成随机数的三种方法 使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象 c# 制作正方形图片 JavaScript 事件循环及异步原理(完全指北)

    c#封装DBHelper类   public enum EffentNextType { /// <summary> /// 对其他语句无任何影响 /// </summary> ...

  5. Facebook存储技术方案:找出“暖性BLOB”数据

    Facebook公司已经在其近线存储体系当中彻底弃用RAID与复制机制,转而采用分布式擦除编码以隔离其所谓的“暖性BLOB”. 暖性?BLOB?这都是些什么东西?大家别急,马上为您讲解: BLOB—— ...

  6. 使用 Visual Studio 分析器找出应用程序瓶颈(转)

    使用 Visual Studio 分析器找出应用程序瓶颈 Hari Pulapaka and Boris Vidolov 本文讨论: 以性能瓶颈为目标 应用程序代码分析 比较分析数据 性能报告 本文使 ...

  7. 使用 Visual Studio 分析器找出应用程序瓶颈

    VS的性能分析工具 性能分析工具的选择 打开一个“性能分析”的会话:Debug->Start Diagnotic Tools Without Debugging(或按Alt+F2),VS2013 ...

  8. 机器学习进阶-图像特征sift-SIFT特征点 1.cv2.xfeatures2d.SIFT_create(实例化sift) 2. sift.detect(找出关键点) 3.cv2.drawKeypoints(画出关键点) 4.sift.compute(根据关键点计算sift向量)

    1. sift = cv2.xfeatures2d.SIFT_create() 实例化 参数说明:sift为实例化的sift函数 2. kp = sift.detect(gray, None)  找出 ...

  9. 机器学习进阶-图像金字塔与轮廓检测-模板匹配(单目标匹配和多目标匹配)1.cv2.matchTemplate(进行模板匹配) 2.cv2.minMaxLoc(找出矩阵最大值和最小值的位置(x,y)) 3.cv2.rectangle(在图像上画矩形)

    1. cv2.matchTemplate(src, template, method)  # 用于进行模板匹配 参数说明: src目标图像, template模板,method使用什么指标做模板的匹配 ...

随机推荐

  1. node+koa2 向页面传值方式

    1. router.post('/form',async(ctx,next)=>{ const form = ctx.request.body; console.log('用户名:'+form. ...

  2. angular.js--------demo1

    <!doctype html><html ng-app> <head> <meta charset="utf-8"> </he ...

  3. BZOJ3861 : Tree

    把集合看成左边的点,图中的点看成右边的点,若集合$i$不包含$j$,则连边$i->j$,得到一个二分图,等价于求这个二分图的完备匹配个数. 设$f[i][j]$表示考虑了前$i$个集合,匹配了$ ...

  4. 20172302 《Java软件结构与数据结构》实验一:线性结构实验报告

    课程:<Java软件结构与数据结构> 班级: 1723 姓名: 侯泽洋 学号:20172302 实验教师:王志强老师 实验日期:2018年9月26日 必修/选修: 必修 实验内容 (1)链 ...

  5. Python和Mysql、Nginx

    链接: python入门和基础: Python 中文学习大本营 你是如何自学 Python 的? 简明 Python 教程 给伸手党的福利:Python 新手入门引导 <Python爬虫学习系列 ...

  6. MySql数据库事务正常提交,回滚失败

    问题:在初次练习Mysql数据库事务时,事务正常提交,但是在遇到异常应当回滚时,回滚失败. 代码如下: //2.更新操作. public void update(Connection conn, St ...

  7. ZwQuerySystemInformation枚举内核模块及简单应用

    简单说,即调用第11号功能,枚举一下内核中已加载的模块.部分代码如下://功能号为11,先获取所需的缓冲区大小ZwQuerySystemInformation(SystemModuleInformat ...

  8. 从UEditor内容中获取指定节点值(转)

    今天吐槽一下百度的富文本编辑器UEditor,这种富文本编辑器极大地方便我们上传文件,开发人员无需编写任何上传代码,只需配置几个路径即可.但高度集成的东西有时也显得笨重,灵活度不高.比如:编辑器中我既 ...

  9. Kafka:ZK+Kafka+Spark Streaming集群环境搭建(二十九):推送avro格式数据到topic,并使用spark structured streaming接收topic解析avro数据

    推送avro格式数据到topic 源代码:https://github.com/Neuw84/structured-streaming-avro-demo/blob/master/src/main/j ...

  10. 熬之滴水成石:最想深入了解的内容--windows内核机制(6)

    58 进程和线程(3) 说完进程再说说线程,线程相比于进程其实有更多可说的内容.首先实现线程调用的数据结构是个栈,该栈记录了调用方法的信息这里面也包括了函数调用及返回的地址.线程肯定是属于某个进程,其 ...