// 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";
}
}
票据预处理(二)
最新推荐文章于 2024-07-26 16:45:27 发布