票据预处理(二)

// DecetorOcr.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include"DecetorOcr.h"
#include<iostream>
#include<string>
#include<opencv.hpp>
using namespace cv;
using namespace std;

//图像细化
void chao_thinimage(Mat &srcimage)//单通道、二值化后的图像
{
    vector<Point> deletelist1;
    int Zhangmude[9];
    int nl = srcimage.rows;
    int nc = srcimage.cols;
    while (true)
    {
        for (int j = 1; j < (nl - 1); j++)
        {
            uchar* data_last = srcimage.ptr<uchar>(j - 1);
            uchar* data = srcimage.ptr<uchar>(j);
            uchar* data_next = srcimage.ptr<uchar>(j + 1);
            for (int i = 1; i < (nc - 1); i++)
            {
                if (data[i] == 255)
                {
                    Zhangmude[0] = 1;
                    if (data_last[i] == 255) Zhangmude[1] = 1;
                    else  Zhangmude[1] = 0;
                    if (data_last[i + 1] == 255) Zhangmude[2] = 1;
                    else  Zhangmude[2] = 0;
                    if (data[i + 1] == 255) Zhangmude[3] = 1;
                    else  Zhangmude[3] = 0;
                    if (data_next[i + 1] == 255) Zhangmude[4] = 1;
                    else  Zhangmude[4] = 0;
                    if (data_next[i] == 255) Zhangmude[5] = 1;
                    else  Zhangmude[5] = 0;
                    if (data_next[i - 1] == 255) Zhangmude[6] = 1;
                    else  Zhangmude[6] = 0;
                    if (data[i - 1] == 255) Zhangmude[7] = 1;
                    else  Zhangmude[7] = 0;
                    if (data_last[i - 1] == 255) Zhangmude[8] = 1;
                    else  Zhangmude[8] = 0;
                    int whitepointtotal = 0;
                    for (int k = 1; k < 9; k++)
                    {
                        whitepointtotal = whitepointtotal + Zhangmude[k];
                    }
                    if ((whitepointtotal >= 2) && (whitepointtotal <= 6))
                    {
                        int ap = 0;
                        if ((Zhangmude[1] == 0) && (Zhangmude[2] == 1)) ap++;
                        if ((Zhangmude[2] == 0) && (Zhangmude[3] == 1)) ap++;
                        if ((Zhangmude[3] == 0) && (Zhangmude[4] == 1)) ap++;
                        if ((Zhangmude[4] == 0) && (Zhangmude[5] == 1)) ap++;
                        if ((Zhangmude[5] == 0) && (Zhangmude[6] == 1)) ap++;
                        if ((Zhangmude[6] == 0) && (Zhangmude[7] == 1)) ap++;
                        if ((Zhangmude[7] == 0) && (Zhangmude[8] == 1)) ap++;
                        if ((Zhangmude[8] == 0) && (Zhangmude[1] == 1)) ap++;
                        if (ap == 1)
                        {
                            if ((Zhangmude[1] * Zhangmude[7] * Zhangmude[5] == 0) && (Zhangmude[3] * Zhangmude[5] * Zhangmude[7] == 0))
                            {
                                deletelist1.push_back(Point(i, j));
                            }
                        }
                    }
                }
            }
        }
        if (deletelist1.size() == 0) break;
        for (size_t i = 0; i < deletelist1.size(); i++)
        {
            Point tem;
            tem = deletelist1[i];
            uchar* data = srcimage.ptr<uchar>(tem.y);
            data[tem.x] = 0;
        }
        deletelist1.clear();

        for (int j = 1; j < (nl - 1); j++)
        {
            uchar* data_last = srcimage.ptr<uchar>(j - 1);
            uchar* data = srcimage.ptr<uchar>(j);
            uchar* data_next = srcimage.ptr<uchar>(j + 1);
            for (int i = 1; i < (nc - 1); i++)
            {
                if (data[i] == 255)
                {
                    Zhangmude[0] = 1;
                    if (data_last[i] == 255) Zhangmude[1] = 1;
                    else  Zhangmude[1] = 0;
                    if (data_last[i + 1] == 255) Zhangmude[2] = 1;
                    else  Zhangmude[2] = 0;
                    if (data[i + 1] == 255) Zhangmude[3] = 1;
                    else  Zhangmude[3] = 0;
                    if (data_next[i + 1] == 255) Zhangmude[4] = 1;
                    else  Zhangmude[4] = 0;
                    if (data_next[i] == 255) Zhangmude[5] = 1;
                    else  Zhangmude[5] = 0;
                    if (data_next[i - 1] == 255) Zhangmude[6] = 1;
                    else  Zhangmude[6] = 0;
                    if (data[i - 1] == 255) Zhangmude[7] = 1;
                    else  Zhangmude[7] = 0;
                    if (data_last[i - 1] == 255) Zhangmude[8] = 1;
                    else  Zhangmude[8] = 0;
                    int whitepointtotal = 0;
                    for (int k = 1; k < 9; k++)
                    {
                        whitepointtotal = whitepointtotal + Zhangmude[k];
                    }
                    if ((whitepointtotal >= 2) && (whitepointtotal <= 6))
                    {
                        int ap = 0;
                        if ((Zhangmude[1] == 0) && (Zhangmude[2] == 1)) ap++;
                        if ((Zhangmude[2] == 0) && (Zhangmude[3] == 1)) ap++;
                        if ((Zhangmude[3] == 0) && (Zhangmude[4] == 1)) ap++;
                        if ((Zhangmude[4] == 0) && (Zhangmude[5] == 1)) ap++;
                        if ((Zhangmude[5] == 0) && (Zhangmude[6] == 1)) ap++;
                        if ((Zhangmude[6] == 0) && (Zhangmude[7] == 1)) ap++;
                        if ((Zhangmude[7] == 0) && (Zhangmude[8] == 1)) ap++;
                        if ((Zhangmude[8] == 0) && (Zhangmude[1] == 1)) ap++;
                        if (ap == 1)
                        {
                            if ((Zhangmude[1] * Zhangmude[3] * Zhangmude[5] == 0) && (Zhangmude[3] * Zhangmude[1] * Zhangmude[7] == 0))
                            {
                                deletelist1.push_back(Point(i, j));
                            }
                        }
                    }
                }
            }
        }
        if (deletelist1.size() == 0) break;
        for (size_t i = 0; i < deletelist1.size(); i++)
        {
            Point tem;
            tem = deletelist1[i];
            uchar* data = srcimage.ptr<uchar>(tem.y);
            data[tem.x] = 0;
        }
        deletelist1.clear();
    }
}

