首页 > 其他分享 >OpenCV自带dnn的Example研究(6)— text_detection

OpenCV自带dnn的Example研究(6)— text_detection

时间:2022-12-25 12:04:44浏览次数:57  
标签:std dnn geometry text float detection scores data size

​https://docs.opencv.org/master/examples.html​​下的



OpenCV自带dnn的Example研究(6)— text_detection_#include


6个文件,看看在最新的OpenCV中,它们是如何发挥作用的。


在配置使用的过程中,需要注意使用较高版本的VS避免编译器兼容问题;由于DNN程序的运行依赖于训练成功的模型,因此需要预先下载准备;此外如果出现各种报错,需要对症下药。


此外,由于需要使用common.hpp文件,所以需要引入dnn目录到include中



OpenCV自带dnn的Example研究(6)— text_detection_ide_02


用到的数据集都放在:


链接:https://pan.baidu.com/s/1WPoXU3VodErPHZo6Yc21xA 


提取码:01no 


如果你没找到,那一定是我忘了。


=====================================================================================友善的分割线============================


对于这个例子,之前我结合tesseract做过一个更好的,这里就不重复了。将其转过来:



目前的代码基本可用,但是需要进行进一步的重构。



获得所有的rect



OpenCV自带dnn的Example研究(6)— text_detection_#include_03


经过筛检后去掉很多



OpenCV自带dnn的Example研究(6)— text_detection_ide_04


里面就有我需要的。




OpenCV自带dnn的Example研究(6)— text_detection_#include_05


那么这里的识别还是有一定问题的,主要是east有漏的情况出现。适当进行修正。



OpenCV自带dnn的Example研究(6)— text_detection_ios_06



那么识别的结果主要是两个entire,一个是前后有多余字符;二个是可能存在错误。



OpenCV自带dnn的Example研究(6)— text_detection_ide_07



OpenCV自带dnn的Example研究(6)— text_detection_ios_08



OpenCV自带dnn的Example研究(6)— text_detection_ios_09




OpenCV自带dnn的Example研究(6)— text_detection_ios_10





我认为在现有的识别结果上,应该可以得到进一步的增强。但是需要建立一个“识别和调整”的循环机制,并且对特别是tesseract的参数调节有进一步的认识。




重新编译了OpenCV4,并且对代码重构,看上去效果非常不错:


// EAST+Tesseract实现自然场景下发票编码识别



// by jsxyhelu.cnblogs.com




#include "pch.h"



#include <iostream>




#include <opencv2/core.hpp>



#include <opencv2/highgui.hpp>



#include <opencv2/imgproc.hpp>



#include <opencv2/imgproc/imgproc_c.h>



#include <opencv2/dnn.hpp>



#include <allheaders.h> // leptonica main header for image io



#include <baseapi.h> // tesseract main header



using namespace std;



using namespace cv;



using namespace cv::dnn;



using namespace std;




//对east的结果进行解码



void decode(const Mat& scores, const Mat& geometry, float scoreThresh,



std::vector<RotatedRect>& detections, std::vector<float>& confidences)



{



detections.clear();



CV_Assert(scores.dims == 4); CV_Assert(geometry.dims == 4); CV_Assert(scores.size[0] == 1);



CV_Assert(geometry.size[0] == 1); CV_Assert(scores.size[1] == 1); CV_Assert(geometry.size[1] == 5);



CV_Assert(scores.size[2] == geometry.size[2]); CV_Assert(scores.size[3] == geometry.size[3]);




const int height = scores.size[2];



const int width = scores.size[3];



for (int y = 0; y < height; ++y)



{



const float* scoresData = scores.ptr<float>(0, 0, y);



const float* x0_data = geometry.ptr<float>(0, 0, y);



const float* x1_data = geometry.ptr<float>(0, 1, y);



const float* x2_data = geometry.ptr<float>(0, 2, y);



const float* x3_data = geometry.ptr<float>(0, 3, y);



const float* anglesData = geometry.ptr<float>(0, 4, y);



for (int x = 0; x < width; ++x)



{



float score = scoresData[x];



if (score < scoreThresh)



continue;




// Decode a prediction.



// Multiple by 4 because feature maps are 4 time less than input image.



float offsetX = x * 4.0f, offsetY = y * 4.0f;



float angle = anglesData[x];



float cosA = std::cos(angle);



float sinA = std::sin(angle);



float h = x0_data[x] + x2_data[x];



float w = x1_data[x] + x3_data[x];




Point2f offset(offsetX + cosA * x1_data[x] + sinA * x2_data[x],



offsetY - sinA * x1_data[x] + cosA * x2_data[x]);



Point2f p1 = Point2f(-sinA * h, -cosA * h) + offset;



Point2f p3 = Point2f(-cosA * w, sinA * w) + offset;



RotatedRect r(0.5f * (p1 + p3), Size2f(w, h), -angle * 180.0f / (float)CV_PI);



detections.push_back(r);



confidences.push_back(score);



}



}



}




