opencv 数字图像识别

参考https://blog.csdn.net/LTG01/article/details/50492556

https://www.cnblogs.com/leegod/p/8929678.html

写了这个识别股票行情的代码,代码比较简单,就是先切割一个个数字字符,然后根据特征识别数字,可能对不同的字体需要微调一些参数,基本上是可以用的。有需要的人拿去吧。


#include "stdafx.h"
#include <iostream>
#include <opencv2\opencv.hpp>

using namespace std;
using namespace cv;

int getColSum(Mat& src, int col)
{
	int colValue = 0;
	for (int i = 0; i < src.rows; i++)
	{
		if (src.at<uchar>(i, col) == 0)
			colValue++;	
	}

	return colValue;
}

int getRowSum(Mat& src, int row)
{
	int colValue = 0;
	for (int i = 0; i < src.cols; i++)
	{
		if (src.at<uchar>(row, i) == 0)
			colValue++;		
	}
	return colValue;
}

void cutTop(Mat& src, Mat& dstImg)//上下切割
{
	int top, bottom;
	top = 0;
	bottom = src.rows;

	int i;
	for (i = 0; i < src.rows; i++)
	{
		int colValue = getRowSum(src, i);
		//cout <<i<<" th "<< colValue << endl;
		if (colValue > 0)
		{
			top = i;
			break;
		}
	}
	for (; i < src.rows; i++)
	{
		int colValue = getRowSum(src, i);
		//cout << i << " th " << colValue << endl;
		if (colValue == 0)
		{
			bottom = i;
			break;
		}
	}

	int height = bottom - top;
	Rect rect(0, top, src.cols, height);
	dstImg = src(rect).clone();
}

int cutLeft(Mat& src, Mat& leftImg, Mat& rightImg)//左右切割
{
	int left, right;
	left = -1;
	right = src.cols;

	int i;
	for (i = 0; i < src.cols; i++)
	{
		int colValue = getColSum(src, i);
		//cout <<i<<" th "<< colValue << endl;
		if (colValue > 0)
		{
			left = i;
			break;
		}
	}
	if (left == -1)
	{
		return -1;
	}

	for (; i < src.cols; i++)
	{
		int colValue = getColSum(src, i);
		//cout << i << " th " << colValue << endl;
		if (colValue == 0)
		{
			right = i;
			break;
		}
	}
	int width = right - left;
	Rect rect(left, 0, width, src.rows);
	leftImg = src(rect).clone();
	Rect rectRight(right, 0, src.cols - right, src.rows);
	rightImg = src(rectRight).clone();
	cutTop(leftImg, leftImg);
	return left;
}

int getRowCross(Mat& src, int x1, vector<int>& vecCols)
{
	// 计算图像与直线x1的交点	
	int lastCols = -2;
	for (int i = 0; i < src.cols; i++)
	{
		if (src.at<uchar>(x1, i) == 0)
		{
			if (i - lastCols > 1)
			{				
				vecCols.push_back(i);
			}
			lastCols = i;
		}
	}
	return vecCols.size();
}

int getColCross(Mat& src, int y1, vector<int>& vecRows)
{
	// 计算图像与直线y1的交点
	int lastRow = -2;
	for (int i = 0; i < src.rows; i++)
	{
		if (src.at<uchar>(i, y1) == 0)
		{
			if (i - lastRow > 1)
			{
				vecRows.push_back(i);
			}
			lastRow = i;
		}
	}
	return vecRows.size();
}

char getNum(Mat& src)
{
	// 判断是否小数点
	if (src.rows == src.cols && src.rows < 3)
		return '.';

	// 判断是否负号
	if (src.cols > 3 && src.rows < 3)
		return '-';

	int y1 = src.cols / 2;
	vector<int> vecRows;
	int c3 = getColCross(src, y1, vecRows);
	if (c3 == 1)		
		return 1 + '0';

	float f7 = 0.4f, f4 = 0.7f, fw = 0.3f, fx1 = 0.3f, fx2 = 0.7f;
	if (c3 == 2) // 0, 7, 4
	{
		int x1 = src.rows * f7;
		vector<int> vecCols1;
		int c1 = getRowCross(src, x1, vecCols1);
		if (c1 == 1)
			return 7 + '0';

		vector<int> vecCols2;
		int x2 = src.rows * f4;
		int c2 = getRowCross(src, x2, vecCols2);
		if (c2 == 1)
			return 4 + '0';

		vector<int> vecCols3;
		x2 = src.rows * fw;
		c2 = getRowCross(src, x2, vecCols3);
		if (c2 == 1)
			return 'w'; // 万

		return '0';		
	}
	if (c3 == 3) // 2, 3, 5, 6, 8, 9
	{
		int x1 = src.rows * fx1;
		vector<int> vecCols1;
		int c1 = getRowCross(src, x1, vecCols1);

		vector<int> vecCols2;
		int x2 = src.rows * fx2;
		int c2 = getRowCross(src, x2, vecCols2);

		if (c1 == 2 && c2 == 2)
			return 8 + '0';

		if (c1 == 1 && c2 == 2)
		{
			if (vecCols1[0] < y1)
				return 6 + '0';
			return 'y'; // 亿
		}

		if (c1 == 2 && c2 == 1)
			return 9 + '0';

		if (c1 == 1 && c2 == 1) // 2, 3, 5
		{
			if (vecCols1[0] > y1&& vecCols2[0] < y1)
				return 2 + '0';

			if (vecCols1[0] > y1&& vecCols2[0] > y1)
				return 3 + '0';

			if (vecCols1[0] < y1 && vecCols2[0] > y1)
				return 5 + '0';
		}
	}
	return ' ';
}

int main()
{
	Mat src = imread("tn7.bmp", CV_LOAD_IMAGE_GRAYSCALE);
	threshold(src, src, 50, 255, CV_THRESH_BINARY_INV);

	Mat leftImg, rightImg;
	int left = cutLeft(src, leftImg, rightImg);
	int i = 0;
	while (left >= 0)
	{
		//char nameLeft[10];
		//sprintf(nameLeft, "%dLeft", i);
		//char nameRight[10];
		//sprintf(nameRight, "%dRight", i);
		//i++;

		//stringstream ss;
	 //   ss << nameLeft;
		//imwrite( ss.str() + ".bmp", leftImg);

		const int maxNumDistance = 5;
		char c = getNum(leftImg);
		if (left > maxNumDistance)
			printf("\n%c", c);
		else
			printf("%c", c);
		
		Mat srcTmp = rightImg;	
		left = cutLeft(srcTmp, leftImg, rightImg);

		//imshow(nameLeft, leftImg);
		//waitKey(0);
	}
	imshow("origin", src);
	waitKey(0);
	return 0;
}

 测试图像 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值