#include<iostream>
#include"AnswerRecognition.h"
using namespace std;
using namespace cv;
double EuDis(Point pt1, Point pt2)
{
return sqrt((pt2.x - pt1.x)*(pt2.x - pt1.x) + (pt2.y - pt1.y)*(pt2.y - pt1.y));
}
void Answer::GetWarpImg(Mat src, Mat& WarpImg)
{
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY);
Mat blur;
GaussianBlur(gray, blur, Size(3, 3), 0);
Mat canny;
Canny(blur, canny, 100, 200);
vector<vector<Point>>contours;
findContours(canny, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
//找到最大矩形轮廓
int index = 0;
double maxArea = 0;
for (int i = 0; i < contours.size(); i++)
{
double area = contourArea(contours[i]);
if (maxArea < area)
{
maxArea = area;
index = i;
}
}
//多边形近似
vector<vector<Point>>conPloy(contours.size());
double peri = arcLength(contours[index], true);
approxPolyDP(contours[index], conPloy[index], 0.02*peri, true);
//找到矩形四个顶点
vector<Point>srcPts;
for (int i = 0; i < conPloy[index].size(); i++)
{
srcPts.push_back(Point(conPloy[index][i].x, conPloy[index][i].y));
}
int width = src.cols / 2;
int height = src.rows / 2;
//将矩形四个顶点按T_L, B_L, B_R, T_R区分
int T_L, B_L, B_R, T_R;
for (int i = 0; i < srcPts.size(); i++)
{
if (srcPts[i].x < width && srcPts[i].y < height)
{
T_L = i;
}
if (srcPts[i].x < width && srcPts[i].y > height)
{
B_L = i;
}
if (srcPts[i].x > width && srcPts[i].y > height)
{
B_R = i;
}
if (srcPts[i].x > width && srcPts[i].y < height)
{
T_R = i;
}
}
/*
变换后,图像的长和宽应该变为:
长 = max(变换前左边长,变换前右边长)
宽 = max(变换前上边长,变换前下边长)
设变换后图像的左上角位置为原点位置。
*/
double upWidth = EuDis(srcPts[T_R], srcPts[T_L]);
double downWidth = EuDis(srcPts[B_R], srcPts[B_L]);
double maxWidth = max(upWidth, downWidth);
double leftHeight = EuDis(srcPts[B_L], srcPts[T_L]);
double rightHeight = EuDis(srcPts[B_R], srcPts[T_R]);
double maxHeight = max(leftHeight, rightHeight);
Point2f AffineSrcPts[4] = { Point2f(srcPts[T_L]) ,Point2f(srcPts[T_R]) ,Point2f(srcPts[B_L]) ,Point2f(srcPts[B_R]) };
Point2f AffineDstPts[4] = { Point2f(0, 0),Point2f(maxWidth , 0),Point2f(0, maxHeight),Point2f(maxWidth , maxHeight) };
Mat M;
//计算仿射变换矩阵
M = getPerspectiveTransform(AffineSrcPts, AffineDstPts);
//对加载图形进行仿射变换操作
warpPerspective(src, WarpImg, M, Point(maxWidth, maxHeight));
}
void Answer::GetAnswerArea(Mat&WarpImg, vector<Mat>&AnswerROI)
{
Mat gray;
cvtColor(WarpImg, gray, COLOR_BGR2GRAY);
Mat bin;
threshold(gray, bin, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
//使用 Size(15, 5)闭操作目的是为了将每一题选项连接起来。
Mat close;
Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 5));
morphologyEx(bin, close, MORPH_CLOSE, kernel);
vector<vector<Point>>contours;
findContours(close, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
RotatedRect rect;
Rect box;
for (int i = 0; i < contours.size(); i++)
{
Mat mask = Mat::zeros(WarpImg.size(), WarpImg.type());
mask = Scalar::all(255);
double area = contourArea(contours[i]);
if (area > 1000)
{
rect = minAreaRect(contours[i]);
box = rect.boundingRect();
double ratio = rect.size.height / rect.size.width;
//将每一选项都单独抠出来放进AnswerROI容器,以便后续识别。
if (ratio > 0.1)
{
//rectangle(WarpImg, Rect(box.tl(), box.br()), Scalar(0, 255, 0), 2);
Mat ROI = WarpImg(Rect(box.tl(), box.br()));
ROI.copyTo(mask(box));
AnswerROI.push_back(mask);
}
}
}
reverse(AnswerROI.begin(), AnswerROI.end());
}
//计算ABCDE区域所有像素点个数
int get_pixsum(Mat image, int pixstart, int pixend)
{
int sum = 0;
for (int i = pixstart; i < pixend; i++)
{
for (int j = 0; j < image.rows; j++)
{
if (image.at<uchar>(j, i) != 0)
{
sum++;
}
}
}
return sum;
}
//找到像素点最多区域的索引
int getMaxIndex(vector<int>Answer)
{
int max = 0;
int index = -1;
for (int i = 0; i < Answer.size(); i++)
{
if (Answer[i] > max)
{
max = Answer[i];
index = i;
}
}
return index;
}
void Answer::GetAnswer(cv::Mat&WarpImg, vector<Mat>&AnswerROI, vector<int>Answers, int &Score)
{
const double Total = 5; //题目数量
double Count = 0; //答对数量
vector<int>Results;
for (int i = 0; i < AnswerROI.size(); i++)
{
Mat gray;
cvtColor(AnswerROI[i], gray, COLOR_BGR2GRAY);
Mat bin;
threshold(gray, bin, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
vector<int>Answer;
//计算ABCDE区域所有像素点个数
int A = get_pixsum(bin, 60, 110);
int B = get_pixsum(bin, 110, 160);
int C = get_pixsum(bin, 160, 210);
int D = get_pixsum(bin, 210, 260);
int E = get_pixsum(bin, 260, 310);
Answer = { A,B,C,D,E };
//找到像素点最多区域的索引
int Index = getMaxIndex(Answer);
Results.push_back(Index);
//将选项在原图圈出来
vector<vector<Point>>contours;
findContours(bin, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
reverse(contours.begin(), contours.end());
for (int j = 0; j < contours.size(); j++)
{
double area = contourArea(contours[j]);
if (area > 200)
{
if (Answers[i] == Index)
{
drawContours(WarpImg, contours, Index, Scalar(0, 255, 0), 2);
}
else
{
drawContours(WarpImg, contours, Answers[i], Scalar(0, 0, 255), 2);
}
}
}
}
//统计得分
for (int i = 0; i < Total; i++)
{
if (Results[i] == Answers[i])
{
Count++;
}
}
Score = (Count / Total) * 100;
}
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论




























收起资源包目录





共 4 条
- 1
资源评论


Zero___Chen
- 粉丝: 5660
上传资源 快速赚钱
我的内容管理 展开
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助


最新资源
- 基于互联网金融的农村普惠金融的发展策略.docx
- 电子商务物流大数据应用问题研究.docx
- 计算机控制系统的软件抗干扰技术.docx
- 中信银行FTP(资金转移定价)基础知识内部培训资料.ppt
- linux服务器网卡驱动安装及故障排除.doc
- CTCP协议的简单即时通信软件的设计方案与实现.doc
- 计算机三级网络技术题库.doc
- Mooc背景下大学计算机基础课程的优化策略.docx
- 计量自动化系统在抄表中运用分析.docx
- 信息网络化对政府行政管理的挑战及对策.docx
- 电子商务概论-电大形考作业.doc
- 常用统计分析软件SPSS讲义.ppt
- 移动通信精品课程网站建设研究.doc
- 信息化条件下的施工企业财务管理问题探究.doc
- 浅析智慧城市顶层设计的思路及其误区.docx
- MATLAB数字滤波器设计方案与仿真.doc
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈



安全验证
文档复制为VIP权益,开通VIP直接复制
