OpenCV 图片数字识别(C++)

下面是用C++来实现的

该算法的过程与上述相同,但该算法只使用第一层次的等高线,因此算法只对每一个数字使用相同的外部轮廓。

创建示例和标签数据的代码

#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/types_c.h>
using namespace std;
using namespace cv;

int main()
{
	//Process image to extract contour
	Mat thr, gray, con;
	Mat src = imread("digit.png", 1);
	cvtColor(src, gray, CV_BGR2GRAY);
	threshold(gray, thr, 200, 255, THRESH_BINARY_INV); //Threshold to find contour
	thr.copyTo(con);

	// Create sample and label data
	vector< vector <Point> > contours; // Vector for storing contour
	vector< Vec4i > hierarchy;
	Mat sample;
	Mat response_array;
	findContours( con, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE ); //Find contour

	for ( int i = 0; i < contours.size(); i = hierarchy[i][0] ) // iterate through first hierarchy level contours
	{
		Rect r = boundingRect(contours[i]); //Find bounding rect for each contour
		rectangle(src, Point(r.x, r.y), Point(r.x + r.width, r.y + r.height), Scalar(0, 0, 255), 2, 8, 0);
		Mat ROI = thr(r); //Crop the image
		Mat tmp1, tmp2;
		resize(ROI, tmp1, Size(10, 10), 0, 0, INTER_LINEAR ); //resize to 10X10
		tmp1.convertTo(tmp2, CV_32FC1); //convert to float
		sample.push_back(tmp2.reshape(1, 1)); // Store  sample data
		imshow("src", src);
		int c = waitKey(0); // Read corresponding label for contour from keyoard
		c -= 0x30;   // Convert ascii to intiger value
		response_array.push_back(c); // Store label to a mat
		rectangle(src, Point(r.x, r.y), Point(r.x + r.width, r.y + r.height), Scalar(0, 255, 0), 2, 8, 0);
	}
	// Store the data to file
	Mat response, tmp;
	tmp = response_array.reshape(1, 1); //make continuous
	tmp.convertTo(response, CV_32FC1); // Convert  to float
	FileStorage Data("TrainingData.yml", FileStorage::WRITE); // Store the sample data in a file
	Data << "data" << sample;
	Data.release();
	FileStorage Label("LabelData.yml", FileStorage::WRITE); // Store the label data in a file
	Label << "label" << response;
	Label.release();
	cout << "Training and Label data created successfully....!! " << endl;
	imshow("src", src);
	waitKey();
	return 0;
}

训练和测试

#include <opencv2/opencv.hpp>
#include <opencv2/ml.hpp>
#include <opencv2/imgproc/types_c.h>
using namespace std;
using namespace cv;

