本帖最后由 tryhi 于 2013-4-19 21:24 编辑
其实之前开过这个贴,后来没人回复之后好像被关闭了http://www.autoitx.com/thread-37246-1-1.html
发出去的分收不回大家尽力拍砖。
注:图中的软件是用了疯子前辈的软件http://www.autoitx.com/forum.php?mod=viewthread&tid=32094
由于没学过验证码识别,所以提出的问题可能有点弱
图中红色(单点双点)、绿色(三点相连)的点是要去除的(所谓的红色绿色是我标出来,实际上图片已经二值化了,见代码),目前我只想到了红色点的去除,关于绿色点没有比较好的方案,红色的思路是这样的,搜索该点周围8个点,如果空白,则去除,如果周围只有1个点,则搜索这一个的周围8个点,发现它也只有一个,就两个都去除,这样就能实现去除红色点的效果,代码如下,可能效率、思路、代码都不是很好,关于三点相连或者抱团的点,应该怎么去除比较好?R的右腿那里有个很浅的红色圆圈那里三个点是不用去除的,怕有人误除,特指出来。
以下代码为去除单点双点的算法
;去除单双噪点算法例子
#include <Array.au3>
$string = " 0 "&@CRLF& _
" 0 00 "&@CRLF& _
" 00 0 0 0 "&@CRLF& _
" 0 0 0 0 0 "&@CRLF& _
" 0 000 0 "&@CRLF& _
" 0 0 "&@CRLF& _
" 0 0 0 "&@CRLF& _
" 0 0 00 "&@CRLF& _
" 0 0 "&@CRLF& _
" 00 00 0 0 "&@CRLF& _
" 00000000 0 0 "&@CRLF& _
" 00 0 0 0 0000000 "&@CRLF& _
" 00 0 0 00000 000 "&@CRLF& _
" 00 0 00 00 0 "&@CRLF& _
" 00 0 00 00 "&@CRLF& _
" 0 00 000000000 0 00 00 "&@CRLF& _
"0 00 0 00 000 0000000000 00 00 "&@CRLF& _
" 00 0 00 000 000 0 0 00 000 "&@CRLF& _
" 00 00 00 00 0 0 0 00 0 00 "&@CRLF& _
" 00 00 0 00 00 0 00 00 "&@CRLF& _
" 00 0 00 000 0 00 00 00 "&@CRLF& _
" 00 0 00 00 00 0 0 000 00 "&@CRLF& _
" 00 00 0000 0 00 0 0 00 00 "&@CRLF& _
" 0 00 0000000 0 00 00 00 00 "&@CRLF& _
" 00 00 00 0 0 00000000 0 0 00 0 00 "&@CRLF& _
" 00 0 0 000 00 00 00 0 00 00"&@CRLF& _
" 00 00 00 000 0 00 0 "&@CRLF& _
" 00 00 0 00 00 0 00 00 "&@CRLF& _
" 00 00 0000 00 00 0 "&@CRLF& _
" 00 00 0000 00 0 00 00 "&@CRLF& _
" 00 00 00 00 0 00 000 "&@CRLF& _
" 00 00 00 00 0 00 0 0000000 "&@CRLF& _
" 00000000 0 0000 000 00 000 "&@CRLF& _
" 00 0 000 0 0 "&@CRLF& _
" 0 0 0 00 0 0 "&@CRLF
Local $array_s[35][97];定义36x98的二维数组
$hang = StringRegExp($string,'\V+',3);===========此段代码为拆分进二维数组
For $i = 0 To 34
$lie = StringSplit($hang[$i],'',2)
For $j = 0 To 96
$array_s[$i][$j] = $lie[$j]
Next
Next;===================================================================
_quchuzaodian($array_s);主函数
_ArrayDisplay($array_s,'去除噪声之后');去除噪点之后的数组
Func _quchuzaodian(ByRef $array)
$35 = UBound($array, 1) - 1
$97 = UBound($array, 2) - 1
For $i = 0 To $35;纵向历遍
For $j = 0 To $97;横向历遍
If $array[$i][$j] = "0" Then;一路扫过去发现0停下搜索四周
$sizhou = _sizhou($array, $i, $j);搜索四周8个点,返回一个数组,[0]为四周存在0的的数量
If $sizhou[0] = 0 Then $array[$i][$j] = " ";发现四周不存在其他点,则去除该点(变为空格变量则去除)
If $sizhou[0] = 1 Then;发现只存在一个点
$sizhou2 = _sizhou($array, $sizhou[1], $sizhou[2]);则搜索存在的这个点四周8个点
If $sizhou2[0] = 1 Then;发现也只有一个点,也就是刚才那个点,则断定这是一个双点,可以去除这两个点
$array[$i][$j] = " ";去除
$array[$sizhou[1]][$sizhou[2]] = " ";去除
EndIf
EndIf
EndIf
Next
Next
EndFunc ;==>_quchuzaodian
Func _sizhou($array, $1, $2, $front = '0')
If Not IsArray($array) Then Return SetError(1)
Local $a = UBound($array, 1) - 1, $b = UBound($array, 2) - 1;$a为数组一维下标-1,$b为数组二维下标-1
Local $temp[3] = [0];定义一个数组用来存返回的结果0为四周存在点的数量,,若只有一个点,则,1为x坐标,2为y坐标
If $1 > 0 And $2 > 0 Then;左上角的点1维2维均要减1,所以要保证都大于零
If $array[$1 - 1][$2 - 1] = $front Then $temp = _sizhou_udf($temp, $1, $2, 1);左上角定义为1
EndIf
If $1 > 0 Then;上面的点1维要减1,所以要保证大于零
If $array[$1 - 1][$2 + 0] = $front Then $temp = _sizhou_udf($temp, $1, $2, 2);上面定义为2
EndIf
If $temp[0] >= 2 Then Return $temp;当超出2个点时候再往下已经没有意义了
If $1 > 0 And $2 < $b Then;左上角的点1维减1(保证大于0),2维要加1(保证小于$b不能超界)
If $array[$1 - 1][$2 + 1] = $front Then $temp = _sizhou_udf($temp, $1, $2, 3);右上角定义为3
EndIf
If $temp[0] >= 2 Then Return $temp;当超出2个点时候再往下已经没有意义了
If $2 < $b Then
If $array[$1 + 0][$2 + 1] = $front Then $temp = _sizhou_udf($temp, $1, $2, 4);右边定义为4
EndIf
If $temp[0] >= 2 Then Return $temp;当超出2个点时候再往下已经没有意义了
If $1 < $a And $2 < $b Then
If $array[$1 + 1][$2 + 1] = $front Then $temp = _sizhou_udf($temp, $1, $2, 5);右下角定义为5
EndIf
If $temp[0] >= 2 Then Return $temp;当超出2个点时候再往下已经没有意义了
If $1 < $a Then
If $array[$1 + 1][$2 + 0] = $front Then $temp = _sizhou_udf($temp, $1, $2, 6);下面定义为6
EndIf
If $temp[0] >= 2 Then Return $temp;当超出2个点时候再往下已经没有意义了
If $1 < $a And $2 > 0 Then
If $array[$1 + 1][$2 - 1] = $front Then $temp = _sizhou_udf($temp, $1, $2, 7);左下角定义为7
EndIf
If $temp[0] >= 2 Then Return $temp;当超出2个点时候再往下已经没有意义了
If $2 > 0 Then
If $array[$1 + 0][$2 - 1] = $front Then $temp = _sizhou_udf($temp, $1, $2, 8);左边定义为8
EndIf
Return $temp
EndFunc ;==>_sizhou
Func _sizhou_udf($array,$1,$2,$i)
Switch $i;将[1]、[2]分别变成该点坐标,这样会导致只记录最后一个点的坐标,不过没事,当超出两个点时这两个变量就没用了
Case 1
$array[1] = $1-1
$array[2] = $2-1
Case 2
$array[1] = $1-1
$array[2] = $2+0
Case 3
$array[1] =$1-1
$array[2] = $2+1
Case 4
$array[1] = $1+0
$array[2] = $2+1
Case 5
$array[1] = $1+1
$array[2] = $2+1
Case 6
$array[1] = $1+1
$array[2] = $2+0
Case 7
$array[1] = $1+1
$array[2] = $2-1
Case 8
$array[1] = $1+0
$array[2] = $2-1
EndSwitch
$array[0] += 1
Return $array
EndFunc
发现好多人看不懂我的表达,没办法将例子中的变量跟这个图联系起来,其实这个图只是表示一个二维数组
看到$string这个变量没有,把它拆进二维数组,一个子变量存一个字符,只有“0”或者一个空格,两种状态
你运行一下就会发现这个数组运行前跟运行后的变化
之前标记为红色的0变量全部成了空格变量
那有什么办法将标记为绿色(三个相连)的0变量也一并变成空格变量,就是一个这样的问题 |