- 浏览: 2163350 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (1878)
- [网站分类]ASP.NET (141)
- [网站分类]C# (80)
- [随笔分类]NET知识库 (80)
- [随笔分类]摘抄文字[非技术] (3)
- [随笔分类]养生保健 (4)
- [网站分类]读书区 (16)
- [随笔分类]赚钱 (7)
- [网站分类].NET新手区 (233)
- [随笔分类]网站 (75)
- [网站分类]企业信息化其他 (4)
- [网站分类]首页候选区 (34)
- [网站分类]转载区 (12)
- [网站分类]SQL Server (16)
- [网站分类]程序人生 (7)
- [网站分类]WinForm (2)
- [随笔分类]错误集 (12)
- [网站分类]JavaScript (3)
- [随笔分类]小说九鼎记 (69)
- [随笔分类]技术文章 (15)
- [网站分类]求职面试 (3)
- [网站分类]其他技术区 (6)
- [网站分类]非技术区 (10)
- [发布至博客园首页] (5)
- [网站分类]jQuery (6)
- [网站分类].NET精华区 (6)
- [网站分类]Html/Css (10)
- [随笔分类]加速及SEO (10)
- [网站分类]Google开发 (4)
- [随笔分类]旅游备注 (2)
- [网站分类]架构设计 (3)
- [网站分类]Linux (23)
- [随笔分类]重要注册 (3)
- [随笔分类]Linux+PHP (10)
- [网站分类]PHP (11)
- [网站分类]VS2010 (2)
- [网站分类]CLR (1)
- [网站分类]C++ (1)
- [网站分类]ASP.NET MVC (2)
- [网站分类]项目与团队管理 (1)
- [随笔分类]个人总结 (1)
- [随笔分类]问题集 (3)
- [网站分类]代码与软件发布 (1)
- [网站分类]Android开发 (1)
- [网站分类]MySQL (1)
- [网站分类]开源研究 (6)
- ddd (0)
- 好久没写blog了 (0)
- sqlserver (2)
最新评论
-
JamesLiuX:
博主,能组个队么,我是Freelancer新手。
Freelancer.com(原GAF – GetAFreelancer)帐户里的钱如何取出? -
yw10260609:
我认为在混淆前,最好把相关代码备份一下比较好,不然项目完成后, ...
DotFuscator 小记 -
日月葬花魂:
大哥 能 加我个QQ 交流一下嘛 ?51264722 我Q ...
web应用程序和Web网站区别 -
iaimg:
我想问下嵌入delphi写的程序总是出现窗体后面感觉有个主窗体 ...
C#自定义控件:WinForm将其它应用程序窗体嵌入自己内部 -
iaimg:
代码地址下不了啊!
C#自定义控件:WinForm将其它应用程序窗体嵌入自己内部
基于AForge.Net框架的扑克牌识别(Nazmi Altun著,野比 译)
© 版权所有 野比 2012
原文地址:点击查看
作者:Nazmi Altun
介绍
(图片上的字:方块4,方块J,黑桃2)
用机器人配上扑克牌识别系统,就可以在二十一点一类的扑克游戏中扮演荷官或是人类玩家的角色。实现这样的程序同样也是学习计算机视觉和模式识别的好途径。
本文涉及到的AForge.NET框架技术有二值化、边缘检测、仿射变换、BLOB处理和模板匹配算法等。
需要注意的是,这篇文章和文中介绍的系统是针对英美扑克设计的,可能不适用于其他种类的扑克。然而,本文描述了扑克的检测和识别的基本方法。因此,具体的识别算法需要根据扑克牌型特点而加以变化。
这里有一个视频演示。
YouTube
© 版权所有 野比 2012
扑克检测
我们需要检测图像(指采集到的视频画面,下同——野比注)上的扑克对象,以便能进行下一步的识别。为了完成检测,我们会用一些图像滤镜对视频画面进行处理。
第一步,将图像去色(即灰度化——野比注)。去色是将彩色图像转换成8bit图像的一种操作。我们需要将彩色图像转换为灰度图像以便对其进行二值化。
我们把彩色图像转为灰度图像后,对其进行二值化。二值化(阈值化)是将灰度图像转换为黑白图像的过程。本文使用Otsu的方法进行全局阈值化。
1 Bitmap temp = source.Clone() as Bitmap; // 复制原始图像 2 3 FiltersSequence seq = new FiltersSequence(); 4 seq.Add(Grayscale.CommonAlgorithms.BT709); // 添加灰度滤镜 5 seq.Add(new OtsuThreshold()); // 添加二值化滤镜 6 temp = seq.Apply(source); // 应用滤镜
(图片上的字:原始图像、灰度图像、二值(黑白)图像)
有了二值图像后,就可以用BLOB处理法检测扑克牌了。我们使用AForge.Net的BlobCounter类完成这项任务。该类利用连通区域标记算法统计并提取出图像中的独立对象(即扑克牌——野比注)。
1 // 从图像中提取宽度和高度大于150的blob 2 BlobCounter extractor = new BlobCounter(); 3 extractor.FilterBlobs = true; 4 extractor.MinWidth = extractor.MinHeight = 150; 5 extractor.MaxWidth = extractor.MaxHeight = 350; 6 extractor.ProcessImage(temp);
执行完上述代码后,BlobCounter
类会滤掉(去除)宽度和高度不在[150,350]像素之间的斑点(blob,即图块blob,图像中的独立对象。以下将改称图块——野比注)。这有助于我们区分出图像中其他物体(如果有的话)。根据测试环境的不同,我们需要改变滤镜参数。例如,假设地面和相机之间距离增大,则图像中的扑克牌会变小。此时,我们需要相应的改变最小、最大宽度和高度参数。
现在,我们可以通过调用extractor.GetObjectsInformation()
方法得到所有图块的信息(边缘点、矩形区域、中心点、面积、完整度,等等)。然而,我们只需要图块的边缘点来计算矩形区域中心点,并通过调用PointsCloud.FindQuadriteralCorners函数来计算之。
1 foreach (Blob blob in extractor.GetObjectsInformation()) 2 { 3 // 获取扑克牌的边缘点 4 List< IntPoint > edgePoints = extractor.GetBlobsEdgePoints(blob); 5 // 利用边缘点,在原始图像上找到四角 6 List< IntPoint > corners = PointsCloud.FindQuadrilateralCorners(edgePoints); 7 }
(图片上的字:在图像上绘制边缘点、寻找每张扑克的角)
找到扑克牌的四角后,我们就可以从原始图像中提取出正常的扑克牌图像了。由上图可以看出,扑克牌可以横放。扑克牌是否横放是非常容易检测的。在扑克牌放下后,因为我们知道,牌的高度是大于宽度的,所以如果提取(转化)图像的宽度大于高度,那么牌必然是横放的。随后,我们用RotateFlip函数旋转扑克牌至正常位置。
注意,为了正确识别,所有的扑克应当具有相同的尺寸。不过,鉴于相机角度不同,扑克牌的尺寸是会变化的,这样容易导致识别失败。为了防止这样的问题,我们把所有变换后的扑克牌图像都调整为200x300(像素)大小。
1 // 用于从原始图像提取扑克牌 2 QuadrilateralTransformation quadTransformer = new QuadrilateralTransformation(); 3 // 用于调整扑克牌大小 4 ResizeBilinear resizer = new ResizeBilinear(CardWidth, CardHeight); 5 6 foreach (Blob blob in extractor.GetObjectsInformation()) 7 { 8 // 获取扑克牌边缘点 9 List<IntPoint> edgePoints = extractor.GetBlobsEdgePoints(blob); 10 // 利用边缘点,在原始图像上找到四角 11 List<IntPoint> corners = PointsCloud.FindQuadrilateralCorners(edgePoints); 12 Bitmap cardImg = quadTransformer.Apply(source); // 提取扑克牌图像 13 14 if (cardImg.Width > cardImg.Height) // 如果扑克牌横放 15 cardImg.RotateFlip(RotateFlipType.Rotate90FlipNone); // 旋转之 16 cardImg = resizer.Apply(cardImg); // 归一化(重设大小)扑克牌 17 ..... 18 }
(图片上的字:使用QuadriteralTransformation类从原始图像提取出的扑克牌。该类利用每张牌的四角进行变换。)
到目前为止,我们已经找到了原始图像上每张扑克牌的四角,并从图像中提取出了扑克牌,还调整到统一的尺寸。现在,我们可以开始进行识别了。
© 版权所有 野比 2012
识别扑克牌
有好几种用于识别的技术用于识别扑克牌。本文用到的是基于牌型(如扑克牌上的形状)及模板匹配技术。扑克牌的花色和大小是分开识别的。我们可以这样枚举:
1 public enum Rank 2 { 3 NOT_RECOGNIZED = 0, 4 Ace = 1, 5 Two, 6 Three, 7 Four, 8 Five, 9 Six, 10 Seven, 11 Eight, 12 Nine, 13 Ten, 14 Jack, 15 Queen, 16 King 17 } 18 public enum Suit 19 { 20 NOT_RECOGNIZED = 0, 21 Hearts, 22 Diamonds, 23 Spades, 24 Clubs 25 }
我们还将创建如下的Card类来表示识别到的扑克牌。这个类包括了牌的大小、花色、提取到的扑克牌图像和其在原始图像上的四角点。
1 public class Card 2 { 3 // 变量 4 private Rank rank; // 大小 5 private Suit suit; // 花色 6 private Bitmap image; // 提取出的图像 7 private Point[] corners ;// 四角点 8 9 // 属性 10 public Point[] Corners 11 { 12 get { return this.corners; } 13 } 14 public Rank Rank 15 { 16 set { this.rank = value; } 17 } 18 public Suit Suit 19 { 20 set { this.suit = value; } 21 } 22 public Bitmap Image 23 { 24 get { return this.image; } 25 } 26 // 构造函数 27 public Card(Bitmap cardImg, IntPoint[] cornerIntPoints) 28 { 29 this.image = cardImg; 30 31 // 将AForge.IntPoint数组转化为System.Drawing.Point数组 32 int total = cornerIntPoints.Length; 33 corners = new Point[total]; 34 35 for(int i = 0 ; i < total ; i++) 36 { 37 this.corners[i].X = cornerIntPoints[i].X; 38 this.corners[i].Y = cornerIntPoints[i].Y; 39 } 40 } 41 }
© 版权所有 野比 2012
识别花色
标准的扑克牌花色有四种:黑桃、梅花、方块和红桃。其中方块和红桃是红色,黑桃和梅花是黑色。再有就是方块的宽度大于红桃,而梅花的宽度大于黑桃。这两个特点可以有助于我们识别花色。
识别颜色
首先,我们从识别颜色开始。正确识别出颜色,将帮助我们消除另外两种花色。我们将通过分析扑克牌图像的右上角来识别颜色。(作者强调过,本文基于他所选用的具体的扑克牌型,和印刷、牌面设计有关——野比注)
1 public Bitmap GetTopRightPart() 2 { 3 if (image == null) 4 return null; 5 Crop crop = new Crop(new Rectangle(image.Width - 37, 10, 30, 60)); 6 7 return crop.Apply(image); 8 }
(图片上的字:裁剪 扑克图像右上角、再次裁剪前次图像的底部)
裁剪了扑克牌右上角后,我们得到一张30x60像素的图像。但是该图像同时包含了花色和大小。因为我们只是分析花色,所以再次裁剪下半部分,得到30x30像素的图像。
现在,我们可以遍历图像中红色像素和黑色像素的总数。如果一个像素的红色分量比蓝色分量和绿色分量的总和还打,就可以认为该像素是红色。如果红、绿、蓝分量小于50,且红色分量不大于蓝色和绿色分量和,则认为该像素是黑色。
1 char color = 'B'; 2 // 开始,锁像素 3 BitmapData imageData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), 4 ImageLockMode.ReadOnly, bmp.PixelFormat); 5 int totalRed = 0; 6 int totalBlack = 0; 7 8 unsafe 9 { 10 // 统计红与黑 11 try 12 { 13 UnmanagedImage img = new UnmanagedImage(imageData); 14 15 int height = img.Height; 16 int width = img.Width; 17 int pixelSize = (img.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; 18 byte* p = (byte*)img.ImageData.ToPointer(); 19 20 // 逐行 21 for (int y = 0; y < height; y++) 22 { 23 // 逐像素 24 for (int x = 0; x < width; x++, p += pixelSize) 25 { 26 int r = (int)p[RGB.R]; // 红 27 int g = (int)p[RGB.G]; // 绿 28 int b = (int)p[RGB.B]; // 蓝 29 30 if (r > g + b) // 红 > 绿 + 蓝 31 totalRed++; // 认为是红色 32 33 if (r <= g + b && r < 50 && g < 50 && b < 50) // 红绿蓝均小于50 34 totalBlack++; // 认为是黑色 35 } 36 } 37 } 38 finally 39 { 40 bmp.UnlockBits(imageData); // 解锁 41 } 42 } 43 if (totalRed > totalBlack) // 红色占优 44 color = 'R'; // 设置颜色为红,否则默认黑色 45 return color;
注意.NET的Bitmap.GetPixel()
函数运行缓慢,所以我们使用了指针来遍历像素。
区分人物牌和数字牌
识别了颜色后,我们需要确定扑克牌是否是人物牌。人物牌的牌面为J、Q、K。人物牌和数字牌之间有一个很突出的特点,即数字牌牌面有很多花色符号指示其大小,而人物牌很好辨认,其牌面有人物头像。我们可以简单的设定一个大个的花色形状来分析扑克,而不是对其使用复杂的模板匹配算法。这样,识别数字牌就可以变得更快。
为了找出一张扑克牌到底是人物牌还是数字牌非常简单。人物牌上面有大的人物图,而数字牌没有。如果我们对牌进行边缘检测和图块(BLOB)处理,找到最大图块,就可以从图块的大小上判断到底是人物牌还是数字牌了。
1 private bool IsFaceCard(Bitmap bmp) 2 { 3 FiltersSequence commonSeq = new FiltersSequence(); 4 commonSeq.Add(Grayscale.CommonAlgorithms.BT709); 5 commonSeq.Add(new BradleyLocalThresholding()); 6 commonSeq.Add(new DifferenceEdgeDetector()); 7 8 Bitmap temp = this.commonSeq.Apply(bmp); 9 ExtractBiggestBlob extractor = new ExtractBiggestBlob(); 10 temp = extractor.Apply(temp); // 提取最大图块 11 12 if (temp.Width > bmp.Width / 2) // 如果宽度大于整个牌的一般宽 13 return true; // 人物牌 14 15 return false; // 数字牌 16 }
所以我们不断的对扑克牌图像进行灰度变换、局部阈值化和边缘检测。注意我们使用局部阈值化而不是全局阈值化来消除照明不良的问题(即消除光线变换时,相机的自动白平衡造成的屏幕忽明忽暗现象——野比注)。
(图片上的字(上下牌相同):原始扑克图像,灰度化,布拉德利局部阈值化,边缘检测,提取最大图块)
正如你所看到的,人物牌最大图块几乎和整张扑克牌一样大,很容易区分。
前面提到过,出于性能上的考虑,我们将使用不同的识别技术对人物牌和数字牌进行识别。对于数字牌,我们直接提取派上最大图块并识别其宽度和颜色。
1 private Suit ScanSuit(Bitmap suitBmp, char color) 2 { 3 Bitmap temp = commonSeq.Apply(suitBmp); 4 //Extract biggest blob on card 5 ExtractBiggestBlob extractor = new ExtractBiggestBlob(); 6 temp = extractor.Apply(temp); //Biggest blob is suit blob so extract it 7 Suit suit = Suit.NOT_RECOGNIZED; 8 9 //Determine type of suit according to its color and width 10 if (color == 'R') 11 suit = temp.Width >= 55 ? Suit.Diamonds : Suit.Hearts; 12 if (color == 'B') 13 suit = temp.Width <= 48 ? Suit.Spades : Suit.Clubs; 14 15 return suit; 16 }
上述测试最大误差2像素。一般来说,因为我们把扑克牌尺寸都调整到了200x300像素,所以测试的结果都会是相同的大小。
人物牌牌面上没有类似数字牌的最大花色图像,只有角上的小花色图。这就是为什么我们会裁剪扑克图像的右上角并对其应用模板匹配算法来识别花色。
在项目资源文件中有二值化模板图像。(参见项目源代码——野比注)
AForge.NET还提供了一个叫做ExhaustiveTemplateMatching的类,实现了穷尽模板匹配算法。该类对原始图进行完全扫描,用相应的模板对每个像素进行比较。尽管该算法的性能不佳,但我们只是用于一个小区域(30x60),也不必过于关心性能。
1 private Suit ScanFaceSuit(Bitmap bmp, char color) 2 { 3 Bitmap clubs, diamonds, spades, hearts; // 花色模板 4 5 // 载入模板资源 6 clubs = PlayingCardRecognition.Properties.Resources.Clubs; 7 diamonds = PlayingCardRecognition.Properties.Resources.Diamonds; 8 spades = PlayingCardRecognition.Properties.Resources.Spades; 9 hearts = PlayingCardRecognition.Properties.Resources.Hearts; 10 11 // 用0.8的相似度阈值初始化模板匹配类 12 ExhaustiveTemplateMatching templateMatching = new ExhaustiveTemplateMatching(0.8f); 13 Suit suit = Suit.NOT_RECOGNIZED; 14 15 if (color == 'R') // 如果是红色 16 { 17 if (templateMatching.ProcessImage(bmp, hearts).Length > 0) 18 suit = Suit.Hearts; //匹配红桃 19 if (templateMatching.ProcessImage(bmp, diamonds).Length > 0) 20 suit = Suit.Diamonds; // 匹配方块 21 } 22 else // 如果是黑色 23 { 24 if (templateMatching.ProcessImage(bmp,spades).Length > 0) 25 suit = Suit.Spades; // 匹配黑桃 26 if (templateMatching.ProcessImage(bmp, clubs).Length > 0) 27 suit = Suit.Clubs; // 匹配梅花 28 } 29 return suit; 30 }
(图片上的字:上面是,模板匹配?是。下面是,模板匹配?否)
当然,模板不能100%匹配样本,所以我们使用0.8(80%)的相似度阈值。
识别大小
识别大小和识别花色类似,也是单独对人物牌和数字牌进行识别。由于数字牌可以只靠计算牌面上的花色图块数量就可以识别,而不用模板匹配,所以利用简单的图像滤镜就可以完成任务。
下面所示的ScanRank函数过滤小图块(小于30像素长或宽)并计算剩余的图块数。
1 private Rank ScanRank(Bitmap cardImage) 2 { 3 Rank rank = Rank.NOT_RECOGNIZED; 4 5 int total = 0; 6 Bitmap temp = commonSeq.Apply(cardImage); // 应用滤镜 7 BlobCounter blobCounter = new BlobCounter(); 8 blobCounter.FilterBlobs = true; 9 // 过滤小图块 10 blobCounter.MinHeight = blobCounter.MinWidth = 30; 11 blobCounter.ProcessImage(temp); 12 13 total = blobCounter.GetObjectsInformation().Length; // 获取总数 14 rank = (Rank)total; // 转换成大小(枚举类型) 15 16 return rank; 17 }
(图片上的字:边缘检测,过滤宽高小于30像素的图块,剩余图块总数为10,即为扑克牌的点数)
所以,数字牌不用模板匹配算法或是OCR即可识别。但是,对人物卡,我们需要再次使用模板匹配进行识别。
1 private Rank ScanFaceRank(Bitmap bmp) 2 { 3 Bitmap j, k, q; // 人物牌人物模板 4 // 载入资源 5 j = PlayingCardRecognition.Properties.Resources.J; 6 k = PlayingCardRecognition.Properties.Resources.K; 7 q = PlayingCardRecognition.Properties.Resources.Q; 8 9 10 // 用0.75进行初始化 11 ExhaustiveTemplateMatching templateMatchin = 12 new ExhaustiveTemplateMatching(0.75f); 13 Rank rank = Rank.NOT_RECOGNIZED; 14 15 if (templateMatchin.ProcessImage(bmp, j).Length > 0) // J 16 rank = Rank.Jack; 17 if (templateMatchin.ProcessImage(bmp, k).Length > 0)// K 18 rank = Rank.King; 19 if (templateMatchin.ProcessImage(bmp, q).Length > 0)// Q 20 rank = Rank.Queen; 21 22 return rank; 23 }
由于识别难度较大,这次我们使用0.75(75%)作为相似度阈值。
已知问题
本文的实现,只能识别分开的扑克牌(没有重叠——野比注)。另一个已知问题是光线环境变化常造成识别错误。
© 版权所有 野比 2012
结论
本文用到的图像用例来自AForge.NET框架。AForge.NET为机器视觉和机器学习领域的开发者提供了大量有用的特性。对我来说,它同样非常简单。
本文还可提高,例如如何在牌还没有分放置的时候就进行识别。另一种提升是用这套系统做成AI二十一点玩家。
历史
* 7th, Oct., 2011: 初稿
许可
本文及附带的源文件代码和文件,遵循代码计划网站开源许可(CPOL)
关于作者
Nazmi Altun
Softeare Developer
Turkey
相关推荐
在本文中,我们将深入探讨如何使用AForge.NET框架来实现基于视频捕捉的图像运动识别检测程序。AForge.NET是一个强大的开源库,它为C#开发者提供了丰富的计算机视觉和人工智能工具,涉及图像处理、机器学习、神经网络...
通过AForge.NET框架,开发者可以快速搭建起基于.NET的智能系统,无论是图像处理、机器学习还是模糊逻辑应用,都能得到强大的支持。同时,由于其开源特性,用户可以根据需要修改和扩展框架,以满足特定项目的需求。...
AForge.NET框架是一个开源的.NET库,专门为计算机视觉和图像处理任务设计。它包含了大量算法和工具,使得开发者能够方便地在C#、VB.NET或其他.NET兼容的语言中实现复杂的图像处理功能,例如从摄像头捕获图像、分析...
最近在做一个服装裁床的项目,需要可视化操作根据设计图纸裁剪到哪里就点击...这样就需要用到图像图形识别技术了,在网上找了一下,发现AForge.NET在图像处理方面还不错,而且提供了大量的例子。其中就有块识别的功能
《AForge.NET框架详解》 AForge.NET框架是一款开源的C#库,专注于计算机视觉、图像处理和机器学习领域,其版本为2.2.5(仅包含库)。该框架为开发者提供了丰富的功能,便于在.NET环境中开发相关应用。本文将深入...
AForge官网的完整版资源 包括帮助手册+实例+源码 内有 给不方便帆墙的同学用. AForge.NET Framework-2.2.5-(libs only).zip AForge.NET Framework-2.2.5.exe AForge.NET Framework-2.2.5.zip
AForge.NET框架是一个开源的、基于C#的开发库,专为计算机视觉和图像处理任务而设计。这个框架版本2.2.5包含了完整的源代码,便于开发者深入理解其内部机制并进行定制化开发。同时,它提供了详细的手册和示例,帮助...
首先,AForge.Net是一个.NET框架下的计算机视觉和图像处理库,它提供了一系列的算法和组件,用于图像分析、处理以及模式识别。其包含的滤波器、边缘检测、颜色空间转换等功能,为开发者提供了构建复杂图像处理系统的...
AForge.Net框架是一个开源的.NET库,主要用于计算机视觉和图像处理任务。在视频通话的实现中,AForge.Net提供了一系列的工具和类库,帮助开发者处理视频流、图像捕获、编码解码以及网络通信等问题。这个框架由一系列...
自己做的,基本功能能实现,免费下载,希望与大家多多交流技术!
标题 "基于AForge.NET图像运动识别检测程序" 涉及到的是利用AForge.NET库在C#环境中实现的一种图像处理技术,特别是针对运动检测的应用。AForge.NET是一个开源的框架,它为开发者和研究者提供了丰富的工具和类库,...
AForge.NET是一个开源框架,专为计算机视觉、图像处理和机器学习任务而设计。这个资源合集包含了完整的AForge.NET库以及相关的示例代码,旨在帮助开发者更方便地利用该框架进行开发工作。由于Aforge.net官网的下载...
AForge.NET 是一个功能强大且功能齐全的图像处理框架,提供了多种图像处理算法和技术。下面是 AForge.NET 框架 2.1.2 版本中提供的图像处理功能概述: 一、图像处理库 AForge.Imaging AForge.Imaging 库是 AForge...
标题"AForge.NET.ZIP"指的是一个包含AForge.NET框架相关组件的压缩文件,而"AForge.NET"是一个开源的.NET框架,专注于计算机视觉和图像处理。这个框架为开发者提供了丰富的类库,支持各种图像分析、模式识别以及机器...
在C#编程环境中,当你需要对图像进行处理,如旋转、缩放或滤波时,AForge.NET是一个非常有用的开源库。AForge.NET提供了一系列的计算机视觉和图像处理功能,适用于各种项目,从简单的图像操作到复杂的算法实现。在这...
介于网络上对采用AForge进行图形验证码的识别,一堆复制黏贴,没有实例,只有BB,本人就亲测一下,并给大家提供个demo,不用谢。本人亲测,匹配率那是相当的低。可以拿来学习看看,或许你有新思路可以把它改进一下。...
AForge.NET是一个开源的.NET框架,专注于计算机视觉和图像处理领域。这个库为开发者提供了丰富的类和算法,使得在C#环境下实现复杂的图像分析、识别和处理任务变得相对简单。AForge.NET的主要特点包括图像过滤、颜色...
**AForge.NET框架详解** AForge.NET是一个开源的C#框架,专为计算机视觉和人工智能领域设计,提供了丰富的算法和组件。这个框架的核心是它的模块化设计,允许开发者轻松地集成各种功能,如图像处理、机器学习、网络...
AForge.NET Framework-2.2.5 文档 源码 例子
AForge.NET Framework是一款开源的C#库,专为开发计算机视觉、图像处理和机器学习应用程序而设计。这个框架由一系列的类库组成,提供了一系列工具和算法,使得开发者能够轻松地实现复杂的图像分析任务,例如图像识别...