//排序函数
bool cmpy_y(cv::Point const& a, cv::Point const& b)
{
    return a.y < b.y;
}
bool cmpy_x(cv::Point const& a, cv::Point const& b)
{
    return a.x < b.x;
}
//包含带边框的
const char * BoundingBox(Mat &srcImg,char* m_name)
{
    if (srcImg.empty())
    {
        return "failer";
    }
    else
    {
        Mat dstImage;
        Mat tempImage = srcImg.clone();
        //GaussianBlur(srcImg,srcImg,Size(5,5),0,0); //高斯滤波
        medianBlur(srcImg, dstImage, 3);//中值滤波
        cvtColor(dstImage, dstImage, CV_RGB2GRAY);
        threshold(dstImage, dstImage, 100, 255, CV_THRESH_BINARY_INV);
        chao_thinimage(dstImage);
        vector<vector<Point>> contours;
        vector<Vec4i> hierarcy;
        findContours(dstImage, contours, hierarcy, CV_RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); //查找轮廓
        vector<Rect> boundRect(contours.size()); //定义外接矩形集合
        int x0 = 0, y0 = 0, w0 = 0, h0 = 0;
        for (int i = 0; i < contours.size(); i++)
        {
            boundRect[i] = boundingRect((Mat)contours[i]); //查找每个轮廓的外接矩形
            drawContours(srcImg, contours, i, Scalar(0, 0, 255), 2, 8);  //绘制轮廓
            x0 = boundRect[i].x;  //获得第i个外接矩形的左上角的x坐标
            y0 = boundRect[i].y; //获得第i个外接矩形的左上角的y坐标
            w0 = boundRect[i].width; //获得第i个外接矩形的宽度
            h0 = boundRect[i].height; //获得第i个外接矩形的高度
            if (w0*h0 > 10000)
            {
                rectangle(srcImg, Point(x0, y0), Point(x0 + w0, y0 + h0), Scalar(0, 255, 0), 2, 8); //绘制第i个外接矩形
                Mat ImageRoi(tempImage, Rect(x0, y0, w0, h0));
                //imshow("ROI", ImageRoi);
                imwrite(m_name, ImageRoi);
            }
        }
        return "success";
    }
}
//不带边框
const char * NoBox(Mat &srcImg,char *m_name)
{
    if (srcImg.empty())
    {
        return "failer";
    }
    else
    {
        Mat dstImg;
        cvtColor(srcImg, dstImg, CV_BGR2GRAY);
        Mat bw;
        adaptiveThreshold(~dstImg, bw, 255, CV_ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
        //chao_thinimage(bw);
        //imshow("bw", bw);
        Mat horizontal = bw.clone();
        Mat vertical = bw.clone();
        int scale = 20; //这个值越大,检测到的直线越多
        int horizontalsize = horizontal.cols / scale;
        // 为了获取横向的表格线,设置腐蚀和膨胀的操作区域为一个比较大的横向直条
        Mat horizontalStructure = getStructuringElement(MORPH_RECT, Size(horizontalsize, 1));
        // 先腐蚀再膨胀
        erode(horizontal, horizontal, horizontalStructure, Point(-1, -1));
        dilate(horizontal, horizontal, horizontalStructure, Point(-1, -1));
        int verticalsize = vertical.rows / scale;
        Mat verticalStructure = getStructuringElement(MORPH_RECT, Size(1, verticalsize));
        erode(vertical, vertical, verticalStructure, Point(-1, -1));
        dilate(vertical, vertical, verticalStructure, Point(-1, -1));
        Mat mask = horizontal + vertical;
        chao_thinimage(horizontal);
        chao_thinimage(vertical);
        Mat joints;
        bitwise_and(horizontal, vertical, joints);
        vector<Point> temp;
        vector<Point> endtemp;
        Point start;
        //寻找左上角点
        for (int i = 0; i < joints.rows; i++)
        {
            uchar *data = joints.ptr<uchar>(i);
            for (int j = 0; j < joints.cols; j++)
            {
                if (data[j] == 255 && data[j - 1] == 0)
                {
                    start.x = j;
                    start.y = i;
                    temp.push_back(start);
                    endtemp.push_back(start);
                }
            }
        }
        sort(temp.begin(), temp.end(), cmpy_x);
        sort(endtemp.begin(), endtemp.end(), cmpy_y);
        int x0 = temp[0].x + 2;
        int y0 = temp[0].y + 2;
        int width = temp[temp.size() - 1].x - temp[0].x - 2;
        int height = endtemp[endtemp.size() - 1].y - endtemp[0].y - 2;
        if (width <= srcImg.cols - x0 && height <= srcImg.rows - y0)
        {
            Mat ROI(srcImg, Rect(x0, y0, width, height));
            //imshow("ROI", ROI);
            imwrite(m_name,ROI);
            return "success";
        }
        else
        {
            return "failer";
        }
    }
}
const char *  _stdcall DetectionBox(char *name,int flag)
{
    Mat temp = imread(name);
    if (flag == 1)
    {
        return BoundingBox(temp,name);
    }
    else if (flag == 2)
    {
        return NoBox(temp,name);
    }
    else
    {
        return "flag is empty";
    }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值