软件杯赛题——工商营业执照的切割和识别

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <algorithm>
#include <iterator>
#include <vector>
#include <math.h>
#include <vector>
#include <assert.h>
#include <string.h>
#include <dirent.h>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>
#include "classification.cpp"
using namespace std;
using namespace cv;

//hanshu shengming
class Cuter
{
public:
Cuter();
Mat newThreshold(Mat img);

vector<RotatedRect> findTextRegion(Mat img);

int  detect(Mat tmp,int type,int &title_right);
//将部分图片切成行
bool vcut(Mat srcImage,char *name);

Mat append(Mat src);

Mat hcut_spare(Mat srcImage);

bool hcut_big(Mat srcImage,char *name);

bool hcut_small();

bool hcut_title();

Mat preprocess(Mat gray,int type);

bool findtitle_cut(Mat src,char *name);

//void linecut(Mat img,char *name,int lineRank,int ranks);

bool hcut_search(Mat srcImage,char *name,int lineRank);

bool hcut_digit_single(Mat roiImg);

Mat merge(Mat leftImg,Mat rightImg);

void digit_classify();

void word_classify(int avg_width);

void linecut(int avg_width);

bool isDigit(string result)
{
	if(result=="1"||result=="2"||result=="3"||result=="0"||result=="4"||result=="5"||result=="6"||result=="7"||result=="8"||result=="9"||result=="0")
	return true;
	else return false;
}

void show()
{
	cout<<"数字的行数 "<<digit_line<<endl;
	for(int i=0;i<singleList.size();i++)
	{
		char savePath[64];
		sprintf(savePath,"singleList/%d.png",tmpRank++);
		imwrite(savePath,singleList[i]);
	}
}

void writeClassifyList()
{
	for(int i=0;i<classifyList.size();i++)
	{
		char savePath[64];
		sprintf(savePath,"classifyList/%d.png",tmpRank2++);
		imwrite(savePath,classifyList[i]);
	}
}

bool printResult(char *picName,bool isSuccess)
{
	int cutPos=0;
	for(int i=strlen(picName);i>=0;i--)
	{
		if(picName[i]=='/')
		{	
			cutPos=i;
			break;
		}
	}
	string name;
	for(int i=cutPos+1;i<strlen(picName);i++)
	{
		name+=picName[i];
	}


	FILE *fpRead=fopen("result_two","a");
	if(digitResult.size()<=12||wordResult.size()<=0||!isSuccess)
	{
		string tmpResult;
		tmpResult=tmpResult+name+" 识别错误  识别错误";
		//out<<name<<" 识别错误 "<<"识别错误"<<endl;
		char saveResult[256];
		strcpy(saveResult,tmpResult.c_str());
		fprintf(fpRead,"%s\n",saveResult);
		fclose(fpRead);
		return false;
	}
	string tmpResult;
	char saveResult[256];
	string digitAll;
	for(int i=0;i<digitResult.size();i++)
	{
		string result=digitResult[i];
		digitAll+=result;
		/*
		if(result=="A"||result=="B"||result=="C"||result=="D"||result=="E"||result=="F"||result=="G"||result=="H"||result=="I"||result=="J"||result=="K"||result=="L"||result=="M"||result=="N"||result=="O"||result=="P"||result=="Q"||result=="R"||result=="S"||result=="T"||result=="V"||result=="U"||result=="W"||result=="X"||result=="Y"||result=="Z")break;
		*/
		
	}
	cout<<digitAll<<endl;
	string wordAll;
	int endPos=0;
	string add;
	
	for(int i=0;i<wordResult.size();i++)
	{
		string result=wordResult[i];
		if(result=="有")
		{
			add="有限公司";
			endPos=i-1;
			break;
		}
		if(result=="限")
		{
			add="限公司";
			endPos=i-2;
			break;
		}
		if(result=="公")
		{
			add="公司";
			endPos=i-3;
			break;
		}
		if(result=="司")
		{
			add="司";
			endPos=i-4;
			break;
		}
		if(result=="厂")
		{
			add="厂";
			endPos=i-1;
			break;
		}
	}
	if(endPos<0)
	{
		//cout<<"识别矫正错误"<<endl;
		return false;
	}
	for(int i=0;i<=endPos;i++)
	{
		string result=wordResult[i];
		wordAll+=result;
	}
	wordAll+=add;
	cout<<wordAll<<endl;
	tmpResult=tmpResult+name+" "+digitAll+" "+wordAll;
	strcpy(saveResult,tmpResult.c_str());
	fprintf(fpRead,"%s\n",saveResult);
	fclose(fpRead);
	return true;
}

Mat myRotate(Mat src,int rotateType)
{
	if(rotateType==1)
	{
		// 矩阵转置
		transpose(src, src);
		//0: 沿X轴翻转; >0: 沿Y轴翻转; <0: 沿X轴和Y轴翻转
		flip(src, src, 1);// 翻转模式,flipCode == 0垂直翻转(沿X轴翻转),flipCode>0水平翻转(沿Y轴翻转),flipCode<0水平垂直翻转(先沿X轴翻转,再沿Y轴翻转,等价于旋转180°)
		return src;
	}
	else if(rotateType==2)
	{
		//0: 沿X轴翻转; >0: 沿Y轴翻转; <0: 沿X轴和Y轴翻转
    		flip(src, src, 0);// 翻转模式,flipCode == 0垂直翻转(沿X轴翻转),flipCode>0水平翻转(沿Y轴翻转),flipCode<0水平垂直翻转(先沿X轴翻转,再沿Y轴翻转,等价于旋转180°)
    		flip(src, src, 1);
    		return src;
	}
	else if(rotateType==3)
	{
		transpose(src, src);// 翻转模式,flipCode == 0垂直翻转(沿X轴翻转),flipCode>0水平翻转(沿Y轴翻转),flipCode<0水平垂直翻转(先沿X轴翻转,再沿Y轴翻转,等价于旋转180°)
    		flip(src, src, 0);
    		return src;
	}
	return src;
}

Mat quzao(Mat src);

void tmplinecut(int avg_width);

Mat getVcutImg()
{
	return vcutImg;
}
private:
	vector<double> rateList;
	Mat vcutImg;
	int classifyRank;
	int imageType; //图片类型
	int digit_line;
	bool isFirstDigitLine;
	bool isFirstWordLine;
	bool hasFindWordLine;
	int word_line;
	int currentLine;
	int currentSingle;
	int lineDigitNum;
	int maxLineDigitNum;
	vector<Mat> lineList;
	vector<Mat> preLineList;
	vector<Mat> singleList;
	vector<Mat> classifyList;
	vector<string> digitResult;
	vector<string> wordResult;
	Classifier *allClassifier;
	Classifier *digitClassifier;
	int tmpRank;
	int tmpRank2;
	int avg_word_width;
	/*
type 0 height>width
     1 width>height && title on the left
     2 width>height && title on the center
  */

};


