摄像头识别手写数字

          最近在做一个项目主要是团队要做一个机器人,其中有个功能就是机器人能够坐电梯。为了实现这个功能首先就得识别电梯上的按钮,并识别出上面的数字,以便选择楼层。

       首先我想到的是手写数字的识别,虽然电梯上的按钮的数字是印刷体,可是如果能够识别手写数字,印刷体自然不在话下。

       一开始着手时,我想到的是先给出样本模版,当给定一个数字时,在所给定的模版中逐一通过像素去比对,找出最相近的模版,并返回这个模版的数值标签,这个标签就是这个数字的值。事与愿违,由于手写数字千变万化,比如6,8,9这3个数字在进行像素比对时,所给测试数字由于大小形状问题,造成容易搞混的的情况。

       在查找了许多资料后,发现有几个方法去实现。基本都是特征点加上分类器,或者神经网络去解决。

       我选择了HOG特征+KNN的方法的实现这一功能。

       结果还是不错的的,识别率在90%以上。如果改为印刷体我相信识别率可以很轻松达到99%,虽然我没有去测试印刷体,可是印刷体比较比较固定。

       下面说说我实现的过程:

      1.制作训练集,这个我就不用说的,网上可以找到手写数字的训练集,或者自己手动写,用手机拍照出来,反正我是后者。

      2.找出图像可能是数字的部分,使用了findContours()这个函数找出图像中拥有外边框的图形,并用这些图形的外接矩形将这些图形抠出来,并进行大小判断,比如太小的排除掉,最后用一个容器保存起来。

vector<vector<Point>> contours;//点容器的容器,用于存放轮廓的点的容器的容器
vector<Vec4i> hierarchy;//点的指针容器
Mat cut_ROI(Mat src)
	{

		contours.clear();
		hierarchy.clear();

		Mat dst, tmp;
		src.copyTo(dst);
		blur(dst, dst, Size(3, 3));
		//GaussianBlur(dst, dst, Size(3, 3), 0.5, 0.5);
		//medianBlur(dst, dst, 3);

		threshold(dst, tmp, 120, 255, CV_THRESH_BINARY_INV);
		findContours(tmp, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
		vector<vector<Point>>::iterator It;

		for (It = contours.begin(); It < contours.end(); It++)
		{                        //画出可包围数字的最小矩形

			rect = boundingRect(*It);

			Mat roi = src(rect);
			roi.copyTo(_roi);//深拷贝出来


			weigth = rect.br().x - rect.tl().x;//宽
			height = rect.br().y - rect.tl().y;//高

			if ((weigth < height)  && (height > 10))
			{
				rectangle(src, rect, Scalar(255, 255, 255), 2);
				ROI.push_back(_roi);//保存,方便操作
				ROIposition.push_back(rect);
				Mat pre;
				resize(_roi, pre, Size(128, 128));

			}
		}
		return src;
	}
       3.KNN识别。KNN就是将训练集分类好,给出测试样本,求这个测试样本到其他训练集的欧几里德距离的一种算法,并求出在前K(一般是K=5)位的最近距离中占比最高的数据属于哪一个训练样本,返回训练样本的标签即可。比如测试样本中距离前5位最近的训练样本的标签是{5,6,5,5,6}那么这个可以得出结果就是这个测试样本是5.不懂的话可以看我上一篇博客。 KNN邻近算法

      4.在启动摄像头之前我们还需要对图像进行一些处理,比如模糊,降噪,二值化等等处理,其实这些处理要看具体情况具体选择,在这里我就不展开描述了。

      5.编写启动摄像头。完成。






  • 12
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 24
    评论
以下是使用OpenCV和Python编写的识别手写数字的代码: ``` python import cv2 import numpy as np # 载入训练好的模型 model = cv2.ml.KNearest_create() model.load('digits_model.xml') # 摄像头初始化 cap = cv2.VideoCapture(0) while True: # 拍摄一张图像 ret, img = cap.read() # 转换为灰度图像并进行二值化处理 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (5, 5), 0) th = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) # 找到数字轮廓 contours, hier = cv2.findContours(th, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 遍历每一个轮廓 for c in contours: # 绘制矩形框 (x, y, w, h) = cv2.boundingRect(c) cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2) # 将数字图像转换为28x28像素 roi = th[y:y+h, x:x+w] roi = cv2.resize(roi, (28, 28), interpolation=cv2.INTER_AREA) roi = cv2.dilate(roi, (3, 3)) # 将图像转换为模型所需的格式 data = np.reshape(roi, (1, 784)).astype(np.float32) ret, result, neighbours, dist = model.findNearest(data, k=1) # 在图像中绘制识别结果 cv2.putText(img, str(int(result[0][0])), (x, y-5), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) # 显示图像 cv2.imshow('camera', img) # 检测按下的按键 k = cv2.waitKey(1) if k == 27: # Esc键退出 break # 释放摄像头并关闭所有窗口 cap.release() cv2.destroyAllWindows() ``` 这段代码使用了KNN算法手写数字进行识别,首先从摄像头拍摄一张图像,然后将其转换为灰度图像,并进行二值化处理,接着找到数字轮廓,将数字图像转换为28x28像素,在图像中绘制识别结果后显示图像。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值