Opencv实战 文字区域的提取

这篇博客的来源

笔者在技术群里看到了 OpenCV入门笔记(七) 文字区域的提取 这篇博客,确实解决文字区域的提取有很大的帮助,但是这篇博客是python来写的算法,笔者是专职C++的程序猿,python固然能够看懂,但能够用C++来实现,既提高了个人的改写算法的能力,也能提高算法的运行效率,何乐而不为啊。多的就不多说了,整个算法的流程,笔者均是按照上面提到的这篇博客来做的C++化,再详细的大家可以参考上面这边博客,笔者在这里还是直接贴代码吧。

代码区

const string IMAGEPATH = "demo2.jpg";//图像路径
int _tmain(int argc, _TCHAR* argv[])
{
    Mat textImageSrc = imread(IMAGEPATH);
    detect(textImageSrc);

    return 0;
}

Mat preprocess(Mat gray)
{
    //1.Sobel算子,x方向求梯度
    Mat sobel;
    Sobel(gray, sobel, CV_8U, 1, 0, 3);

    //2.二值化
    Mat binary;
    threshold(sobel, binary, 0, 255, THRESH_OTSU + THRESH_BINARY);

    //3.膨胀和腐蚀操作核设定
    Mat element1 = getStructuringElement(MORPH_RECT, Size(30, 9));
    //控制高度设置可以控制上下行的膨胀程度,例如3比4的区分能力更强,但也会造成漏检
    Mat element2 = getStructuringElement(MORPH_RECT, Size(24, 4));

    //4.膨胀一次,让轮廓突出
    Mat dilate1;
    dilate(binary, dilate1, element2);

    //5.腐蚀一次,去掉细节,表格线等。这里去掉的是竖直的线
    Mat erode1;
    erode(dilate1, erode1, element1);

    //6.再次膨胀,让轮廓明显一些
    Mat dilate2;
    dilate(erode1, dilate2, element2);

    //7.存储中间图片
    imwrite("binary.jpg", binary);
    imwrite("dilate1.jpg", dilate1);
    imwrite("erode1.jpg", erode1);
    imwrite("dilate2.jpg", dilate2);

    return dilate2;
}


vector<RotatedRect> findTextRegion(Mat img)
{
    vector<RotatedRect> rects;
    //1.查找轮廓
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    findContours(img, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE, Point(0, 0));

    //2.筛选那些面积小的
    for (int i = 0; i < contours.size(); i++)
    {
        //计算当前轮廓的面积
        double area = contourArea(contours[i]);

        //面积小于1000的全部筛选掉
        if (area < 1000)
            continue;

        //轮廓近似,作用较小,approxPolyDP函数有待研究
        double epsilon = 0.001*arcLength(contours[i], true);
        Mat approx;
        approxPolyDP(contours[i], approx, epsilon, true);

        //找到最小矩形,该矩形可能有方向
        RotatedRect rect = minAreaRect(contours[i]);

        //计算高和宽
        int m_width = rect.boundingRect().width;
        int m_height = rect.boundingRect().height;

        //筛选那些太细的矩形,留下扁的
        if (m_height > m_width * 1.2)
            continue;

        //符合条件的rect添加到rects集合中
        rects.push_back(rect);

    }
    return rects;
}

void detect(Mat img)
{
    //1.转化成灰度图
    Mat gray;
    cvtColor(img, gray, CV_BGR2GRAY);

    //2.形态学变换的预处理,得到可以查找矩形的轮廓
    Mat dilation = preprocess(gray);

    //3.查找和筛选文字区域
    vector<RotatedRect> rects = findTextRegion(dilation);

    //4.用绿线画出这些找到的轮廓
    for each (RotatedRect rect in rects)
    {
        Point2f P[4];
        rect.points(P);
        for (int j = 0; j <= 3; j++)
        {
            line(img, P[j], P[(j + 1) % 4], Scalar(0,255,0), 2);
        }
    }

    //5.显示带轮廓的图像
    imshow("img", img);
    imwrite("imgDrawRect.jpg", img);

    waitKey(0);
}

成果区

这里,笔者给出上面所说的博客的图像的处理效果,另外笔者随意在网页上截了两张图,一共三个演示实例 
【原图1】来自上面所说的博客截图 
这里写图片描述 
【二值图1】 
这里写图片描述 
【初次膨胀图1】 
这里写图片描述 
【初次腐蚀图1】 
这里写图片描述 
【二次膨胀图1】 
这里写图片描述 
【最终结果图1】 
这里写图片描述 
【原图2】来自任意搜索后的网页截图 
这里写图片描述 
【二值图2】 
这里写图片描述 
【初次膨胀图2】 
这里写图片描述 
【初次腐蚀图2】 
这里写图片描述 
【二次膨胀图2】 
这里写图片描述 
【最终结果图2】 
这里写图片描述 
【原图3】有倾角的截图 
这里写图片描述 
【二值图3】 
这里写图片描述 
【初次膨胀图3】 
这里写图片描述 
【初次腐蚀图3】 
这里写图片描述 
【二次膨胀图3】 
这里写图片描述 
【最终结果图3】 
这里写图片描述

猜你喜欢

转载自blog.csdn.net/yangzm/article/details/81105844