Cuter::Cuter()
{
	 hasFindWordLine=false;
	tmpRank=0;
	tmpRank2=0;
	isFirstDigitLine=true;
	isFirstWordLine=true;
	maxLineDigitNum=0;
	classifyRank=0;
	imageType=-1;
	digit_line=-1;
	word_line=-1;
	currentLine=0;
	currentSingle=0;
	string model_file="45-word-new/lenet.prototxt";
	string trained_file="45-word-new/lenet_solver_iter_405000.caffemodel";
	string label_file="45-word-new/label";
	//初始化分类器
	allClassifier=new Classifier(model_file, trained_file, label_file);
	
	model_file="45-digit-model/lenet.prototxt";
	trained_file="45-digit-model/lenet_solver_iter_45000.caffemodel";
	label_file="45-digit-model/label";
	digitClassifier=new Classifier(model_file,trained_file,label_file);
}

Mat Cuter::newThreshold(Mat img)
{
int pixcount=0;
int height=img.rows;
int width=img.cols;
for(int i=0;i<height;i++)
{
	for(int j=0;j<width;j++)
	{
		pixcount+=img.at<uchar>(i,j);
	}
}
int avg_pix=(pixcount)/(height*width);
//cout<<avg_pix<<endl;
threshold(img,img,avg_pix-10,255,CV_THRESH_BINARY);
return img;
}

Mat Cuter::preprocess(Mat gray,int type)
{
    //1.Sobel算子,x方向求梯度
    Mat sobel;
    Sobel(gray, sobel, CV_8U, 2, 1, 5);

    //2.二值化
    Mat binary;
   // threshold(sobel, binary, 0, 255, THRESH_OTSU + THRESH_BINARY);
    //imwrite("binary.png",sobel);
    
     //3.膨胀和腐蚀操作核设定
    Mat element1,element2;
    if(type==0)
    {
    	  element1 = getStructuringElement(MORPH_RECT, Size(40, 5));
   	 //控制高度设置可以控制上下行的膨胀程度,例如3比4的区分能力更强,但也会造成漏检
    	  element2 = getStructuringElement(MORPH_RECT, Size(45,3));
    }
    else
    {
    	
   	element1 = getStructuringElement(MORPH_RECT, Size(65, 10));
    	//控制高度设置可以控制上下行的膨胀程度,例如3比4的区分能力更强,但也会造成漏检
    	element2 = getStructuringElement(MORPH_RECT, Size(40,4));
    }
    //4.膨胀一次,让轮廓突出
    Mat dilate1;
    dilate(sobel, dilate1, element2);

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

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

    //7.存储中间图片
 return dilate2;
}


vector<RotatedRect> Cuter::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++)
    {
    	//cout<<"contours.size "<<contours.size()<<endl;
        //计算当前轮廓的面积
        double area = contourArea(contours[i]);

        //面积小于1000的全部筛选掉
        
        if (area < 2000)
            continue;
	
        //轮廓近似,作用较小,approxPolyDP函数有待研究
        double epsilon = 0.001*arcLength(contours[i], true);
        Mat approx;
        approxPolyDP(contours[i], approx, epsilon, true);

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

        //计算高和宽
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值