在上一篇博客《OpenCV4学习笔记(54)》中,整理了关于KNN最近邻算法的一些相关内容和一个手写体数字识别的例子。但是上次所实现的手写体数字识别,每次只能固定地输入测试图像进行预测,而且所使用的也是从OpenCV自带测试图中裁剪下来的数字。那么这一次笔记,我们就把上一次笔记的内容和OpenCV中的鼠标操作进行结合,实现一个可以利用鼠标书写数字并实时进行手写体数字识别的小程序。
关于KNN算法实现手写数字识别的部分内容,可以参阅我的上一篇博客,这里就不多赘述了。这里主要看一下OpenCV中关于鼠标操作的内容。
首先,我们需要声明一个鼠标的回调函数:
static void on_Mouse(int event, int x, int y, int flag, void*);
该函数的参数含义如下:
(1)参数event:鼠标事件
(2)参数x:鼠标当前点的x坐标
(3)参数y:鼠标当前的的y坐标
(4)参数flag:鼠标所处状态
然后,在程序中需要使用鼠标的时候,就加入一条定义鼠标操作的函数,当鼠标位于该指定窗口上时,执行回调函数:
setMouseCallback("digit", on_Mouse, 0);
该函数参数含义如下:
(1)参数windowName:指定的窗口名,当鼠标位于该窗口上时就执行回调函数。
(2)参数MouseCallback:需要执行的鼠标回调函数。
(3)参数userdata:用户传入数据,不需要可以直接置零。
接着就需要定义我们的鼠标回调函数来进行所需的操作了,在窗口中按下鼠标左键进行书写数字,写完后按空格键进行识别,按鼠标右键是清空窗口。代码演示如下:
static void on_Mouse(int event, int x, int y, int flag, void*)
{
if (event == EVENT_LBUTTONDOWN) //当鼠标左键按下,获取该点坐标
{
prePoint = Point(x, y);
}
//当鼠标左键保持按下标志,且鼠标移动
else if (event == EVENT_MOUSEMOVE && (flag & EVENT_FLAG_LBUTTON))
{
Point nowPoint(x, y);
line(digit, nowPoint, prePoint, Scalar(255), 2, 8, 0);
prePoint = nowPoint; //将鼠标的当前点作为上个点位,以开始下一个线段区域的绘制
imshow("digit", digit); //在窗口更新目标图像
}
//当鼠标右键按下时
else if (event == EVENT_RBUTTONDOWN)
{
imshow("digit", canvas);
digit = canvas.clone();
}
}
到这里,就实现了在一个窗口中书写数字的功能了,接下来只需要把上次笔记中的训练、识别部分加进来就可以了,下面是完整代码演示:
#include<opencv2/opencv.hpp>
#include<stdlib.h>
#include<iostream>
#include<string>
#