目录

使用Google Gemini实现OCR

写这篇文章的原因是,我目前在参与一个手机APP的项目。其中有功能要求,用户在APP中使用手机摄像头,拍摄食品外包装上的配料表。APP分析配料表图片,识别出其中的各种食材原料。

然后从所识别出的食材原料中,筛选出添加剂,以及过量食用会对对人体健康不利的如:糖、盐、酒精、易过敏的物质等。

按照功能要求,第一步就是对用户拍摄的照片,进行OCR识别,并且识别的准确率要尽可能的高。

测试 Vertex AI OCR

需要识别的食品配料表

需要识别的食品配料表

以前的项目中,只要Google提供相关的API,我们都会尽量选择选择Google的API服务。这次需要做OCR识别,Google API服务也是我们的首选。

搜索Google的开发者文档,发现OCR API已经迁入Vertex AI,而Vertex AI提供的多模态,其背后使用的实际服务是Google Gemini 1.5 flash和Gemini 1.5 pro。

Google Cloud - Vertex AI

Google Cloud - Vertex AI

似乎Google现在针对AI服务都提供了类似的Studio,Gemini有Google AI Studio,Vertex AI也有Vertex AI Studio。上传需要识别的食品配料表照片,使用简单描述词,“Read the text in this image”。Vertex AI Studio中默认设置的温度是1,Top-P是0.95,模型默认选择是gemini-1.5-flash-001。点击运行后,很快输出结果,不出所料近乎完美的识别准确性。

测试Gemini AI OCR

因为Vertex AI的完美表现,我们开始尝试使用Gemini API来自己实现OCR功能。

把相同的图片,相同的描述词,重新添加到Google AI Studio中。在消耗了400多个Token后,得到的结果却惨不忍睹。

Google Gemini AI

Google Gemini AI

于是我开始尝试修改描述词,开始在System Instructions中添加限制条件,但是输出结果依然不可用。

就在我准备放弃时,突然想起来,以前做OCR程序开发,对用户上传的图片都要经过一些预处理,例如灰度化,做提升亮度、锐度、对比度等等。

现在虽然最终处理服务转用多模态模型,但是质量不高的输入图片,应该还是会对数据处理操作产生极大的影响。于是我先尝试用图像处理软件,手工调节这张图片的锐度和对比度。

需要识别的食品配料表 - 提升锐度、对比度

需要识别的食品配料表 - 提升锐度、对比度

把这张图片添加到Google AI Studio中。继续使用简单描述词,“Read the text in this image”,结果完美。

提升锐度、对比度后,Gemini AI对图片内容的识别

提升锐度、对比度后,Gemini AI对图片内容的识别

最终实现

经过以上的测试验证,只要上传的图片足够清晰,自己使用Gemini API和简单描述词就可以实现效果非常完美的OCR功能。

由于我们后端开发语言是Golang,向Gemini提问,它向我们推荐了 github.com/disintegration/imaging 。虽然这个库已经有5年没有发新版本,但是5.2k stars,极少的Issues,让我们还是决定试用一下它。


func improveImageContrast(imgUrl string) (ouputImgUrl string, err error) {
	src, err := imaging.Open(imgUrl, imaging.AutoOrientation(true))
	if err != nil {
		log.Printf("imageing.Open error: %v", err)
		return "", err
	}
	fileName := filepath.Base(imgUrl)
	img2 := imaging.Grayscale(src)
	img2 = imaging.AdjustContrast(src, 55)
	img2 = imaging.Sharpen(img2, 1.5)
	//img2 = imaging.AdjustGamma(img2, 1.5)
	ouputImgUrl = config.Cfg.App.ImproveDir + fileName
	if err = imaging.Save(img2, ouputImgUrl); err != nil {
		log.Printf("imageing.Save error: %v", err)
		return "", err
	}
	return ouputImgUrl, nil
}

简单的一个func,提升图片的锐度和对比度,这里的55和1.5是我们经过多次尝试的经验值,使用中可以根据实际情况进行调整。

需要注意一点,图片中文字的方向,对OCR识别的准确率有极大的影响。 在最初实现中,调用imaging.Open时,我们没有设置imaging.AutoOrientation(true)。虽然用户上传的照片中,文字的方向是向上的。但是因为图片纵向长宽比,经过提升锐度和对比度方法后,输出图片变成横向,图片内的文字方向朝向左侧。识别出的文字虽然精确度已经提高不少,但是还是会出现个别错误。当调用imaging.Open,设置imaging.AutoOrientation(true)后,输出图片中文字向上,识别率就接近100%了。