第一次接触图像解析,随便上网搜罗了一些资料自己整理了一下就不要脸的写了下来,有错的地方还望指点.
先说说大致流程吧
1.先将图片进行降噪
2.将降噪的图片二值化
3.对二值化的图片进行划分,分割出独立的字符图片
4.识别
这是一个验证码
一、降噪
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个点的一律剔除,那些是边界点。
二、二值化
没觉得二、二像一个表情??好了言归正传,当图像进行灰值化后通过计算阈值可以将图片进行二值化,低于阈值的g(x,y)设为0,高于阈值的设为1...是255!0代表黑色,255代表白色。虽然不准确,但是比较好理解。
三、切分
这个我没写下去,我通过统计一条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
差不多就是这样。能帮到需要的人一点点就好了。蟹蟹看完