完成电表数字的识别主要步骤有:
- 从摄像头获取电表图片,调整图片大小
- 二值化后执行闭运算,去除散乱的孤立点
- 找轮廓,包含数字的矩形轮廓区域,可通过面积大小和长宽比来唯一确定
- 使用漫水填充算法把轮廓四周的多余的背景变成黑色,数字为白色
- 找到轮廓的上下边界,即白色区域边界
- 从左到右找到数字的左右边界
- 提取数字,可放入KNN进行训练得到预测模型
- 加载模型进行测试
#include <iostream>
#include <fstream>
#include <opencv2/opencv.hpp>
#include <string>
using namespace std;
using namespace cv;
using namespace cv::ml;
int dst_l(Mat &dst, int start);
int dst_r(Mat &dst, int start);
int dst_t(Mat &dst);
int dst_b(Mat &dst);
void train_pixel();
int predict(Mat &img);
int main(int argc,char** argv)
{
string name1="a.jpg";
Mat img1 = imread(name1, 0);
Mat dst, mid;
resize(img1, img1, Size(1920, 1080));
threshold(img1, mid, 100, 255, THRESH_BINARY);
imshow("二值化",mid);
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
morphologyEx(mid, mid, MORPH_CLOSE, element);
imshow("闭运算",mid);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(mid, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size(); i++)
{
RotatedRect rect = minAreaRect(contours[i]);
if (rect.size.width < rect.size.height)
{
float temp = rect.size.width;
rect.size.width = rect.size.height;
rect.size.height = temp;
}
if (rect.size.width / rect.size.height > 3 && rect.size.width / rect.size.height < 4 && rect.size.area