简单的验证码识别OC

第一次接触图像解析,随便上网搜罗了一些资料自己整理了一下就不要脸的写了下来,有错的地方还望指点.

先说说大致流程吧
1.先将图片进行降噪
2.将降噪的图片二值化
3.对二值化的图片进行划分,分割出独立的字符图片
4.识别

这是一个验证码

我的梦想是做一个二维码.png

一、降噪
1.我拿来处理的验证码本身格式很简单,所以我对图片进行了灰值化处理。
图片本身是一个个像素点构成,可以将图片看成是一个由像素构成的二维数组。每个像素点都有Red Green Blue三个颜色的值,通过遍历像素点,令R = G = B来完成图片的灰值化。
常见的灰值化算法(方法??):
1.g(x,y) = (r(x,y) + g(x,y) + b(x,y))/3
2.g(x,y) = 0.11r(x,y) + 0.59g(x,y) + 0.3*b(x,y)
3.g(x,y) = min(min(r(x,y), g(x,y)) , b(x,y))

第二种算法是来源于NTSC色彩空间中Y分量的计算公式,处理大部分验证码效果比较满意。但处理红色调为主的验证码就不行了,权值太小。在我的案例里我选用的就是第二种算法,因为我的图像真的简单:-D。

如果图片有噪点还需要对噪点进行判断,具体操作是判断某个像素点与周围8个像素点的色差是否大于某个阙值,如果大于就+1s,如果有超过6个像素点大于的话就认定位噪点。周围没有8个点的一律剔除,那些是边界点。

灰值化.png

二、二值化
没觉得二、二像一个表情??好了言归正传,当图像进行灰值化后通过计算阈值可以将图片进行二值化,低于阈值的g(x,y)设为0,高于阈值的设为1...是255!0代表黑色,255代表白色。虽然不准确,但是比较好理解。


二值化不要太清晰虽然本身就很清晰了.png

三、切分
这个我没写下去,我通过统计一条X轴上所有的黑色像素点来获取字与字之间间隔的阈值。当低于这个阈值或等于0时就可以认为这是字与字之间的间隔,通过这个分割字符串。好像还有别的方法切分,具体应该看是什么类型的验证码。

四、识别
我集成了TesserectORC进行匹配,所以我切分也没搞。大致还是记录一下吧。目前的图片在理想情况下会根据每个字符切成一块矩阵。这个矩阵上0是空白1是有像素。一个图片字符就转换为了一个矩阵,然后用你的肉眼去识别它,做成键值对,通过对比这个矩阵和另一个矩阵是否一致来确定另一个矩阵是不是这个字符。什么汉明距离,编辑距离我也不太懂,就当一个索引以后拓展。

五、TesserectORC
oc 上识别图像用这个应该没错,免费而且有google维护。

代码

#import "UIImage+BGImage.h"
#import <TesseractOCR/TesseractOCR.h>

@implementation UIImage (BGImage)

typedef enum {
    
    ALPHA = 0,
    
    BLUE = 1,
    
    GREEN = 2,
    
    RED = 3
    
} PIXELS;

- (UIImage *)convertToGrayscale {
    
    CGSize size = [self size];
    
    int width = size.width;
    
    int height = size.height;
    
    
    //获取像素点数组
    uint32_t *pixels = (uint32_t *) malloc(width * height * sizeof(uint32_t));
    
    memset(pixels, 0, width * height * sizeof(uint32_t));
    
    //创建颜色通道
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    
    //上下文规则??我也不懂
    CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, width * sizeof(uint32_t), colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast);
    
    //创建图片上下文
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), [self CGImage]);
    
    NSMutableArray *array = [NSMutableArray array];
    NSMutableArray *nub = [NSMutableArray array];
    for(int x = 0; x < width; x++) {
//        NSMutableString *str = [NSMutableString string];
        int i = 0;

        for(int y = 0; y < height; y++){
            
            uint8_t *rgbaPixel = (uint8_t *) &pixels[y * width + x];
            
            uint32_t gray = 0.11 * rgbaPixel[RED] + 0.59 * rgbaPixel[GREEN] + 0.3* rgbaPixel[BLUE];
//            uint32_t gray = MIN(MIN(rgbaPixel[RED], rgbaPixel[GREEN]), rgbaPixel[BLUE]);
//            uint32_t gray = rgbaPixel[GREEN];
            
            if (gray > 138) {
                gray = 255;
            }else {
                gray = 0;
                i++;
                //保存黑点的XY值
                NSValue *value = [NSValue valueWithCGPoint:CGPointMake(x, y)];
                [array addObject:value];
            }
            
            rgbaPixel[RED] = gray;
            
            rgbaPixel[GREEN] = gray;
            
            rgbaPixel[BLUE] = gray;
            
        }
        [nub addObject:[NSNumber numberWithInt:i]];
    }
//    NSLog(@"%@",nub);
////    NSLog(@"%@",array);
//    //i代表y值
//    for (int i = 0; i < nub.count; i++) {
//        NSNumber *num = nub[i];
//        if (num.intValue == 0) {
//            
//        }
//    }
    
    CGImageRef image = CGBitmapContextCreateImage(context);
    
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    free(pixels);
    
    UIImage *resultUIImage = [UIImage imageWithCGImage:image];
    
    CGImageRelease(image);

    G8Tesseract *rect = [[G8Tesseract alloc]init];
    rect.language = @"eng";
    rect.engineMode = G8OCREngineModeTesseractCubeCombined;
    rect.pageSegmentationMode = G8PageSegmentationModeAuto;
    rect.maximumRecognitionTime = 60.0;
    rect.image = resultUIImage;
    NSString *newStr = rect.recognizedText;
    
    NSLog(@"hhhhh::%@",newStr);
    
    return resultUIImage;
    
}

@end

差不多就是这样。能帮到需要的人一点点就好了。蟹蟹看完

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,408评论 4 371
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,690评论 2 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,036评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,726评论 0 221
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,123评论 3 296
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,037评论 1 225
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,178评论 2 318
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,964评论 0 213
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,703评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,863评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,333评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,658评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,374评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,195评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,988评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,167评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,970评论 2 279

推荐阅读更多精彩内容