游戏验证码之“从五个怪中找出最壮实的那个”

发布时间:2024-04-19 05:29  浏览量:7

前言

这篇文章来自于学员群的问题,有一个游戏的验证是从五个相同样子的怪中找出最壮实的那个,具体样子看下图:

如果是手动验证很容易知道第3只怪是最壮实的,那么怎么让脚本也能知道呢?

以下是我关于这个脚本的思考过程,未必是最好的思路,仅供参考:

①、最壮实的怪有什么特点?

这个怪最大,占据的像素(数量)面积最大。

②、怎么知道每个怪的面积?

把怪和背景分离开得二值化,获取怪的像素数,不过这个问题我好像解决不了,原因是怪与怪之间有重叠的部分。

③、怪的整体面积不好算出来,可以不可以算局部面积?

我们其实并不是真的需要知道每个怪的面积大小,我们最终目的是找到最大的怪,如果相同局部对比,局部最大的那个怪就是最大的怪,比如都比较头部,头最大的怪就是整体最大的怪。

④、找哪个局部最为合理呢?

我最初的想方法是找高光,也就是最亮的那个像素点。

使用RGB阈值做了二值化,最亮的那个像素点是最大的怪脚的高光部分。

于是我思考为啥最大的怪高光是最亮的像素点呢?

因为图像在缩小后,高光点会变暗。

依据这个特性是不是找到最亮的像素点就找到最大的怪了???

按照这个思路写了如下代码:

Dim t = TickCount验证图(155,116,681,330) TracePrint "用时:",TickCount-tFunction 验证图(x1, y1, x2, y2)Dim GetColorDim arr = {0,0,0}KeepCapture For j = y1 To y2For i = x1 To x2GetColor = GetPixelColor(i,j)Dim record = ColorDiff(GetColor, "000000")If record > arr[1] Then arr[1] = recordarr[2] = iarr[3] = jEnd IfNextNextReleaseCapture TracePrint encode.TableToJson(arr)Dim n = (x2-x1)/5For i = 0 To 4 If x1 + n * i

输出结果:

原本我以为到这里就可以结束了,但是测试其他图发现这个思路有问题了。

上面我说到图像在缩小后,高光点会变暗,但是图像在放大后,高光点也可能会变暗。这就难办了,如果最大的怪是放大图片得到的,那根据高光点判断就会出错了。

⑤、根据高光点判断不行,那么就根据高光面,大怪的高光面理论上是比小怪的高光面要大的。

找到高光点后,把它做个扩展,让高光的颜色值范围变大一些,然后看高光面哪个面积大,哪个就是最大的怪。

Dim t = TickCount验证图 178,117,686,347TracePrint "用时:",TickCount-tFunction 验证图(x1, y1, x2, y2)Dim GetColorDim arr = {0,0,0}KeepCapture For j = y1 To y2For i = x1 To x2GetColor = GetPixelColor(i,j)Dim record = ColorDiff(GetColor, "000000")If record > arr[1] Then arr[1] = recordarr[2] = iarr[3] = jEnd IfNextNextReleaseCapture TracePrint encode.TableToJson(arr)Dim arr_num = {0,0}Dim n = (x2-x1)/5For i = 0 To 4// TracePrint "范围:",x1+n*i,y1,x1+n*(i+1),y2// TracePrint "范围"&i+1&"数量:",GetColorNum(x1+n*i,y1,x1+n*(i+1),y2,GetPixelColor(arr[2],arr[3]),0.96)Dim num = GetColorNum(x1+n*i,y1,x1+n*(i+1),y2,GetPixelColor(arr[2],arr[3]),0.9)TracePrint i+1,numIf num > arr_num[1] Then arr_num[1] = numarr_num[2] = i+1End IfNextTracePrint "最壮实的怪:",arr_num[2]End Function

原本我以为写到这里就可以了,后来又遇到问题了,如果高光点在重叠地方,就会出错。

看上图,最大的怪是第4个怪,但是高光点在武器上,这个武器高光正好在第3个怪上,脚本就会以为这个高光是第3个怪的,最终以为最大的怪是第三个怪。

⑥、不能以高光面作为判断区域,必须放大判断区域,我想的方式是用亮面。

Dim t = TickCount验证图1 178,117,686,347TracePrint "用时:",TickCount-tFunction 验证图1(x1, y1, x2, y2)Dim GetColorDim arr = {0,0,0}KeepCapture For j = y1 To y2For i = x1 To x2GetColor = GetPixelColor(i,j)Dim record = ColorDiff(GetColor, "000000")If record > arr[1] Then arr[1] = recordarr[2] = iarr[3] = jEnd IfNextNextReleaseCapture TracePrint encode.TableToJson(arr)Dim arr_num = {0,0}Dim n = (x2-x1)/5For i = 0 To 4// TracePrint "范围:",x1+n*i,y1,x1+n*(i+1),y2// TracePrint "范围"&i+1&"数量:",GetColorNum(x1+n*i,y1,x1+n*(i+1),y2,GetPixelColor(arr[2],arr[3]),0.96)Dim num = GetColorNum(x1+n*i,y1,x1+n*(i+1),y2,GetPixelColor(arr[2],arr[3]),0.6)TracePrint i+1,numIf num > arr_num[1] Then arr_num[1] = numarr_num[2] = i+1End IfNextTracePrint "最壮实的怪:",arr_num[2]End Function

这次代码和上面的代码只改动了一个数字,就是相似度从0.9改成了0.6,可以理解为和高光点90%相似的所有像素点组合是高光面,和高光点60%相似的所有像素点组合是亮面,通过扩大区域增加了识别的准确度。

⑦、写到这里突然我发现,我干嘛要通过高光点找亮面呢,这不是脱裤子放屁吗?直接找亮面不好吗?

亮面,阈值大于128就可以认为是亮面的颜色值。

Dim t = TickCount验证图 178,117,686,347TracePrint "用时:",TickCount-tFunction 验证图(x1, y1, x2, y2)Dim GetColor,numDim arr_num = {0,0}Dim n = (x2-x1)/5KeepCaptureFor i = 0 To 4num = 0For j = y1 To y2For r = x1+n*i To x1+n*(i+1)GetColor = GetPixelColor(r, j)If ColorDiff(GetColor, "000000") > 384 Then num = num + 1End IfNextNextIf num > arr_num[1] Then arr_num[1] = numarr_num[2] = i+1End IfNextTracePrint "最壮实的怪:",arr_num[2]ReleaseCaptureEnd Function

优化完以后,速度提升一倍,识别用时从1秒变成0.5秒。

外部推荐