文号
t12553
阅读
44289
回复
35
收藏
11
【RF】验证码的分析与识别[1]
2009/02/11
IP:广东
本人在科创发表的最后一系列文章

自从网络被应用,验证码也应运而生。验证码一般是由字母+数字+随机干扰组成的一幅图片。
人们在WEB或其他地方执行一些如注册、发表文章等操作时,往往要输入验证码,这是为了防止恶意行为。

本文章仅探讨验证码的识别作学习用途

前景与背景的分离方法

58_1_1264512711.png

这是一幅验证码,我们可以观察到,背景十分杂乱,而且有干扰线。
这是为了防止程序去识别它,但是 “凭着RF工作室的智慧” 可以说是轻而易举的

我们还可以观察到,背景与前景的颜色深度不一样——对,这就是关键。
这也就是说,背景的RGB值加起来肯定比前景的要小,这就好办了,我们先创建一个函数

Public Function ColorRGB(ByVal Color As Long) As Long
If Color = -1 Then ColorRGB = 999: Exit Function
Const ByN As Integer = 256
Const ByN2 As Long = 65536
Dim A(2) As Byte
A(0) = (Color Mod ByN)
A(1) = ((Color Mod ByN2) \ ByN)
A(2) = (Color \ ByN2)

ColorRGB = (Color Mod ByN) + ((Color Mod ByN2) \ ByN) + (Color \ ByN2)
End Function

好,我们看到,输入的是VB的颜色值,输出则是该颜色值RGB的总和。

然后我们可以调用这个函数

Picture2.Cls
Picture3.Cls
Dim l As Long
For i = 1 To 140 * 15 Step 15
    For j = 1 To 50 * 15 Step 15
    If ColorRGB(Picture1.Point(i, j)) < 560 Then
        l = l + 15
        Picture2.PSet (i, Picture2.Height - l)
        Picture3.PSet (i, j)
    End If
    Next
    l = 0
Next

我们看到,这个过程中有两个for循环,不断扫描图片,如果RGB值的总和小于560(180x3)就判断为前景。

这样,前景就被完美地分离出来了。

58_1_1139671021.png

前景与背景分离到此结束

干扰线的去除

但是,问题又来了。我们看到验证码中有随机的线段,这回严重影响验证码的识别工作
我们当然有办法应对。

注意观察两幅图片(线段的局部放大)

58_1_1302318119.png    58_1_1019096673.png

看到了吗?这是单像素的,我们也可以简单地解决掉。

我们再创建一个函数

Public Function ClearLine(ByVal iX As Long, ByVal iY As Long, picInput As PictureBox) As Boolean

Const W_VALUE As Long = 16777215

Dim tmp1, tmp2, tmp3, tmp4 As Long
Dim tmp As Long

If picInput.Point(iX, iY) = W_VALUE Then
    ClearLine = False
    Exit Function
End If

tmp1 = picInput.Point(iX + 15, iY)
tmp2 = picInput.Point(iX - 15, iY)
tmp3 = picInput.Point(iX, iY + 15)
tmp4 = picInput.Point(iX, iY - 15)

If tmp1 = W_VALUE Then tmp = tmp + 1
If tmp2 = W_VALUE Then tmp = tmp + 1
If tmp3 = W_VALUE Then tmp = tmp + 1
If tmp4 = W_VALUE Then tmp = tmp + 1

If tmp > 2 Then
    ClearLine = True
End If

If tmp3 = W_VALUE And tmp4 = W_VALUE Then
    ClearLine = True
End If

End Function

这段代码的作用是,扫描一个像素的上下左右,如果有3个点是白色的,就判断为线段的一部分。

然后我们调用它

Dim i, j As Long

For i = 1 To 140 * 15 Step 15
    For j = 1 To 50 * 15 Step 15

    If ClearLine(i, j, Picture3) Then
        Picture3.PSet (i, j), 16777215
    End If
    
    Next
Next


如图
58_1_1190603827.png

这样,干扰线也被完美地去除了。

未完待续
+1000
科创币
delete
2009/02/11
妙
+1000
科创币
彼岸江山
2009/02/11
很好,谢老
+1000
科创币
chiataimakro
2009/02/11
+1000
科创币
虎哥
2009/02/11
思路不错。
93°作者
17年11个月前IP:未同步
74579
2楼
有没有搞错,这是我发过的最正经的帖子啊
+1
科创币
彼岸江山
2009/02/12
ding
引用
评论
93°作者
17年11个月前IP:未同步
74628
6楼
楼上正确

正在转向delphi中。客户要求

58_3212_1114129532.png
引用
评论
93°作者
17年11个月前IP:未同步
74639
8楼
参见旋转卡壳算法,迟一些我再介绍。

delphi的兼容性无敌啊。。
引用
评论
93°作者
17年11个月前IP:未同步
74992
12楼
唉唉 。。都没啥人看
引用
评论
93°作者
17年9个月前IP:未同步
88250
19楼
LS错误
在.NET里是没有point函数的,.NET里的point是一个类型,不会连这都不知道吧
.NET里用getpixel()
而delphi里用pixels[];
C/CPP我更偏向于直接读取BMP文件,因为BMP的结构直接就是RGB

PS 这个项目400块钱到手
+80
科创币
delete
2009/04/05
干什么
-80
科创币
chiataimakro
2009/04/05
个人所得税
引用
评论
93°作者
17年9个月前IP:未同步
88259
21楼
日飞破chia,pia!,您又不是ZF收个毛税啊……那天中午M记还是我用着400块请您吃的呢
引用
评论
93°作者
17年9个月前IP:未同步
88264
24楼
我啥时候说过不是VB,VB跟XXXXXX不是一种东西
VB的代码不能直接放到XXXXXX上运行
XXXXXX完全面向对象,所以不能像VB那样随便写
我用的是VB98开发的

PS:收钱的时候给的是delphi写的DLL
引用
评论
93°作者
17年9个月前IP:未同步
88268
26楼
我啥时候说过那400块钱全部用来吃MCD了?
引用
评论
93°作者
17年9个月前IP:未同步
88269
27楼
引用第22楼phpskycn于2009-04-05 12:05发表的  :
要知道你开发出的东西有巨大危害……
都出现Dim……
AS……了,还不是VB?

是的,用小括号代替大括号的编译器危害更大
引用
评论
1
93°作者
17年9个月前IP:未同步
88279
29楼
看来您连图形的基本算法都不懂吧
引用
评论
93°作者
17年9个月前IP:未同步
88293
33楼
引用第30楼phpskycn于2009-04-05 12:20发表的  :
的确,每次看到这个我都认没用又不会考,就忽略了。

为什么而学习?这是算法问题,经典算法存在就有它的价值
引用
评论
笔记
{{note.content}}
{{n.user.username}}
{{fromNow(n.toc)}} {{n.status === noteStatus.disabled ? "已屏蔽" : ""}} {{n.status === noteStatus.unknown ? "正在审核" : ""}} {{n.status === noteStatus.deleted ? '已删除' : ''}}
  • 编辑
  • 删除
  • {{n.status === 'disabled' ? "解除屏蔽" : "屏蔽" }}
我也是有底线的