用opencv svm 折腾的识别程序

版权声明:本文为博主原创文章,转载注明出处。 https://blog.csdn.net/pengjc2001/article/details/62036476

前面有过用halcon识别字符,现在用opencv折腾下。比较一下

排除svm算法的问题,对我们来说就是构建合适的分类数据, 在这还是采用《Mastering OpenCV with Practical Computer Vision》中说的 水平方向字符投影 + 竖直方向字符投影 + 缩小后的字符像素信息矩阵(把它平铺)

将所有16个字符的信息 放在 一个 2维矩阵中  16X (characterOriginalWidth + characterOriginalHeight + characterWidth*characterHeight) 大小

还有需要注意的是 顺序, 找到的轮廓顺序不一定是你相应的分类顺序


#include "stdafx.h"
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/imgcodecs.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp>
#include <vector>
#include <string>
#include <sstream>
#define HORIZONTAL 1
#define VERTICAL 0

#define characterOriginalWidth 58
#define characterOriginalHeight 120
#define characterWidth 5
#define characterHeight 10
#define testCount 16

using namespace cv;
using namespace cv::ml;
using std::vector;
using std::string;


Mat ProjectedHistogram(Mat img, int t)
{
	int sz = (t) ? img.rows : img.cols;
	Mat mhist = Mat::zeros(1, sz, CV_32F);
	for (int j = 0; j < sz; j++)
	{
		Mat data = (t) ? img.row(j) : img.col(j);
		mhist.at<float>(j) = countNonZero(data);
	}
	//Normalize histogram
	double min, max;
	minMaxLoc(mhist, &min, &max);
	if (max > 0)
		mhist.convertTo(mhist, -1, 1.0f / max, 0);
	return mhist;
}

Mat features(Mat in, int sizeData_X, int sizeData_Y)
{
	Mat vhist = ProjectedHistogram(in, VERTICAL);
	Mat hhist = ProjectedHistogram(in, HORIZONTAL);

	Mat lowData;
	resize(in, lowData, Size(sizeData_X, sizeData_Y));
	int numCols = vhist.cols + hhist.cols + lowData.rows*lowData.cols;
	Mat out = Mat::zeros(1, numCols, CV_32F);

	int j = 0;
	for (int i = 0; i < vhist.cols; i++)
	{
		out.at<float>(j) = vhist.at<float>(i);
		j++;
	}
	for (int i = 0; i < hhist.cols; i++)
	{
		out.at<float>(j) = hhist.at<float>(i);
		j++;
	}
	for (int y = 0; y<lowData.rows; y++)
	{
		for (int x = 0; x<lowData.cols; x++)
		{
			out.at<float>(j) = (float)lowData.at<unsigned char>(y, x);
			j++;
		}
	}
	return out;
}

bool SortByIndex(Rect i, Rect j)
{ 
	return (i.x<j.x); 	
}

int main()
{
	char res[20];
	vector<string> letters{"0","1","2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" };
	Mat img = imread("D:\\Visual Studio 2015\\Projects\\numbers\\Debug\\1.bmp", CV_LOAD_IMAGE_GRAYSCALE);
	imshow("输入原图像", img);
	Mat binaryImg, meanImg, contoursImg(img.size(), CV_8U, Scalar(255));
	
	GaussianBlur(img, meanImg, Size(5, 19), 0, 0);
	threshold(meanImg,binaryImg,200,255,CV_THRESH_BINARY_INV);
	vector<vector<Point>> contours;
	findContours(binaryImg,contours,CV_RETR_EXTERNAL,CHAIN_APPROX_NONE);
	drawContours(contoursImg, contours, -1, Scalar(0), 3);
	
	int numCols = characterOriginalWidth + characterOriginalHeight + characterWidth*characterHeight;

	Mat data = Mat::zeros(testCount, numCols, CV_32FC1);   //预先产生一个 testCount X 2 的矩阵
	
	Mat labels = Mat::zeros(testCount, 1, CV_32SC1);

	// Draw blue contours on a white image  
	cv::Mat result;
	img.copyTo(result);
	cvtColor(result, result, CV_GRAY2RGB);

	vector<vector<Point> >::iterator itc = contours.begin();
	vector<cv::Rect>  contoursRect;
	
	 
	//构建轮廓的最小矩形
	while (itc != contours.end()) 
	{
		Rect mr = boundingRect(Mat(*itc));
		contoursRect.push_back(mr);
		++itc;
	}
	//最小矩形轮廓按左上角的x值由小到达排序为了和分类顺序对应
	sort(contoursRect.begin(),contoursRect.end(), SortByIndex);
	vector<Rect> ::iterator itcontoursRect = contoursRect.begin();
	int i = 0;
	while (itcontoursRect != contoursRect.end())
	{
		//用矩形切割图像
		Mat auxRoi(img, *itcontoursRect);
		sprintf_s(res, "train_data_%d.jpg", i);		
		//把分割好的图像统一大小(characterOriginalWidth * characterOriginalHeight)
		resize(auxRoi, auxRoi, Size(characterOriginalWidth, characterOriginalHeight));
		imwrite(res, auxRoi);
		rectangle(result, *itcontoursRect, Scalar(0, 0, 255), 2);					
		Mat f = features(auxRoi, characterWidth, characterHeight);
		f.row(0).copyTo(data.row(i));
		labels.at<int>(i, 0) = i;
		++itcontoursRect;
		i++;
	}
	imshow("矩形分割后的输入原图像", result);

	Ptr<SVM> svm = SVM::create();
	svm->setType(SVM::C_SVC);
	svm->setKernel(SVM::LINEAR);
	svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));
	svm->train(data, ROW_SAMPLE, labels);


	Mat imgPredict = imread("D:\\Visual Studio 2015\\Projects\\numbers\\Debug\\2.bmp", CV_LOAD_IMAGE_GRAYSCALE);
	Mat binaryImgPredict, meanImgPredict, contoursImgPredict(img.size(), CV_8U, Scalar(255));
	imshow("需要预测的图像", imgPredict);
	GaussianBlur(imgPredict, meanImgPredict, Size(5, 19), 0, 0);
	threshold(meanImgPredict, binaryImgPredict, 200, 255, CV_THRESH_BINARY_INV);
	vector<vector<Point>> contoursPredict;
	findContours(binaryImgPredict, contoursPredict, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE);
	drawContours(contoursImgPredict, contoursPredict, -1, Scalar(0), 3);		

	vector<vector<Point> >::iterator itcPredict = contoursPredict.begin();
	     
	Mat imgPredicted(imgPredict.size().height, imgPredict.size().width,CV_8UC3,Scalar(255,255,255));
	while (itcPredict != contoursPredict.end())
	{
		Rect mr = boundingRect(Mat(*itcPredict));
		Point point(mr.x, 80);
		Mat auxRoi(imgPredict, mr);
		resize(auxRoi, auxRoi, Size(characterOriginalWidth, characterOriginalHeight));
		Mat f = features(auxRoi, characterWidth, characterHeight);
		float response = svm->predict(f);
		++itcPredict;
		int index = response;
		putText(imgPredicted, letters[index], point, CV_FONT_HERSHEY_SIMPLEX, 1, Scalar(255,0,0));
		
	}
	
	imshow("预测结果", imgPredicted);
	waitKey(0);
    return 0;
}


猜你喜欢

转载自blog.csdn.net/pengjc2001/article/details/62036476
今日推荐