int main()



{



//参数和常量准备



String model = "./frozen_east_text_detection.pb";



std::vector<Mat> outs;



std::vector<String> outNames(2);



outNames[0] = "feature_fusion/Conv_7/Sigmoid";



outNames[1] = "feature_fusion/concat_3";



Mat blob;



std::vector<RotatedRect> boxes;



std::vector<float> confidences;



std::vector<int> indices;



char cbuf[255];



// 引入EAST model



Net net = readNet(model);



//对tesseract进行初始化操作



tesseract::TessBaseAPI tess;



if (tess.Init("E:\\sandbox\\新建文件夹\\tessdata", "eng"))



{



std::cout << "OCRTesseract: Could not initialize tesseract." << std::endl;



return 1;



}




Mat src = imread("E:\\未来项目\\(15)微模式ocr\\发票图片\\2.png");



Mat board = src.clone();//用于显示图片



blobFromImage(src, blob, 1.0, Size(320, 320), Scalar(), true, false);//Scalar采用默认是设置




net.setInput(blob);



net.forward(outs, outNames);



Mat scores = outs[0];



Mat geometry = outs[1];




decode(scores, geometry, 0.5, boxes, confidences);//注意0.5是超参数



NMSBoxes(boxes, confidences, 0.5, 0.4, indices);




Point2f ratio((float)src.cols / 320, (float)src.rows / 320);//缩放比例




//获得最终框选结果



for (size_t i = 0; i < indices.size(); ++i)



{



RotatedRect& box = boxes[indices[i]];



Point2f vertices[4];



box.points(vertices);



for (int j = 0; j < 4; ++j)



{



vertices[j].x *= ratio.x;



vertices[j].y *= ratio.y;



}



Point2f* lastItemPointer = (vertices + sizeof vertices / sizeof vertices[0]);



vector<Point2f> contour(vertices, lastItemPointer);



//筛选出所有矩形中中心点y值小于整个图像1/6的举行,绘制最小外接矩形



Rect boundRect = boundingRect(Mat(contour));



//对rect适当进行扩充



boundRect = cv::Rect(boundRect.tl().x - 5, boundRect.tl().y, boundRect.width + 10, boundRect.height);



if (boundRect.y < src.rows / 6)



{



Mat roi = src(boundRect);



//绘制外接边线



for (int j = 0; j < 4; ++j)



line(board, vertices[j], vertices[(j + 1) % 4], Scalar(0, 255, 0), 1);



rectangle(board, boundRect, Scalar(0, 0, 255));//绘制外接最小矩形



//打印数据



sprintf_s(cbuf, "E:\\未来项目\\(15)微模式ocr\\发票图片\\roi\\%d.jpg", i);//打印出来



imwrite(cbuf, roi);



//将切割出来的图片输入tesseract中



auto pixs = pixRead(cbuf);



if (!pixs)



{



std::cout << "Cannot open input file: " << std::endl;



return 1;



}



// recognize



tess.SetImage(pixs);



tess.Recognize(0);



// get result and delete[] returned char* string



std::cout << std::unique_ptr<char[]>(tess.GetUTF8Text()).get() << std::endl;



putText(board, std::unique_ptr<char[]>(tess.GetUTF8Text()).get(), boundRect.tl(), 1, 1.0f, Scalar(0, 255, 0));



// cleanup



tess.Clear();



pixDestroy(&pixs);



}




}



imshow("board", board);



cv::waitKey();



getchar();



return 0;



}


标签:std,dnn,geometry,text,float,detection,scores,data,size
From: https://blog.51cto.com/jsxyhelu2017/5968067

相关文章