c#高效比对大量图片
比较图片的方法
以前传统的比较方式是遍历图片中的每一个像素,然后进行比对。这样的比对在少量图片的比对上虽然效率低一点,但是也没有什么不好。但是在大量图片比对的时候,过长的反应时间和对服务器比较高的消耗肯定是不行的。
所以微软给我们提供了另外一种比对的方法,能够正确,高效的比对出两张图片的是否相同。这种方法的原理是:将图片保存到数据流中然后使用Convert.ToBase64String将数据流转换为字符串,那么我们只需要比对两张图片的字符串就ok了。代码如下:
public bool CheckImg(string filePath1, string filePath2)
{ MemoryStream ms1 = new MemoryStream();
Image image1 = Image.FromFile(filePath1);
image1.Save(ms1, System.Drawing.Imaging.ImageFormat.Jpeg); string img1 = Convert.ToBase64String(ms1.ToArray()); Image image2 = Image.FromFile(filePath2);
image2.Save(ms1, System.Drawing.Imaging.ImageFormat.Jpeg);
string img2 = Convert.ToBase64String(ms1.ToArray()); if (img1.Equals(img2))
{
return true;
}
else
{
return false;
}
}
比较图片
这种方法我使用控制台测试了下时间,时间大概为0.015s左右比较一张图片的时间。还是比较高效的。
大量图片的比较
比较两张图片能够满足需求,那么大量呢? 我这边也做了这种测试的。在450张图片中,选择出其中重复的图片,并展示出来。大概时间是16s左右,基本能够满足大部分的需求了。
比较方法是,先讲450张图片,全部一次性转换为string类型,存放到一个数组里面,这样就避免了每次循环都要额外的去转换,使程序的效率降低很多。
public static List<Dictionary<string, string>> chekImgss(string filePath)
{ List<Dictionary<string, string>> liststr = new List<Dictionary<string, string>>();
DirectoryInfo dir = new DirectoryInfo(filePath);
FileInfo[] files = dir.GetFiles();
foreach (FileInfo fileInfo in files)
{
Dictionary<string, string> dic = new Dictionary<string, string>();
string ex = fileInfo.Extension;
if (ex == ".jpg" || ex == ".png")
{
MemoryStream ms1 = new MemoryStream();
Image image2 = Image.FromFile(filePath + fileInfo.Name);
image2.Save(ms1, System.Drawing.Imaging.ImageFormat.Jpeg); string imgBase64 = Convert.ToBase64String(ms1.ToArray()); dic["base64"] = imgBase64;
dic["imgName"] = fileInfo.Name;
liststr.Add(dic);
}
} return liststr;
}
将图片的base64string和图片的名称存储在一个dictionary中,然后存储到list数组中。这样我们在比较的时候,只需要判断两个字符串是否相等就可以了。
/// <summary>
/// 对数组进行深拷贝
/// </summary>
/// <param name="files"></param>
/// <returns></returns>
public static List<Dictionary<string, string>> CopyList(List<Dictionary<string, string>> files)
{
MemoryStream ms = new MemoryStream();//序列化
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, files);
ms.Position = ; List<Dictionary<string, string>> array3 = (List<Dictionary<string, string>>)bf.Deserialize(ms); //反序列化
return array3;
} /// <summary>
/// 比较图片
/// </summary>
/// <param name="listDic"></param>
/// <param name="filePath"></param>
/// <returns></returns>
public static List<Dictionary<object, string>> chekImg2(List<Dictionary<string, string>> listDic,string filePath)
{
List<Dictionary<object, string>> list = new List<Dictionary<object, string>>(); DirectoryInfo dir = new DirectoryInfo(filePath);
var files = dir.GetFiles().ToList(); for (int j = ; j < listDic.Count; j++)
{
var file = listDic[j]; var fileList = CopyList(listDic);
var index = ;
var isFirst = false;
Dictionary<object, string> dic = new Dictionary<object, string>();
for (int i = ; i < fileList.Count; i++)
{
var fileInfo = fileList[i]; if (file["imgName"] == fileInfo["imgName"])
{
fileList.Remove(fileInfo);
i -= ;
continue;
}
//使用equals比普通的,string==string 高效很多倍
if (file["base64"].Equals(fileInfo["base64"]))
{
if (!isFirst)
{
dic[++index] = file["imgName"];
isFirst = true;
}
dic[++index] = fileInfo["imgName"]; fileList.Remove(fileInfo); listDic.Remove(listDic.Where(c => c.Values.Contains(fileInfo["imgName"])).FirstOrDefault());
i -= ;
}
else
{
fileList.Remove(fileInfo);
i -= ;
} } if (dic.Keys.Count > )
{
list.Add(dic);
listDic.Remove(file);
j -= ;
}
else
{
listDic.Remove(file);
j -= ;
}
}
return list;
}
这样,我们就可以将完全相同的图片都取出来存放在一个dictionary中,每一组相同的都是一个dictionary,然后存放到list数组中。需要的时候遍历出来就可以了。
总结
大量比对的时候,最好先将图片转换为string吧。如果在两个for里面实现这个转换,时间会是现在的很多倍,因为造成了许多重复的转换。然后在比对的过程中,尽量将已经比对过的图片从数组中剔除,这样比对,你会发现越来越快。
c#高效比对大量图片的更多相关文章
- (源代码分析)Android-Universal-Image-Loader (图片异步载入缓存库)的使用配置
转载请注明出处:http://blog.csdn.net/u011733020 前言: 在Android开发中,对于图片的载入能够说是个老生常谈的问题了,图片载入是一个比較坑的地方.处理不好,会有各种 ...
- [翻译]开发文档:android Bitmap的高效使用
内容概述 本文内容来自开发文档"Traning > Displaying Bitmaps Efficiently",包括大尺寸Bitmap的高效加载,图片的异步加载和数据缓存 ...
- Android高效加载大图、多图解决方案,有效避免程序OOM
高效加载大图片 我们在编写Android程序的时候经常要用到许多图片,不同图片总是会有不同的形状.不同的大小,但在大多数情况下,这些图片都会大于我们程序所需要的大小.比如说系统图片库里展示的图片大都是 ...
- Android高效加载大图、多图解决方案,有效避免程序OOM(转)
本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工,英文好的朋友也可以直接去读原文. http://developer.android.com/training/displaying ...
- 【译】快速高效学习Java编程在线资源Top 20
想要加强你的编程能力吗?想要提升你的 Java 编程技巧和效率吗? 不用担心.本文将会提供快速高效学习 Java 编程的 50 多个网站资源: 开始探索吧: 1.MKyong:许多开发者在这里可以找到 ...
- 快速高效学习Java编程在线资源Top 20(转载)
想要加强你的编程能力吗?想要提升你的 Java 编程技巧和效率吗? 不用担心.本文将会提供快速高效学习 Java 编程的 50 多个网站资源: 开始探索吧: 1.MKyong:许多开发者在这里可以找到 ...
- 如何高效、快速学习Flutter?如何避坑?(文末送服福利)
稳住,今天是周末,不过我今天要上班....啊..啊... 对于 Flutter 我没有太多的发言权,不过GSY是对 Flutter 充分理解并精深掌握的前辈了,所以转一篇他对 Flutter 的一些解 ...
- 从I/O复用谈epoll为什么高效
上一篇文章中,谈了一些网络编程的基本概念.在现实使用中,用的最多的就是I/O复用了,无非就是select,poll,epoll 很多人提到网络就说epoll,认为epoll效率是最高的.单纯的这么认为 ...
- 利用on和off方法编写高效的js代码
先说下将这个话题的起因:最近发现公司的功能代码,很多在dom对象删除以后,其声明的绑定在window上的resize事件还一直存在,导致相同的功能代码执行了几次.对于我这种轻微代码洁癖的人来说,简直是 ...
随机推荐
- centos7安装mysql
centos7安装mysql 1 查找系统是否安装了myql rpm -q mysql mysql-server1.1如果安装了.就删除 sudo yum -y remove mysql mysql- ...
- js解析或获取页面路径归纳
/** * 当填写参数href后,解析你给的参数,如果为空自动从获取浏览器的地址 *测试路径:>>>http://127.0.0.1:8020/url/index.html?id=1 ...
- delphi 程序全屏显示无标题栏,覆盖整个屏幕
delphi 程序全屏显示无标题栏,覆盖整个屏幕,这个在做工控机或屏保时有用的,所以记下 procedure TMainFrm.FormCreate(Sender: TObject); begin w ...
- Flask + Gunicorn + Nginx 部署
最近很多朋友都在问我关于 Flask 部署的问题,说实在的我很乐意看到和回答这样的问题,至少证明了越来越多人开始用 Flask 了. 之前我曾发表过一篇在 Ubuntu 上用 uwsgi + ngin ...
- virtualenvwrapper
VirtualEnv 是什么 VirtualEnv用于在一台机器上创建多个独立的python运行环境,VirtualEnvWrapper为前者提供了一些便利的命令行上的封装. 为什么要用 - 隔离项目 ...
- python metaclass 入门简介
http://cizixs.com/2015/08/30/metaclass-in-python 动态类型也是类型 python 是一种动态类型语言,换句话说每个变量可以在程序里任何地方改变它的类型. ...
- [SQL]断开并更改数据库名
EXEC sp_dboption 'my', 'Single User', 'TRUE' EXEC sp_renamedb 'my', 'mycrjtest' EXEC sp_dboption 'my ...
- linux入门学习1
推荐 实验楼网站 在线的linux环境和课程学习 这是一些摘要和笔记 UNIX/Linux历史简介 操作系统始于二十世纪 50 年代,当时的操作系统能运行批处理程序.但是不能实现交互.交互式操作系统也 ...
- Nginx作为简单代理服务器(Windows环境)
Nginx一个频繁的应用是作为代理服务器,由Nginx代理服务器接受客户请求,并将客户请求发送到应用服务器处理,接受应用服务器的响应,然后将响应发送给客户. 现在要做的一个应用场景就是当客户请求图片资 ...
- Xcode引入外界文件时选Create groups 或 Create folder references的区别
一.使用Create groups 我们在项目中可以手动添加一个groups(右键点击选择New Group),但是手动添加的groups实际上并不会存在于项目的目录中,被添加进groups中的文件仍 ...