1.准备训练数据与标签
2.训练SVM模型、保存
//训练SVM分类器
void TrainSVM()
{
Mat train_img = new Mat(@"C:\\Users\\HJ\\Desktop\\OCR.bmp");
Mat traindata = new Mat();
Mat trainlabel = new Mat();
//------------------------图像预处理-------------------------------
Mat graymat = new Mat();
Cv2.CvtColor(train_img,graymat,ColorConversionCodes.BGR2GRAY); //转灰度图
//Cv2.ImShow("gray_img",graymat);
Mat blurImg = new Mat();
Cv2.GaussianBlur(graymat,blurImg,new OpenCvSharp.Size(5,5),0); //高斯滤波
//Cv2.ImShow("blurImg", blurImg);
Mat _dilate = new Mat();
Mat element = Cv2.GetStructuringElement(MorphShapes.Rect,new OpenCvSharp.Size(11,11),new CVPoint(-1,-1));
Cv2.Erode(graymat, _dilate, element); //形态学处理-腐蚀
//Cv2.ImShow("_dilate", _dilate);
Mat binImg = new Mat();
Cv2.Threshold(_dilate, binImg,0,255,ThresholdTypes.BinaryInv|ThresholdTypes.Otsu); //二值化
//Cv2.ImShow("binImg", binImg);
CVPoint[][] contours = new CVPoint[][] { };
HierarchyIndex[] hierarchy = new HierarchyIndex[] { };
Cv2.FindContours(binImg,out contours, out hierarchy,RetrievalModes.External,ContourApproximationModes.ApproxSimple); //提取字符
List<int> labels = new List<int>() { 51894, 45794, 45552,51924,47099,55254};//汉字国标码十六进制转十进制
for (int i = 0; i < contours.Length; i++)
{
if (Cv2.ContourArea(contours[i])>10)
{
Rect rect = Cv2.BoundingRect(contours[i]);
Cv2.Rectangle(train_img,rect,new Scalar(0,255,0),2);
Mat ROI = new Mat(train_img,rect);
Cv2.ImShow($"ROI{i}", ROI);
;
Mat resizemat = new Mat();
Cv2.Resize(ROI, resizemat, new OpenCvSharp.Size(30,30)); //统一单个字符图像大小
Mat _floatmat = new Mat();
resizemat.ConvertTo(_floatmat,MatType.CV_32FC1);//traindata接收CV_32FC1,数据转换
traindata.PushBack(_floatmat.Reshape(1,1)); //添加训练数据
trainlabel.PushBack(labels[i]); //添加对应的标签
}
}
traindata.ConvertTo(traindata,MatType.CV_32FC1);
trainlabel.ConvertTo(trainlabel,MatType.CV_32SC1); //SVM接收的标签数据类型为CV_32SC1
SVM sVM = SVM.Create(); //创建SVM
sVM.Type = SVM.Types.CSvc; //设定type
sVM.KernelType = SVM.KernelTypes.Linear; //设定内核type
sVM.Train(traindata,SampleTypes.RowSample,trainlabel); //训练
sVM.Save("model.xml"); //保存模型
}
3.加载SVM模型、预测验证模型
void Predict()
{
Mat test_Img = new Mat("C:\\Users\\HJ\\Desktop\\TestOCR.bmp"); //读取测试图像
SVM svm = SVM.Load("model.xml");
//图像预处理
Mat graymat = new Mat();
Cv2.CvtColor(test_Img, graymat, ColorConversionCodes.BGR2GRAY); //转灰度图
Mat blurImg = new Mat();
Cv2.GaussianBlur(graymat, blurImg, new OpenCvSharp.Size(5, 5), 0); //高斯滤波
Mat _dilate = new Mat();
Mat element = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(13, 11), new CVPoint(-1, -1));
Cv2.Erode(graymat, _dilate, element); //腐蚀
Mat binImg = new Mat();
Cv2.Threshold(_dilate, binImg, 200, 255, ThresholdTypes.BinaryInv); //二值化
CVPoint[][] contours = new CVPoint[][] { };
HierarchyIndex[] hierarchy = new HierarchyIndex[] { };
Cv2.FindContours(binImg, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple); //提取字符
for (int i = 0; i < contours.Length; i++)
{
Rect rect = Cv2.BoundingRect(contours[i]);
Cv2.Rectangle(test_Img,rect,new Scalar(0,0,255),2);
Mat ROI = new Mat(test_Img,rect);
Mat resize = new Mat();
Cv2.Resize(ROI,resize,new OpenCvSharp.Size(30,30)); //统一每个字符的图像大小
Mat roifloat = new Mat();
resize.ConvertTo(roifloat,MatType.CV_32FC1);
roifloat = roifloat.Reshape(1,1);
float f = svm.Predict(roifloat); //预测字符
string character = "";
//转汉字
string hanzi = "";
string s = ((int)f).ToString("X");
byte[] b = strToToHexByte(s);
hanzi = GBCode2Chinese2GBCode.BytesToString(b);
switch (f) //Cv2.PutText()无法显示中文,暂时用拼音代替
{
case 47099:
character = "fu";
break;
case 55254:
character = "zi";
break;
case 51894:
character = "shi";
break;
case 45552:
character = "bie";
break;
case 45794:
character = "ce";
break;
case 51924:
character = "shi";
break;
default:
character = "NUll";
break;
}
double scale = rect.Width * 0.02;
Cv2.PutText(test_Img, character, rect.BottomRight,HersheyFonts.HersheySimplex,scale,new Scalar(0,255,0),2);
Cv2.ImShow("test_img",test_Img);
}
预测结果: