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

這個博客系列,簡單來講,今天咱們就是要研究
6個文件,看看在最新的OpenCV中,它們是如何發揮做用的。
在配置使用的過程當中,須要注意使用較高版本的VS避免編譯器兼容問題;因爲DNN程序的運行依賴於訓練成功的模型,所以須要預先下載準備;此外若是出現各類報錯,須要對症下藥。
此外,因爲須要使用common.hpp文件,因此須要引入dnn目錄到include中
用到的數據集都放在:
連接:https://pan.baidu.com/s/1WPoXU3VodErPHZo6Yc21xA 
提取碼:01no 
若是你沒找到,那必定是我忘了。
=====================================================================================友善的分割線============================
對於這個例子,以前我結合tesseract作過一個更好的,這裏就不重複了。將其轉過來:

EAST+Tesseract識別天然場景下發票序號
目前的代碼基本可用,可是須要進行進一步的重構。

得到全部的rect
通過篩檢後去掉不少
裏面就有我須要的。

那麼這裏的識別仍是有必定問題的,主要是east有漏的狀況出現。適當進行修正。

那麼識別的結果主要是兩個entire,一個是先後有多餘字符;二個是可能存在錯誤。




我認爲在現有的識別結果上,應該能夠獲得進一步的加強。可是須要創建一個「識別和調整」的循環機制,而且對特別是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 Matscoresconst Matgeometryfloat scoreThresh,
    std::vector<RotatedRect>& detectionsstd::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 floatscoresData = scores.ptr<float>(0, 0, y);
        const floatx0_data = geometry.ptr<float>(0, 0, y);
        const floatx1_data = geometry.ptr<float>(0, 1, y);
        const floatx2_data = geometry.ptr<float>(0, 2, y);
        const floatx3_data = geometry.ptr<float>(0, 3, y);
        const floatanglesData = 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 * wsinA * w+ offset;
            RotatedRect r(0.5f * (p1 + p3), Size2f(wh), -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<Matouts;
    std::vector<StringoutNames(2);
    outNames[0] = "feature_fusion/Conv_7/Sigmoid";
    outNames[1] = "feature_fusion/concat_3";
    Mat  blob;
    std::vector<RotatedRectboxes;
    std::vector<floatconfidences;
    std::vector<intindices;
    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(srcblob, 1.0, Size(320, 320), Scalar(), truefalse);//Scalar採用默認是設置
    net.setInput(blob);
    net.forward(outsoutNames);
    Mat scores = outs[0];
    Mat geometry = outs[1];
    decode(scoresgeometry, 0.5, boxesconfidences);//注意0.5是超參數
    NMSBoxes(boxesconfidences, 0.5, 0.4, indices);
    Point2f ratio((float)src.cols / 320, (float)src.rows / 320);//縮放比例
    //得到最終框選結果
    for (size_t i = 0; i < indices.size(); ++i)
    {
        RotatedRectbox = 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;
        }
        Point2flastItemPointer = (vertices + sizeof vertices / sizeof vertices[0]);
        vector<Point2fcontour(verticeslastItemPointer);
        //篩選出全部矩形中中心點y值小於整個圖像1/6的舉行,繪製最小外接矩形
        Rect boundRect = boundingRect(Mat(contour));
        //對rect適當進行擴充
        boundRect = cv::Rect(boundRect.tl().x - 5, boundRect.tl().yboundRect.width + 10, boundRect.height);
        if (boundRect.y < src.rows / 6)
        {
            Mat roi = src(boundRect);
            //繪製外接邊線
            for (int j = 0; j < 4; ++j)
                line(boardvertices[j], vertices[(j + 1) % 4], Scalar(0, 255, 0), 1);
            rectangle(boardboundRectScalar(0, 0, 255));//繪製外接最小矩形
            //打印數據
            sprintf_s(cbuf"E:\\將來項目\\(15)微模式ocr\\發票圖片\\roi\\%d.jpg"i);//打印出來
            imwrite(cbufroi);
            //將切割出來的圖片輸入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(boardstd::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;
}



相關文章
相關標籤/搜索