int main()
{
	Mat thr, gray, con;
	Mat src = imread("dig.png", 1);
	// imshow("src", src);
	// waitKey(10000);

	cvtColor(src, gray, CV_BGR2GRAY);
	threshold(gray, thr, 200, 255, THRESH_BINARY_INV); // Threshold to create input
	thr.copyTo(con);


	// Read stored sample and label for training
	Mat sample;
	Mat response, tmp;
	FileStorage Data("TrainingData.yml", FileStorage::READ); // Read traing data to a Mat
	Data["data"] >> sample;
	Data.release();

	FileStorage Label("LabelData.yml", FileStorage::READ); // Read label data to a Mat
	Label["label"] >> response;
	Label.release();


	// ml::KNearest knn;
	cv::Ptr<cv::ml::KNearest> knn = cv::ml::KNearest::create();
	knn->train(sample, ml::ROW_SAMPLE, response); // Train with sample and responses
	cout << "Training compleated.....!!" << endl;

	vector< vector <Point> > contours; // Vector for storing contour
	vector< Vec4i > hierarchy;

	//Create input sample by contour finding and cropping
	findContours(con, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
	Mat dst(src.rows, src.cols, CV_8UC3, Scalar::all(0));


	for ( int i = 0; i < contours.size(); i = hierarchy[i][0] ) // iterate through each contour for first hierarchy level .
	{
		Rect r = boundingRect(contours[i]);
		if (r.height > 50)
			continue;
		if (r.height < 5)
			continue;
		Mat ROI = thr(r);
		Mat tmp1, tmp2;
		resize(ROI, tmp1, Size(10, 10), 0, 0, INTER_LINEAR );
		tmp1.convertTo(tmp2, CV_32FC1);
		cv::Mat result;
		knn->findNearest(tmp2.reshape(1, 1), 5, result);

		float p = ((float *)result.data)[0];
		int value = (int)p;
		if (value >= 0 && value < 10) {
			char name[4];
			sprintf(name, "%d", value);
			putText(dst, name, Point(r.x, r.y + r.height) , 0, 1, Scalar(0, 255, 0), 2, 8 );
			// imshow("dst", dst);
			// waitKey(500);
		}
	}
	imshow("src", src);
	imshow("dst", dst);
	imwrite("dest.jpg", dst);
	waitKey(10000);
	return 0;
}

结果

结果,第一行中的点被检测为8,而我们还没有对点进行训练。此外,我也考虑了每一个等高线在第一层次作为样本输入,用户可以通过计算面积避免它。

 

要在Java中使用OpenCV识别数字,您需要完成以下步骤: 1.安装OpenCV库:下载OpenCV的Java库并将其添加到您的项目中。 2.准备训练数据集:您需要准备一个包含数字图像的数据集,这些数字图像应该是已知标签的。 3.训练模型:使用OpenCV的机器学习库训练模型以识别数字。您可以使用支持向量机(SVM)或人工神经网络(ANN)等算法。 4.测试模型:对于测试数据集中的每个数字图像,使用训练好的模型进行识别并比较其预测结果和真实标签。 下面是一个简单的Java示例代码,演示如何使用OpenCV识别数字: ```java import org.opencv.core.*; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.ml.*; import java.util.ArrayList; import java.util.List; public class DigitRecognizer { public static void main(String[] args) { // Load training data Mat digits = new Mat(); Mat labels = new Mat(); List<Mat> digitList = new ArrayList<>(); for (int i = 0; i < 10; i++) { for (int j = 0; j < 500; j++) { Mat digit = Imgcodecs.imread("digit_data/" + i + "_" + j + ".png", Imgcodecs.IMREAD_GRAYSCALE); digitList.add(digit); labels.push_back(new Mat(1, 1, CvType.CV_32SC1, new Scalar(i))); } } Core.merge(digitList, digits); // Train SVM SVM svm = SVM.create(); svm.setType(SVM.C_SVC); svm.setKernel(SVM.RBF); svm.setGamma(0.5); svm.setC(10.0); svm.train(digits, Ml.ROW_SAMPLE, labels); // Load test data Mat testDigits = new Mat(); Mat testLabels = new Mat(); List<Mat> testDigitList = new ArrayList<>(); for (int i = 0; i < 10; i++) { for (int j = 500; j < 1000; j++) { Mat digit = Imgcodecs.imread("digit_data/" + i + "_" + j + ".png", Imgcodecs.IMREAD_GRAYSCALE); testDigitList.add(digit); testLabels.push_back(new Mat(1, 1, CvType.CV_32SC1, new Scalar(i))); } } Core.merge(testDigitList, testDigits); // Test SVM Mat results = new Mat(); svm.predict(testDigits, results, 0); // Evaluate results int correct = 0; for (int i = 0; i < testLabels.rows(); i++) { if (testLabels.get(i, 0)[0] == results.get(i, 0)[0]) { correct++; } } double accuracy = (double) correct / testLabels.rows() * 100; System.out.println("Accuracy: " + accuracy + "%"); } } ``` 此代码加载包含数字图像的训练数据集,并使用SVM算法训练模型。然后,它加载包含数字图像的测试数据集,并使用训练好的模型对其进行分类。最后,它评估结果并输出分类准确度。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值