OCR(Optical Character Recognition)光学字符识别,用来处理图像上的文本识别。其中有一个步骤叫做文本预处理和分割,在这个步骤中需要学会处理图像噪声和旋转,并且要确定候选文本的区域。
1、图像阀值化,消除所有颜色的信息,有用的信息填入白色,背景填入黑色
Mat Ocr::binarize(Mat input){
Mat binaryImage;
cvtColor(input, input, COLOR_BGR2GRAY);
//THRESH_OTSU 大津法
threshold(input, binaryImage, 0, 255, THRESH_OTSU);
//计算黑白像素的数据
int white=countNonZero(binaryImage);
int black=binaryImage.size().area()-white;
//如果白色比较多,反转它
return white
2、文本切割,找到文本所在的位置并提取他。创建连通区域(使用连通分量分析,搜索图像组的连接图像)
使用膨胀使图像元素加粗
Mat Ocr::showDilated(Mat input){
Mat dilated;
Mat kernel=getStructuringElement(MORPH_CROSS, Size(3,3));
dilate(input, dilated, kernel,Point(-1,-1),9);
imshow("dilated", dilated);
return dilated;
}
3、识别段落块
vector Ocr::findTextAreas(Mat input){
vector areas;
vector> contours;
findContours(input, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
for(auto contour:contours)
{
//找到旋转矩阵,确定每个轮廓的最小边界
auto box=minAreaRect(contour);
//丢弃非常小的矩阵
if(box.size.width<20||box.size.height<20)
{
continue;
}
double pro=box.angle<-45.0?box.size.height/box.size.width:box.size.width/box.size.height;
if(pro<2)
{
continue;
}
areas.push_back(box);
}
printf("areas=====%d\n",areas.size());
return areas;
}
4、文本提取和倾斜调整
Mat Ocr::deskewAndCrop(Mat input, const RotatedRect &box){
Mat cropped;
double angle=box.angle;
Size2f size=box.size;
if(angle<-45.0)
{
angle+=90.0;
//交换宽高
swap(size.width, size.height);
}
//根据角度旋转文本,getRotationMatrix2D二维防射变换矩阵,1。0保持原始比例
Mat transform=getRotationMatrix2D(box.center, angle, 1.0);
Mat rotated;
warpAffine(input, rotated, transform, input.size(),INTER_CUBIC);
//裁剪结果
getRectSubPix(rotated, size, box.center, cropped);
copyMakeBorder(cropped, cropped, 10, 10, 10, 10, BORDER_REFLECT,Scalar(0));
return cropped;
}
Mat ticket= ocr->binarize(imread("/Users/linfangfang/Desktop/pic.jpg"));
Mat dilated= ocr->showDilated(ticket);
// imshow("ticket test", dilated);
auto regions=ocr->findTextAreas(dilated);
for(auto region:regions){
auto cropped=ocr->deskewAndCrop(ticket, region);
imshow("cropped test", cropped);
waitKey(0);
destroyAllWindows();
}
//waitKey(0);
//destroyAllWindows();
delete ocr;