参考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;
}
测试图像