我有一个C ++二值化例程,我将其用于以后的OCR操作。 但是我发现它产生了不必要的文本倾斜。 寻找替代方案我发现GPUImage具有重要价值,它解决了倾斜问题。
我在使用OCR之前使用GPUImage code like this二进制化我的输入图像。
然而,阈值不包括我得到的图像范围。 查看输入图像中的两个样本:
我无法使用相同的阈值处理两者。 较低的值似乎在以后很好,而第一个值更高的值。
第二张图片似乎特别复杂,因为我从未让所有的字符都被正确地二进制化,无论我为阈值设置了什么值。另一方面,我的C ++二值化例程似乎做得对,但我没有太多的见解可以像GPUImage中的简单阈值一样进行实验。
我应该如何处理?
更新
我尝试使用GPUImageAverageLuminanceThresholdFilter
并使用默认乘数= 1.它适用于第一张图片,但第二张图片仍然存在问题。
一些更加多样化的二值化输入:
更新II:
在浏览this answer by Brad之后,尝试了GPUImageAdaptiveThresholdFilter
(也包含了GPUImagePicture,因为之前我只在UIImage上应用它)。
有了这个,我得到了第二张二进制图像。然而,当我设置模糊大小为3.0时,第一个似乎在二值化后有很多噪音。 OCR导致添加额外字符。使用较低的模糊大小值,第二个图像会失去精确度。
这是:
+(UIImage *)binarize : (UIImage *) sourceImage
{
UIImage * grayScaledImg = [self toGrayscale:sourceImage];
GPUImagePicture *imageSource = [[GPUImagePicture alloc] initWithImage:grayScaledImg];
GPUImageAdaptiveThresholdFilter *stillImageFilter = [[GPUImageAdaptiveThresholdFilter alloc] init];
stillImageFilter.blurSize = 3.0;
[imageSource addTarget:stillImageFilter];
[imageSource processImage];
UIImage *imageWithAppliedThreshold = [stillImageFilter imageFromCurrentlyProcessedOutput];
// UIImage *destImage = [thresholdFilter imageByFilteringImage:grayScaledImg];
return imageWithAppliedThreshold;
}
答案 0 :(得分:2)
对于预处理步骤,您需要adaptive thresholding。
我使用opencv灰度和自适应阈值方法得到了这些结果。也许通过添加低通噪声滤波(高斯或中值),它应该像魅力一样。
我使用provisia(它是一个ui来帮助你快速处理图像)来获得我需要的块大小:这里提供的图像为43。如果您从更近或更远的地方拍摄照片,块大小可能会改变。如果你想要一个通用算法,你需要开发一个应该搜索最佳大小的算法(搜索直到检测到数字)
编辑: 我刚看到最后一张图片。它非常小。即使您应用最佳的预处理算法,也不会检测到这些数字。由于噪音将会出现,因此采样不会成为解决方案。
答案 1 :(得分:1)
我最终以自己的方式进行了探索,这是 GPUImage
过滤器的结果:
+ (UIImage *) doBinarize:(UIImage *)sourceImage
{
//first off, try to grayscale the image using iOS core Image routine
UIImage * grayScaledImg = [self grayImage:sourceImage];
GPUImagePicture *imageSource = [[GPUImagePicture alloc] initWithImage:grayScaledImg];
GPUImageAdaptiveThresholdFilter *stillImageFilter = [[GPUImageAdaptiveThresholdFilter alloc] init];
stillImageFilter.blurSize = 8.0;
[imageSource addTarget:stillImageFilter];
[imageSource processImage];
UIImage *retImage = [stillImageFilter imageFromCurrentlyProcessedOutput];
return retImage;
}
+ (UIImage *) grayImage :(UIImage *)inputImage
{
// Create a graphic context.
UIGraphicsBeginImageContextWithOptions(inputImage.size, NO, 1.0);
CGRect imageRect = CGRectMake(0, 0, inputImage.size.width, inputImage.size.height);
// Draw the image with the luminosity blend mode.
// On top of a white background, this will give a black and white image.
[inputImage drawInRect:imageRect blendMode:kCGBlendModeLuminosity alpha:1.0];
// Get the resulting image.
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return outputImage;
}
我使用这个几乎达到了90% - 我确信必须有更好的选项,但我尽可能尝试使用blurSize
,而8.0是与大多数我的输入图像一起使用的值< / em>的
对于其他任何人,祝你好运!
答案 2 :(得分:0)
<强> SWIFT3 强>
解决方案1
extension UIImage {
func doBinarize() -> UIImage? {
let grayScaledImg = self.grayImage()
let imageSource = GPUImagePicture(image: grayScaledImg)
let stillImageFilter = GPUImageAdaptiveThresholdFilter()
stillImageFilter.blurRadiusInPixels = 8.0
imageSource!.addTarget(stillImageFilter)
stillImageFilter.useNextFrameForImageCapture()
imageSource!.processImage()
guard let retImage: UIImage = stillImageFilter.imageFromCurrentFramebuffer(with: UIImageOrientation.up) else {
print("unable to obtain UIImage from filter")
return nil
}
return retImage
}
func grayImage() -> UIImage? {
UIGraphicsBeginImageContextWithOptions(self.size, false, 1.0)
let imageRect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
self.draw(in: imageRect, blendMode: .luminosity, alpha: 1.0)
let outputImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return outputImage
}
}
解决方案2
使用GPUImageLuminanceThresholdFilter
实现100%黑白效果,不带灰色
let stillImageFilter = GPUImageLuminanceThresholdFilter()
stillImageFilter.threshold = 0.9