• 按键公众号 :
按键精灵电脑版
立即下载

软件版本:2014.06
软件大小:22.9M
更新时间:2021-12-03

按键精灵安卓版
立即下载

软件版本:3.7.2
软件大小:46.2M
更新时间:2023-05-10

按键精灵iOS版
立即下载

软件版本:1.8.0
软件大小:29.2M
更新时间:2023-03-21

按键手机助手
立即下载

软件版本:3.8.0
软件大小:262M
更新时间:2023-05-30

快捷导航

登录 后使用快捷导航
没有帐号? 注册

发新话题 回复该主题

[笨蛋熊] 【大道至简】颜色里的秘密 - bitmap数据处理篇 [复制链接]

1#
颜色是一个 int32 类型的数据,我们32位的处理器,一次就能处理一个颜色,很方便是吧?
一张 100x100 的图片,一共才 10000 个点,每个点都是一个颜色,也就是说,这张图片的本质,其实是一个颜色的数组。

你可以把它理解为一个 bitmap[10000] 的一维数组,也可以把它理解为一个 bitmap[100][100] 的二维数组。

这俩东西在memory里的本质其实是一样的。



这里我们用到了 bitmap 这个单词,什么是 bitmap? bit 是位的意思,map 是图的意思,俩字连起来:位图。

Windows 系统里,管 bmp 这种格式的文件叫做位图文件,其实就是 bitmap picture 的缩写。

但实际上,在编程领域,这个单词代表的是像素点阵的意思,bmp只是一种存储格式,其核心要点,还是像素点阵。

我又要拿出这张图来了:



对于一些人来说,这种东西像是一座难以逾越的山峰,怎么识别?

学过我们前几期教程的人应该一眼就能看出来玄机了把?缺口处颜色发暗!

如果我们按照找图,或者找字的思路去做,颜色暗不一定就是缺口,因为被子的颜色也挺暗的,所以没办法二值化。

但就算阴影出现在被子上,我们的眼睛也能很好的识别到,因为被子更暗了!

所以其实这种验证码识别起来多简单啊?

他是不是给人看的?是!那就能识别,问题仅仅在于,现有的工具过于拉跨了,我们需要一套全新的工具来做这件事情。

什么工具?bitmap数据呀!



论坛里大漠也好,乐玩一号,鱼鱼也好,他们做的各种识别工具,其实都是基于 bitmap 数据开发的

使用 bitmap 数据来搞定这个东西,一下子难度就降下来了。

但是这里要先泼个冷水,按键精灵并不是一种擅长处理bitmap数据的语言,具体的事情还是得用C语言来做。

大家可以参考这篇教程:http://bbs.anjian.com/showtopic-699075-1.aspx



bitmap 处理主要有这几个概念:

width:也就是图像的宽度,因为bitmap数据通常是用一个一维数组来表示,那么访问每一个像素点的话,就需要宽度数据来确定第二行、第三行的位置
height:图像的高度,遍历像素点的时候用的
bpp:像素位宽,或者代指一个像素点的数据占多少个字节,一般在数据处理时,都会把图像转换为32位数据,占用4个字节
pitch:扫描行数据大小,就是一行像素点的数据大小,如果没有 pitch,每一个像素定位都需要用 width * 4,电脑计算乘法的性能是比较低的,因此一般会提前把这个数值计算出来。
bitmap[]:就是数据的数组了,这个数组在C语言里一般会定义为union,包括一个int32的颜色值,和4个byte的分量,方便拆分计算,这样可以少很多取分量的操作,提升性能。



一个典型的 bitmap 数据处理代码是这样的:
  1. for y = 0 to width - 1
  2.     for x = 0 to height - 1
  3.         int c = bitmap[pitch * y + x * bpp]
  4.         // 这里的C就是循环到的颜色了,进行运算然后分析结果
  5.     next
  6. next
复制代码
这里再次给出拼图验证码识别的核心逻辑C语言代码来帮助大家理解 bitmap 数据处理:
  1. // 识别滑块拼图验证码(返回中心点坐标的位置)
  2. int CrackSliderVCode(char* sFile, int sw, int sh, int iTop)
  3. {
  4.     // 滑块至少从 1/ 4 的位置开始,至少从拼图图形一半的地方结束
  5.     ClImage* img = ffbot_LoadImage(sFile);
  6.     int iPosS = sw;
  7.     int iPosE = img->width - (sw / 2);
  8.     int iOffsetY1 = iTop + (0.33 * sh);
  9.     int iOffsetY2 = iTop + (0.67 * sh);
  10.     int light = 255;
  11.     int left = 0;
  12.     for ( int i = iPosS; i < iPosE; i++ ) {
  13.         int l1[43];
  14.         int l2[43];
  15.         int lt[43];
  16.         for ( int p = 0; p < 43; p++ ) {
  17.             int x = i - 21 + p;
  18.             ClRgbQuad c1 = img->bitmapRGBA[ ((img->height - iOffsetY1) * img->width) + x ];
  19.             ClRgbQuad c2 = img->bitmapRGBA[ ((img->height - iOffsetY2) * img->width) + x ];
  20.             l1[p] = (max3(c1.rgbBlue, c1.rgbGreen, c1.rgbRed) + min3(c1.rgbBlue, c1.rgbGreen, c1.rgbRed)) / 2;
  21.             l2[p] = (max3(c1.rgbBlue, c1.rgbGreen, c1.rgbRed) + min3(c1.rgbBlue, c1.rgbGreen, c1.rgbRed)) / 2;
  22.             lt[p] = (l1[p] + l2[p]) / 2;
  23.         }
  24.         int lsum = 0;
  25.         for ( int p = 0; p < 43; p++ ) {
  26.             lsum += lt[p];
  27.         }
  28.         lsum = lsum / 43;
  29.         if (lsum < light) {
  30.             light = lsum;
  31.             left = i;
  32.         }
  33.         //printf("%d, %d\n", i, lsum);
  34.     }
  35.     //printf("最终结果:%d, %d\n", left, light);
  36.     ffbot_FreeBMP(img);
  37.     return left;
  38. }
复制代码
逻辑就是将RGB转换为HSV,然后统计V值(亮度),取平均最暗的位置,为拼图缺口位置。

学会 bitmap 处理,对于颜色来说,你已经成就太乙金仙,剩下的,就是在无尽的bitmap世界和需求中求索了。

2#

大佬快点填前面的坑哇

发新话题 回复该主题