#include <opencv2\opencv.hpp>
#include<cmath>
#include<iostream>
using namespace std;
using namespace cv;
int mark[4][2][2];
Mat image; //原图
Mat image1; //灰度图
Mat image2; //二值图
Mat imagebox2;//最大域二值图
Rect maxRect; //最大域大小
Rect maxAbcRect;//填图区
Mat imagebox;//最大域原图
Mat imageabc2;//选择题二值图
Mat imageabc;//选择题原图
Mat imageblank2;//填空题二值图
Mat imageblank;//填空题原图
char answer[1000];
void abc()
{
Mat imageboxtest = imagebox.clone();
vector<Vec4i> lines;
HoughLinesP(imagebox2, lines, 1, CV_PI / 2, 100, 300, 12);
for (size_t i = 0; i < lines.size(); i++)
{
Vec4i l = lines[i];
line(imageboxtest, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 1, 8);
line(imageboxtest, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 1, 8);
}
cvtColor(imageboxtest, imageboxtest, CV_RGB2GRAY);
adaptiveThreshold(imageboxtest, imageboxtest, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 21, 10); //自适应二值化
maxAbcRect.x = lines[0][0]; maxAbcRect.y = lines[0][1] + 8; //选择题
maxAbcRect.width = lines[0][2] - lines[0][0];
maxAbcRect.height = lines[1][1] - lines[0][1] - 8;
imageabc2 = imageboxtest(maxAbcRect);
imageabc = imagebox(maxAbcRect);
maxAbcRect.x = lines[1][0]; maxAbcRect.y = lines[1][1]; //填空题
maxAbcRect.width = lines[1][2] - lines[1][0];
maxAbcRect.height = imageboxtest.rows - lines[1][1];
imageblank2 = imageboxtest(maxAbcRect);
imageblank = imagebox(maxAbcRect);
imwrite("2.jpg", imageblank);
}
void showabc()
{
Mat abctest = imageabc2.clone();
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(abctest, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
Mat image(abctest.rows, abctest.cols, CV_8UC1, Scalar(0));
double maxArea = 0;
vector<Point> maxContour;
for (size_t i = 0; i < contours.size(); i++)
{
double area = contourArea(contours[i]);
if (area > 20)
{
drawContours(image, contours, i, Scalar(255), CV_FILLED);//画出图像轮廓
int locaX = (contours[i][0].x + 3) % (abctest.cols / 4);
int X = (contours[i][0].x) / (abctest.cols / 4);
int Y = (contours[i][0].y) / (abctest.rows / 10);
int choose = locaX / (abctest.cols / 20);
answer[(Y / 5) * 20 + Y % 5 + 1 + 5 * X] = 'a' + choose - 1;
char c[2];
c[0] = 'a' + choose - 1;
c[1] = 0;
contours[i][0].y += 5;
contours[i][0].x -= 5;
putText(imageabc, c, contours[i][0], FONT_HERSHEY_PLAIN, 2, Scalar(0, 0, 255), 1, 8);
}
}
}
int returnmath(Mat pic)
{
int one = 0, two = 0, three = 0;
for (size_t i = pic.rows / 4; i > 0; i--)
{
uchar o = pic.at<uchar>(i, pic.cols / 2);
if (o< 100)
{
++one; break;
}
}
for (size_t i = pic.rows / 4; i < pic.rows * 3 / 4; i++)
{
if (pic.at<uchar>(i, pic.cols / 2)< 100)
{
++one; break;
}
}
for (size_t i = pic.rows * 3 / 4; i < pic.rows; i++)
{
uchar p = pic.at<uchar>(i, pic.cols / 2);
if (p< 100)
{
++one; break;
}
}
for (size_t i = pic.cols / 2; i >0; i--)
{
if (pic.at<uchar>(pic.rows / 4, i)< 100)
{
two = 1; break;
}
}
for (size_t i = pic.cols / 2; i >0; i--)
{
if (pic.at<uchar>(pic.rows * 3 / 4, i)< 100)
{
three = 1; break;
}
}
int math = mark[one][two][three];
if (math > 9)
{
math = 6;
for (size_t i = pic.cols / 2; i <pic.cols; i++)
{
if (pic.at<uchar>(pic.rows / 4, i)< 100)
{
math = 8; break;
}
}
}
return math;
}
void showmath()
{
Mat mathtest = imageblank2.clone();
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(mathtest, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
Mat image(mathtest.rows, mathtest.cols, CV_8UC1, Scalar(0));
double maxArea = 0;
vector<Point> maxContour;
vector<char>m;
for (size_t i = 0; i < contours.size(); i++)
{
double area = contourArea(contours[i]);
if (area > 50)
{
drawContours(image, contours, i, Scalar(255), CV_FILLED);
int minx = 9999999, miny = 99999, maxx = 0, maxy = 0;
for (size_t j = 0; j < contours[i].capacity(); j++)
{
if (contours[i][j].x > maxx)maxx = contours[i][j].x;
if (contours[i][j].x < minx)minx = contours[i][j].x;
if (contours[i][j].y > maxy)maxy = contours[i][j].y;
if (contours[i][j].y < maxy)miny = contours[i][j].y;
}
Rect p;
p.x = minx; p.y = miny; p.width = maxx - minx; p.height = maxy - miny;
Mat pic = mathtest(p);
bitwise_not(pic, pic);
vector<vector<Point> > contour_math;
findContours(pic, contour_math, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
for (size_t k = 0; k < contour_math.size(); k++)
{
double area_math = contourArea(contour_math[k]);
if (area_math >(pic.cols*pic.rows) / 3 && contour_math[k][0].x > pic.cols / 2)
{
int minx = 9999999, miny = 99999, maxx = 0, maxy = 0;
for (size_t l = 0; l < contour_math[k].capacity(); l++)
{
if (contour_math[k][l].x > maxx)maxx = contour_math[k][l].x;
if (contour_math[k][l].x < minx)minx = contour_math[k][l].x;
if (contour_math[k][l].y > maxy)maxy = contour_math[k][l].y;
if (contour_math[k][l].y < maxy)miny = contour_math[k][l].y;
}
Rect q;
q.x = minx; q.y = miny; q.width = maxx - minx; q.height = maxy - miny;
Mat pic_math = pic(q);
int math = returnmath(pic_math);
char c[2];
c[0] = '0' + math;
c[1] = 0;
contours[i][k].y += 20;
putText(imageblank, c, contours[i][k], FONT_HERSHEY_PLAIN, 2, Scalar(0, 0, 255), 1, 8, 0);
contours[i][k].y -= 20;
int X = contours[i][k].x / (imageblank.cols / 5);
int Y = contours[i][k].y / (imageblank.rows / 3);
answer[40 + 5 * Y + X + 1] = math + '0';
}
}
}
}
}
int main()
{
memset(mark, -1, sizeof(mark));
mark[0][0][0] = 1; mark[3][0][1] = 2; mark[3][0][0] = 3; mark[1][1][0] = 4; mark[3][1][0] = 5;
mark[3][1][1] = 6; mark[1][0][0] = 7; mark[3][1][1] = 8; mark[2][1][0] = 9; mark[2][1][1] = 0;
image = imread("D://1.jpg");
imshow("原图", image);
cvtColor(image, image1, CV_RGB2GRAY);
adaptiveThreshold(image1, image2, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 21, 10); //自适应二值化
Mat imagecanny;
image2.copyTo(imagecanny);//将image2粘贴到image canny;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(imagecanny, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));//得到答题卡的轮廓
double maxArea = 0;
vector<Point> maxContour;
for (size_t i = 0; i < contours.size(); i++)
{
double area = contourArea(contours[i]);
if (area > maxArea)
{
maxArea = area;
maxContour = contours[i];
}
}//找到最大的连通域
maxRect = boundingRect(maxContour);//计算外围的矩形边框
imagebox = image(maxRect);//得到最大域的原图
imagebox2 = imagecanny(maxRect);//得到最大域的二值图
Mat imageboxtest = imagebox.clone();//创建一个和imagebox相同的图像
vector<Vec4i> lines;
HoughLinesP(imagebox2, lines, 1, CV_PI / 180, 190, 100, 13);
for (size_t i = 0; i < lines.size(); i++)
{
Vec4i l = lines[i];
line(imageboxtest, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 1, 8);
//line(imageboxtest, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 1, 8);
}//使用霍夫变换进行划线
cvtColor(imageboxtest, imageboxtest, CV_RGB2GRAY);
adaptiveThreshold(imageboxtest, imageboxtest, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 21, 10); //自适应二值化
vector<Point>corners;
vector<Point2f>cornerPos(4);
vector<Point2f>cornerTrans(4);//四个角点
int j = 0;
Point center;
center.x = cvRound(maxRect.width / 2);
center.y = cvRound(maxRect.height / 2);//对边界取整
goodFeaturesToTrack(imageboxtest, corners, 2000, 0.01, 10, Mat(), 3, true, 0.04);//角点搜寻
int maxline;
maxline = sqrt(center.x*center.x + center.y*center.y) + 1;
for (unsigned int i = 0; i < corners.size(); i++)
{
int t = abs(center.x - corners[i].x)*abs(center.x - corners[i].x) + abs(center.y - corners[i].y)*abs(center.y - corners[i].y);
if (t > 48400)
{
circle(imagebox, corners[i], 5, Scalar(0, 0, 255), -1, 8, 0);
cornerPos[j++] = corners[i];
}
}
cornerTrans[0].x = imagebox.cols; cornerTrans[0].y = 0;
cornerTrans[1].x = 0; cornerTrans[1].y = imagebox.rows;
cornerTrans[2].x = imagebox.cols; cornerTrans[2].y = imagebox.rows;
cornerTrans[3].x = 0; cornerTrans[3].y = 0;//根据图片的坐标确定角点
Mat transform = getPerspectiveTransform(cornerPos, cornerTrans); //获得透视变换矩阵
warpPerspective(imagebox, imagebox, transform, imageboxtest.size(), INTER_LINEAR);//进行透视变换
cvtColor(imagebox, imagebox2, CV_RGB2GRAY);
adaptiveThreshold(imagebox2, imagebox2, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 21, 10); //自适应二值化
abc();//抠出涂改区域
showabc(); //找涂抹区
showmath();
imshow("识别后的图片", image);
cout << "题号 答案" << endl << endl << "选择题:" << endl;
for (int i = 1; i < 53; i++)
{
cout << i << " : " << answer[i] << endl;
}
waitKey(0);
return 0;
}
机读卡的识别
猜你喜欢
转载自blog.csdn.net/qq_41705596/article/details/83278589
今日推荐
周排行