返回首页

{A}
{S0的}介绍
此应用程序可能没有任何实用价值,但它是从学习的角度来看。我想了解计算机视觉。计算机视觉是现代计算最令人兴奋的领域之一。这也是一个困难的领域。什么是人类大脑的简单和明显的是非常困难的一台计算机。与当前的IT水平的进步,还有很多事是不可能的。
此应用程序使用低级别的C,因为我想学习如何引擎盖下工作的实施。如果你想开始与计算机视觉应用程序,你应该利用现有的库(如OpenCV的),并从那里开始。在CodeProject上,这里你可以找到几个教程。摄像头的图像采集源代码是从,瓦迪姆Gorbatenko(AviCap CodeProject上)。
摄像头获得一个图像,在一个时间(帧)。流帧,使运动的印象。下一张图片解释了什么是一个摄像头范围内的应用。
{S}
下面的图像的数字设置为640x480像素的摄像头在我的2.8GHz的PC上测量毫秒的延迟。毫秒显示了一些有趣的结果。例如,最慢的一步是摄像头的图像采集。 100毫秒意味着,你将得到每秒10帧。这是穷人。摄像头通常是缓慢的。你可以让他们更快质量的帐户。较低的分辨率,使相机的更快,但图像质量可能会变得毫无用处。另一个令人惊讶的是,为什么这么慢(12毫秒)转换为黑色和白色。另一方面,预计要慢是OCR和求解。但这些都是出奇的快吗??只有7毫秒。我将详细解释每个步骤,并显示如何可以改善的东西。源代码的函数调用上述过程是DoSomeImageProcessing()。如何转换为黑白作品阈值
每台计算机视觉应用开始从颜色(或灰度)转换为黑白图像。在未来,将有可能是一些颜色识别算法,将有一些色彩的运用,但今天的计算机视觉应用都是基于单色(daltonists)。
转换颜色为单色的最简单的方法是"全球阈值??假设你有一个红色强度200 200,绿色,蓝色200像素。由于强度从0到255,这个像素是在光线非常密集。黑人和白人之间的阈值是中间:256/2 = 128。我们的像素平均强度(200 200 200)/ 3 = 200,这是阈值128以上,所以它会被转换为白色。但这个简单的全局阈值是不是在现实世界中的应用非常有用。接下来的图像显示。
{S2的}
对于一个好的转换为单色,我们将使用自适应阈值。自适应阈值不使用固定的阈值128。相反,它计算的阈值分别为每个像素。它读取11x11周围的像素,并总结其强度。然后平均金额的平均值成为该像素的阈值。像素的计算公式是阈值= sum/121,其中121 = 11x11,总和是总结的周围强度。如果中央的像素强度大于计算的平均阈值,它会变成白色,另有黑色。我们对未来的形象,阈值的像素标记为红色。同样的计算是必需的所有其他像素。这是这是为什么这么慢的原因。该方案需要宽*高* 121像素读取。
{S3的}整体形象
这可以优化使用"整体形象?整体形象是一个整数数组的int [图像宽度*图像高度]。这个概念很简单和强大。下面的图片就是一个例子。假设我们有1设置为简单起见,所有强度值图像12x12像素(在现实世界中的应用,样品图像不会那么简单)。整体形象是从顶部,并从左侧的所有像素的像素的总和。
{四至}
下的图像是一个例子,如何可能是有用的整体形象。我们的目标是计算的灰色矩形中的所有像素的总和。
计算公式为:总和=粑答:在我们的例子:110-44-40 16 = 42(尝试手动计数)。
,而不是阅读所有的像素从灰色的矩形(可以是远远高于这个例子更大),我们只需要四个内存读取。这是一个显着优化。但即使有这种优化,转换为黑色和白色仍是最重的步骤之一。
{五}如何检测旋转
一个摄像头是不是一台扫描仪。一个摄像头画面是永远不会完全一致。我们必须想到的形象被扭曲和旋转。要检测的旋转角度,我们将使用一个事实,即数独画面总是有一定的水平和垂直线。我们将检测最传神(最强)线附近的图片中心。最传神的行不会受噪音影响。在黑白图像检测线的算法被称为Hough变换。
它是如何工作的:你必须记得行学校的数学公式:Y =(X * COS(θ)RHO)/ SIN(θ)。
{六}
theta是该行的角度和rho是从中心坐标(0,0)线的距离。
重要的是要注意的是,每行可以用只有两个变量表示:THETA和Rho。
程序遍历通​​过在单色图像的每个像素。它跳过白色像素。黑色像素时,它会尝试画出所有可能的线穿过的像素(虚拟线路)。它与分辨率1度。这意味着,每个像素将通过它的虚拟线路180。为什么不是360?因为角度180-360角度0-180副本。
是一个虚拟的线阵列称为累加器。累加器是一个名为THETA和rho尺寸的二维数组。相同的THETA和rho线公式。每一个虚拟的线代表一个累加器中的值。顺便说一下,这就是为什么这种方法被称为转型 - 从[X,Y]至[THETA,RHO]数组转换线。每一个虚拟的生产线将增加一个累加器值,提高的可能性,这个虚拟的线是实线。这是一种投票。实线将有过半数票。
毕竟像素和他们的180虚拟线路已经投了赞成票,我们必须找到在累加器的最大价值。 (顺便说一下,为什么取名"蓄能??因为它积累票)。赢家是最具表现力(最强)线。其尺寸THETA和rho可以使用与上述线公式来绘制它。
下的图像是一个简单的例子。在左边,我们有3个像素的线条。你的眼睛可以看到,从左上角到右下角的对角线,但是这不是电脑,明显。
{七}
如何在线检测工作:看上面的图片。 Hough变换算法跳过白色像素。每一个黑色的像素绘制四个绿色的虚拟线(实际上,它是180线,但我们需要为简单起见,这里只有四)通过该像素。行第一个像素票,B,C和D的第二个像素票é,乙,G H.的第三个像素会表决,B线是为所有常见的,我行,B,K,L。注三个黑色像素。它会获得3票。所有其他的生产线将累加器中只有一票。因此,虚拟的B线必须是赢家 - 实线。
下的图像是一个比较复杂的例子。左边是独网格线的形象。右边是累加器阵列后的Hough变换算法的执行。累加器中的明亮区域是指有多少票。黑暗意味着没有机会找到一条线。只集中在最亮的点。每一行(标有字母盟)有一个累加器中的亮点。你可以看到,所有的线条稍微旋转(约6度)。 A线是比线K.旋转,由于图像是不是唯一的旋转,但也扭曲。另外,如果你看的更深一些,你可以看到怎么行A和B比B和C是接近的,你可以看到,无论在左边和右边的图像。
{S8的}
Hough变换,重要的是要明白,如果你想了解一般的视觉模式识别。虚拟的线,可以通过投票产生的实线的概念可以扩展到任何其他的几何形状。如圆或矩形。该生产线是最简单的几何形状,因此它应该是最简单的理解。
如果你需要找到圆(S),您将需要与尺寸的立体累加器:X,Y,R,其中x,y坐标,r为半径的虚拟各界。再次,最高(最轻)票在这样一个累加器是真正的圆圈上的图像。
Hough变换执行限制区和原始图像的角度,可以优化。我们不需要从源图像中的所有行。为了检测旋转角度,我们只需要一个图像中心附近的单行。从该行的角度来看,我们假设所有其他线旋转。如何检测网格线
为了从电网中提取的数字,我们需要精确定位其中一个数独电网的开始和结束的地方。这部分是对人类大脑的最简单的一部分,但出乎意料的是,这部分是最困难计算机。为什么呢?为什么不使用Hough变换检测线,在上一节中所述吗?答案是因为有一个很大的噪音。在大多数情况下,独格在一本杂志或报纸印刷是永不孤独。有其他电网和它周围的线条,使噪音。例如,看看这个:
{S9的}
这是很难告诉电脑线是独线和周围的噪音。哪里是一格的结束和另一个开始。
为了解决这个问题,我们将无法检测到黑线。相反,我们将检测围绕独电网的白色区域。在接下来的图像,你可以看到如何。绿线1与从独电网的黑色像素,从未间断,而2号线中断了至少10倍。这意味着1号线电网外有更多的可能性。通过计算多少次中断任何水平和垂直线与黑色像素,我们可以得出结论,下一张图片上的绿线是可能的Sudoku电网的界限。简单 - 只需数从白到黑像素转换线下是多少。你不需要运行线,在1个像素的分辨率。这是不够好,跳过每3个像素的速度。
{S10的}
后,我们发现的界限,我们将这些界限内运行Hough变换精确检测的网格线。到目前为止,我们没在意倾斜的图像和其他图像缺陷。大约只有粗图像旋转。这一步将改善。运行Hough变换的网格的面积有限,我们将得到所有的网格线的精确位置。这将有助于找到在细胞中的数字。
TODO:在此步骤可以改善噪声更敏感。我的下一个版本的计划是要结合"倾斜哈尔样的功能?上面的方法吗?检测电网的角落。我希望这能提高产品质量。该问题可能是,哈尔样的特点是良好的固地区,但我们用线处理。行占据较小的区域,让光明与黑暗的矩形之间的差异是没有那么大。
我不知道什么其他选择,检测10X10的网格呢??/ P>多的OCR工程
后,我们找到了网格内的斑点,我们需要认识到他们。我们有一个相对容易的任务。只有从1到9的数字。而不是整个字母表。理论
每个识别算法有以下步骤:确定功能火车(学习步骤)分类(运行确认)
确定的特点,是一种应用程序设计的一部分。功能,例如:1号是又高又瘦。这是什么使得它从别人的不同。 8号有两个圆圈,一个以上的其他等。
功能定义可以是一个非常艰苦和直观的工作,取决于对事物认识。例如,你会用什么功能来识别某人的脸?没有任何的脸。具体的面孔。开发区的功能
在此应用中,我们将使用区域密度功能。下一步(即已经提前完成),是培养应用程序,通过提供培训图片数字1-9。你可以看到这些照片。\ res文件夹中。图片的大小,以5x5的像素,规范化,并存储在静态数组OCRDigit :: m_zon [10] [5] [5],它看起来像:
{的S11}
5x5的大小被称为分区。上述阵列被称为密度的特点。
那些5x5的照片密度值0到1024范围内的规范手段。没有正常化,区域将是无法比拟的。
在运行时会发生什么情况:当一个blob分离从一个摄像头的形象,它调整到5x5的像素。然后,这25个像素相比,一个接一个,与9个训练有素的密度特征阵列。我们的目标是要找到在像素强度的最小差异。少的差异意味着更多的相似性。
{的S12}
这种方法是不敏感的BLOB规模的,因为我们总是使用5x5的区域。这是敏感的旋转,但我们已经知道什么是旋转,并可以调整它。问题是,它是敏感的位置偏移,也不起作用的负面形象(黑底白字)与真正旋转图像(如倒挂)。宽/高比例的功能
1号是一个特例。 4和7,因为它是类似的,上面的方法是不可靠的。 1号的具体特点是:如果BLOB的宽度是BLOB的高度低于40%,它必须是1号。没有其他的数字是如此之薄。除了上述25个区的功能,这是第26届的功能,我们正在检查。

的分类步骤,我们使用k-近邻,K = 1,这意味着我们发现只有一个最亲密的邻居。待办事项
OCR质量的下一个版本,可以通过引入其他功能改善。例如,数字5,6和9非常相似,如果使用具有区域特色。为了区分它们,我们可以使用配置文件的功能。轮廓特征的像素数(距离)之间的边界框的BLOB和blob的边缘。
在接下来的图像,你可以看到正确的配置文件是为5和6相似,但9个不同的。 5日和9左型材是相似的,但有6种不同的。
{S14系列}
有其他可能的改进。专业的OCR引擎使用许多不同的特点。其中一些是非常奇特。固定的OCR结果
后的OCR进行,结果在逻辑上是根据数独规则纠正。相同的数字不能被发现在同一行,列,或3x3的块。如果这个规则被打破,OCR的结果必须是错误的,需要改正。我们将替换错误的结果与未来可能的结果。例如,在图。 12以上,结果是5,因为差异= 5210,这是最小的。未来可能的结果是6。因为它有未来的diff = 5508。因此,我们将取代与5个结果。决定哪两个冲突的数字需要更正,我们采取的第一和第二的差异之间的差异最小的一个。源代码是SudSolver ::皿()。数独解算器是如何工作的
有更多不同的方法来解决数独谜题。在这里,我们将使用三个简单的方法一起工作,互相帮助:裸体单打,隐藏单,蛮力。方法1。蛮力
也称为回溯。这是最常用的方法,程序员,总是给人一种解决方案,无论是多么困难。但蛮力可能会非常缓慢,根据需要递归迭代的数量。你永远不能事先知道需要多少迭代。蛮力是"摸着石头过河??方法。它试图在所有空单元格1-9可能的值的所有组合,直到所有的细胞都充满一致的价值观。可能有多个解决方案,但我们很高兴只找到第一个。
第一步是准备候选人的表??每个空单元格的可能值。下面的图片说明了什么是候选人。它们是蓝色的。由数独的规则,第一个单元格可以包含1只,4或8。例如,3不能有,因为它已经存在以下两个单元。

蛮力将尝试结合所有的蓝色小数字,直到它找到一个解决方案。看到的第一个单元格。算法将启动值1,然后第五细胞,它会采取3号等。如果任何选定的号码是不与其他值一致,将尝试用一个不同的算法。例如,从左边第六届细胞也作为候选人,3号,但因为这是不符合第五单元,该算法将尝试用未来的候选人,这是4等
蛮力可以是很慢的解决方案,如果需要多次迭代。例如,未来的形象是一个"近最坏的情况下,蛮力算法的难题吗??(来源:维基)。因为它试图与所有可能的值,正确的是最后的候选人,候选人的顺序。幸运的是,解决这个问题 - 你不应该从左上角单元格。任何其他的初始细胞会得到更快的解决方案。我们将使用这一招,加快蛮力方法。
{S16号}
有其他可能的优化,使蛮力,快如递归序列与最小的候选人数与候选人的最大数量排序从细胞的细胞。但是,我们不使用这样的优化,因为它们是唯一的局部优化。他们都有一个"最坏的情况吗??如果他们不是足够快的实时应用。相反,我们将使用时间盒装,三试,随机序列的优化。关键是要中止回溯,如果时间太长。然后重新排序随机递归序列从头再试一次。方法2。赤裸裸的单一候选人
下面的图片说明了这种方法。如果一个细胞都有一个单一的候选人,我们是100%肯定这是一个细胞的有效价值。我们设置该值后,下一步就是重建的候选人名单。候选人名单逐渐减少,直到所有的候选人选拔。这是一个明显的电脑和简单的方法。并不明显,对人类,虽然。人类玩家无法继续在他们头上的候选人名单。
方法3。隐藏的单
下面的图片说明了这种方法。看数字7。如果你是一个独的球员,你可能会立即看到,7号必须存在。
{S18纯}
即使这种细胞有四名候选人:4,7,8,9(见图15),诀窍是,我们寻找一个候选人的3x3块,列,或行内唯一的实例。这种方法或许可以解决整个难题,但一起很好地工作与方法2。方法2运行时的单一候选人,方法3可以提供帮助。 综合所有方法
摄像头的求解,速度是非常重要的。蛮力是没有足够快为我们的应用程序。因此,我们将使用所有这三种方法的组合。方法2和3都非常快,但也只能解决简单的拼图。因为我们从嘈杂的摄像头输入,我们往往很难甚至无法解决的难题(因为不可靠的OCR)。我们必须承担的难题往往是很难解决的。即使是原来的难题是一个简单的。
如何读下图:在左侧,有快的方法2和3。只有当他们是不成功的,我们会跳向右侧,这是缓慢的蛮力。方法2和3,即使是不成功的解决,他们做了伟大的工作,至少解决一些细胞减少蛮力的工作。

方法2和3只有解决不了,该方案下降的蛮力方法。即使如此,蛮力是有限的60万迭代保持算法的时间盒装。会有三个程序重新尝试后放弃。每次重试之间,递归序列是随机重排与希望的新的序列,将导致一个快速的解决方案。如果蛮力三个重试失败后,它不是一个完整的失败。我们可能有更多的运气,与未来的相机框架。上面的图是实施在SudSolver :: SolveMe()。缓冲的解决方案
当找到解决方案,我们保持最近期的解决方案中数组类型SudResultVoter的轨道。缓冲是必要的,因为OCR是不是100%可靠,我们不时得到错误的解决方案。为了避免波动的解决方案,我们将始终显示最强的解决方案,最近已被发现(在过去12解决方案,要准确)。不时,数组复位,忘了旧的解决方案,并提供一个机会,以一个新的数独,是目前在重点。视频
待办事项
为未来的一些想法:改写为Android方案。我不知道如何将智能手机上。并行处理的一些功能,使用多核处理器。今天,几乎所有的电脑都至少双核心处理器。通常情况下,并行任务使用以提高性能。但与摄像头的求解,我们并不需要更快的速度,我们需要更多的品质。这个想法是并行任务在同一帧图像,但使用不同的设置应执行相同的操作。所有的任务都加入后,我们将用最好的结果和放电他人的任务。历史2011年8月08 - 初版。|博扬万古

回答

评论会员:难以置信 时间:2012/02/04
马里奥Majcica
评论会员:!欢呼 时间:2012/02/04
thatraja:......(MVP得主,2012年){S20的}
thatraja
| |没人仍然是一个处​​女,生活螺丝大家
评论会员:拉杰什Anuhya 时间:2012/02/04
我的投票5,良好的工作
评论会员:sisira 时间:2012/02/04
有没有人实施的16位图像处理?如果是的话请分享。感谢:
|
sisira:伟大的工作
评论会员:Nigam的帕特尔 时间:2012/02/04
好的artical {S22的}
:2614807 |会员
评论会员:游客 时间:2012/02/04
好文章。爱你已清楚解释每个子课题的方式
pablosfor:这篇文章是非常完整的和有益的。非常感谢
评论会员:马赫迪Nejadsahebi 时间:2012/02/04
大文章。为进一步研究的书签。我也很喜欢你改写为Android程序的想法。 {S22的}
评论会员:RKnGl 时间:2012/02/04
!优秀的文章和代码

感谢分享。 S22的{}
评论会员:Irwan哈桑 时间:2012/02/04
这是伟大的
评论会员:!_groo_ 时间:2012/02/04
。绝对大,以便在一个程序等1问题的多元化数
评论会员:博扬万古 时间:2012/02/04
我没有' ţ阅读整篇文章。但画面讲千言万语。这是非常好的文章,很好地解释
评论会员:aeastham 时间:2012/02/04
大文章,唯一奇怪的是10fps的捕获率。 100ms的是获取一个帧太多。我没有问题,在C#与Matlab使用一个廉价的罗技QuickCam(约20美元)的30fps的。在CodeProject上有几篇文章使用不同的技术(WIA标准,DirectShow的,OpenCV的),并达到相当不错的帧速率
评论会员:游客 时间:2012/02/04
约瑟普cagalj|100ms的肯定是太慢了。我有两个摄像头。缓慢。但可能只是意外。我从来没有困扰与相机的速度。因为如果它运作良好,一个缓慢的相机,它会在快速工作做得更好。我的印象是,相机的速度取决于摄像头驱动程序和硬件,软件(凸轮使用的技术。驱动程序包装),。来检查,通过使用不同的样品在CodeProject上发现的应用程序应该有一个至少4个不同的相机和措施帧率
亚历山大・沃罗宁:这是一个奇妙的引进,图像处理。感谢分享你们的辛勤工作。安迪:

| jerviz_76
评论会员:游客 时间:2012/02/04
!Vrlopohvalno,svaka演员:|幸运VDB
!非常非常好的工作
评论会员:adit_sheth 时间:2012/02/04

评论会员:EugeneZak:真棒{BR} 时间:2012/02/04
manos_crete:
|真正noice工作