赞
踩
当初用C++写的, 高考答题卡 大概原理是先进行模板匹配 得到四个顶点,然后分割出下图这两根线
读取端点,然后判断目标点上有没有涂黑。
- #include <opencv2/opencv.hpp>
- #include <iostream>
- #include <stdio.h>
- #include <conio.h>
- #include <stack>
- using namespace std;
- using namespace cv;
-
- vector<char*> listFiles(const char * dir);
- void cuttingX();
- void cuttingY();
- void HSVthreshold ();//HSV阈值分割
- int linex[16]={0};
- int liney[22]={0};
- //for循环 用%10求余来得到余值加2便可以
- /**************请在此处输入正确答案*************************/
- int a[60]={15,15,14,14,16,//1-5
- 15,14,14,16,15,//6-10
- 16,15,16,14,16,//11-15
- 15,16,14,15,14,//16-20
- 13,11,12,10,12,//21-25
- 12,11,10,12,13,//26-30
- 11,13,12,10,11,//31-35
- 12,10,11,8,7,//36-40
- 5,3,6,4,6,//41-45
- 6,4,5,4,3,//46-50
- 6,5,4,5,3,//51-55
- 5,6,6,3,4 //56-60
- };
- int main()
- {
- /***************拍照***************/
- VideoCapture capture(0);
- waitKey(50);
- capture.set(CV_CAP_PROP_FRAME_WIDTH, 1920);
- capture.set(CV_CAP_PROP_FRAME_HEIGHT, 1080);
- while(1)
- {
- Mat src;
- while (1)
- {
- capture >> src;
- Mat src1=src.clone();
-
- int x0 = src1.cols / 4;
- int x1 = src1.cols * 9/10;
- int y0 = src1.rows / 4-140;
- int y1 = src1.rows * 9/10;
- //画线的坐标,起始坐标和终止坐标
-
- cv::Point p0 = cv::Point(x0,y0);
- cv::Point p1 = cv::Point(x1, y0);
- cv::Point p2 = cv::Point(x1, y1);
- cv::line(src1, p0, p1, cv::Scalar(0, 0, 255), 3, 4);
- cv::line(src1, p1, p2, cv::Scalar(0, 0, 255), 3, 4);
- cv::namedWindow("对齐", CV_WINDOW_NORMAL);
- cv::imshow("对齐", src1);
- waitKey(10);
- if(kbhit( ))
- {
- int k1=getch();
- break;
- }}
- imwrite("保存的图像.jpg", src);
- /***************模板匹配***************/
- //Mat src= imread("±£´æ.jpg",1);
- Mat mattmp= imread("3.jpg", 1);
- Mat imagematch;
- Point minLoc;
- Point maxLoc01,maxLoc02,maxLoc03,maxLoc04,judje0;
- Point anchor01,anchor02,anchor03,anchor04;
- double minVal;
- double maxVal2;
- //Mat src = imread("C:/answercard/1.jpg",0);//¶ÁÈëºÚ°×ÔʼͼÏñ
- int srcRows = src.rows;
- int srcCols = src.cols;
- Mat src01 = src(Rect(0,0,srcCols/2,srcRows/2));
- Mat src02 = src(Rect(srcCols/2,0,srcCols/2,srcRows/2));
- Mat src03 = src(Rect(0,srcRows/2,srcCols/2,srcRows/2));
- Mat src04 = src(Rect(srcCols/2,srcRows/2,srcCols/2,srcRows/2));
- //imshow("src01",src01);imshow("src02",src02);imshow("src03",src03);imshow("src04",src04);
-
- matchTemplate( mattmp, src01, imagematch, 5 );
- normalize( imagematch, imagematch, 0, 1, NORM_MINMAX, -1, Mat() );
- minMaxLoc( imagematch, &minVal, &maxVal2, &minLoc, &maxLoc01, Mat() );
- anchor01 = maxLoc01;
- maxLoc01.x=maxLoc01.x+28;
- maxLoc01.y=maxLoc01.y+25;
- circle(src,maxLoc01,3,Scalar(0,255,0),3);
-
- matchTemplate( mattmp, src02, imagematch, 5 );
- normalize( imagematch, imagematch, 0, 1, NORM_MINMAX, -1, Mat() );
- minMaxLoc( imagematch, &minVal, &maxVal2, &minLoc, &maxLoc02, Mat() );
- anchor02 = Point(maxLoc02.x+srcCols/2,maxLoc02.y);
- anchor02.x=anchor02.x+28;
- anchor02.y=anchor02.y+25;
- circle(src,anchor02,3,Scalar(0,255,0),3);
-
- matchTemplate( mattmp, src03, imagematch, 5 );
- normalize( imagematch, imagematch, 0, 1, NORM_MINMAX, -1, Mat() );
- minMaxLoc( imagematch, &minVal, &maxVal2, &minLoc, &maxLoc03, Mat() );
- anchor03 = Point(maxLoc03.x,maxLoc03.y+srcRows/2);
- anchor03.x=anchor03.x+28;
- anchor03.y=anchor03.y+27;
- circle(src,anchor03,3,Scalar(0,255,0),3);
-
- matchTemplate( mattmp, src04, imagematch, 5 );
- normalize( imagematch, imagematch, 0, 1, NORM_MINMAX, -1, Mat() );
- minMaxLoc( imagematch, &minVal, &maxVal2, &minLoc, &maxLoc04, Mat() );
- anchor04 = Point(maxLoc04.x+srcCols/2,maxLoc04.y+srcRows/2);
- anchor04.x=anchor04.x+28;
- anchor04.y=anchor04.y+27;
- circle(src,anchor04,3,Scalar(0,255,0),3);
-
- //cv::namedWindow("原图", CV_WINDOW_NORMAL);
- //cv::imshow("原图", src);
- imwrite("保存图像.jpg", src);
- HSVthreshold ();//HSV阈值分割
- src = imread("img.jpg", 0);
-
-
- /***************区域切割***************/
- threshold(src, src, 16, 255, THRESH_BINARY);
- // imshow("二值图",src);
- GaussianBlur(src, src, Size(9,9), 0);
- Mat element = getStructuringElement(MORPH_RECT, Size(3,4));
- dilate(src, src, element);
- //element = getStructuringElement(MORPH_RECT, Size(5,4));
- erode(src, src, element);
- GaussianBlur(src, src, Size(7,7), 0);
- GaussianBlur(src, src, Size(7,7), 0);
- //morphologyEx(img, img, MORPH_OPEN, element);
- //morphologyEx(img, img, MORPH_CLOSE, element);
- //morphologyEx(img, img, MORPH_OPEN, element);
- threshold(src, src, 150, 255, THRESH_BINARY);
- // cv::namedWindow("camera", CV_WINDOW_NORMAL);//CV_WINDOW_NORMAL¾ÍÊÇ0
- // cv::imshow("camera", src);
- IplImage imgTmp = src;
- IplImage* image = cvCloneImage(&imgTmp);//以上两行为深拷贝
- cvSetImageROI(image,cvRect(maxLoc01.x,anchor02.y-10,anchor02.x-maxLoc01.x,20));//x、y、长、宽
- //cvShowImage("imageROIX",image);//X轴
- cvSaveImage("imageROIX.jpg",image);
- image = cvCloneImage(&imgTmp);
- cvSetImageROI(image,cvRect(anchor02.x-10,anchor02.y,20,anchor04.y-anchor02.y));//x、y、长、宽
- //cvShowImage("imageROIY",image);//Y轴
- cvSaveImage("imageROIY.jpg",image);
- cuttingX();
- cuttingY();
- /****************答案获取************************/
- //选择题20道 1.5分 1-20
- //21-35 2 36-40是2分一道 7个选项
- //41-60 2
- //用for循环对于某一点的右下角区域进行考察15*15
- //若白色区域大于50 则认为进行了填涂,且为对。且用绿色标注
- //否则为错,并用红色对该点进行标注
- //用for循环开始判断 x位置为linex【a【题号】】 y的位置为题号%liney【10+2】
- cvSetImageROI(image,cvRect(maxLoc01.x,anchor02.y,anchor02.x-maxLoc01.x,anchor04.y-maxLoc02.y));//x、y、长、宽
- cvSaveImage("imageROI.jpg",image);
- Mat srcXY = imread("imageROI.jpg", 1);
- float sum1=0,sum2=0,sum3=0;
- for (int tihao=0;tihao<60;tihao++)//判断每一题的正确与错误
- {
- int whitesum=0;
-
- for (int x=0;x<16;x++)
- {
- for (int y=0;y<16;y++)
- {
- Vec3b &p = srcXY.at<Vec3b>(liney[tihao%20+2]+y , (linex[a[tihao]-1]+x) );
- //printf(" (%d,%d)处的颜色为(b=%d, g=%d, r=%d) \n",linex[a[tihao]]+x, liney[tihao%10+2]+y,p[0], p[1], p[2]);
- //printf("第%d个的答案是%d\r\n",x+y,a[x+y]);
- if (p[0]>128)
- {
- whitesum++;
- }
- // p[0] = 255;//p1蓝色 用于判断
- // p[1] = 255; //P2 绿色
- // p[2] = 255; //P3 红色
- }
- }
- judje0.x=linex[a[tihao]-1];
- judje0.y=liney[tihao%20+2];
- //printf("第%d道题目位置是(%d,%d)\r\n",tihao,judje0.x,judje0.y);
- if (whitesum>20)
- {
- circle(srcXY,judje0,3,Scalar(0,255,0),3);
- if (0<=tihao&tihao<=19) sum1++;
- if (40<=tihao&tihao<=59) sum3++;
- if (20<=tihao&tihao<=39) sum2++;
-
- }
- else
- {
- circle(srcXY,judje0,3,Scalar(0,0,255),3);
- }
-
- // printf("一共有%d个白色像素\n",whitesum);
- }
- imshow("指定点",srcXY);
- imwrite("指定点.jpg",srcXY);
- //cvSaveImage("imageROI.jpg",srcXY);
- printf("该同学1-20得分%.1f\n",(1.5*sum1));
- printf("21-40得分%.1f\n",(sum2*2));
- printf("41-60得分%.1f\n",sum3*1.5);
- printf("总分为%.1f\n",(1.5*sum1+2*sum2+1.5*sum3));
-
- }
- }
-
-
-
- void HSVthreshold ()//HSV阈值分割
- {
- Mat img;
- Mat bgr;
- Mat hsv;
- Mat dst;
- //输入图像
- img = imread("保存图像.jpg", IMREAD_COLOR);
-
- //imshow("原图", img);
- //彩色图像的灰度值归一化
- img.convertTo(bgr, CV_32FC3, 1.0 / 255, 0);
- //颜色空间转换
- cvtColor(bgr, hsv, COLOR_BGR2HSV);
-
- dst = Mat::zeros(img.size(), CV_32FC3);
- //掩码
- Mat mask;
- inRange(hsv, Scalar(0, 0 / float(255) , 0 / float(255)) , Scalar(360 , 255 / float(255) , 142 / float(255)), mask);
- // hmin,smin/float(smin_Max), vmin / float(vmin_Max)), Scalar(hmax, smax / float(smax_Max), vmax / float(vmax_Max)
- //只保留
- for (int r = 0; r < bgr.rows; r++)
- {
- for (int c = 0; c < bgr.cols; c++)
- {
- if (mask.at<uchar>(r, c) == 255)
- {
- dst.at<Vec3f>(r, c) = bgr.at<Vec3f>(r, c);
- }
- }
- }
- //输出图像
- //imshow("3HSV阈值计算", dst);
- //保存图像
- dst.convertTo(dst, CV_8UC3, 255.0, 0);
- imwrite("img.jpg", dst);
- dst.release();//释放内存
- //waitKey(0);
-
- }
-
- void cuttingX( )
- {
-
- //一共有15个点 后期进行位置排序 并且去掉第一个和最后一个
- Mat matSrc = imread("imageROIX.jpg", 0);
- //threshold(matSrc, matSrc, 135, 254, THRESH_BINARY_INV);
-
- GaussianBlur(matSrc, matSrc, Size(7,7), 0);
- vector<vector<Point> > contours;//contours的类型,双重的vector
- vector<Vec4i> hierarchy;//Vec4i是指每一个vector元素中有四个int型数据。
- //阈值
- threshold(matSrc, matSrc, 70, 255, THRESH_BINARY);
- //imshow("阈值",matSrc);
- //寻找轮廓,这里注意,findContours的输入参数要求是二值图像,二值图像的来源大致有两种,第一种用threshold,第二种用canny
- findContours(matSrc.clone(), contours, hierarchy,CV_RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));
- /// 计算矩
- vector<Moments> mu(contours.size());
- for (int i = 0; i < contours.size(); i++)
- {
- mu[i] = moments(contours[i], false);
- }
- /// 计算中心矩:
- vector<Point2f> mc(contours.size());
- for (int i = 0; i < contours.size(); i++)
- {
- mc[i] = Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);
- linex[i]=int (mu[i].m10 / mu[i].m00);
- //printf("第 %d 个的位置是 %d\r\n",i,linex[i]);
- }
- /// 绘制轮廓
- Mat drawing = Mat::zeros(matSrc.size(), CV_8UC1);
- for (int i = 0; i < contours.size(); i++)
- {
- Scalar color = Scalar(255);
- //drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
- circle(drawing, mc[i], 4, color, -1, 8, 0);
- }
- int i,j,temp;
- for(j=0;j<=17;j++)//外围循环 循环10次
- {
- for (i=0;i<16-j;i++)//内层循环 循环 10减去外围的循环的第几次
- if (linex[i]>linex[i+1])//比较 比较 a[i]是不是大于a[i+1]是的话
- {
- temp=linex[i]; //就吧a[i]和a[i+1]互相交换了 这样 大的数就 随着循环
- linex[i]=linex[i+1]; //排到 后面了
- linex[i+1]=temp;}
- }
- //for(i=0;i<16;i++)
- // printf("%d=%d,",i,linex[i] );//去掉前后两个
- // printf("\r\n");
- // imshow("outImageX",drawing);
-
- }
- void cuttingY( )
- {
- Mat matSrc = imread("imageROIY.jpg", 0);
- //threshold(matSrc, matSrc, 120, 254, THRESH_BINARY_INV);
-
- GaussianBlur(matSrc, matSrc, Size(7, 7), 0);
- vector<vector<Point> > contours;//contours的类型,双重的vector
- vector<Vec4i> hierarchy;//Vec4i是指每一个vector元素中有四个int型数据。
- //阈值
- threshold(matSrc, matSrc, 70, 255, THRESH_BINARY);
- //寻找轮廓,这里注意,findContours的输入参数要求是二值图像,二值图像的来源大致有两种,第一种用threshold,第二种用canny
- findContours(matSrc.clone(), contours, hierarchy,CV_RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));
- /// 计算矩
- vector<Moments> mu(contours.size());
- for (int i = 0; i < contours.size(); i++)
- {
- mu[i] = moments(contours[i], false);
- }
- /// 计算中心矩:
- vector<Point2f> mc(contours.size());
- for (int i = 0; i < contours.size(); i++)
- {
- mc[i] = Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);
- liney[i]=int (mu[i].m01 / mu[i].m00);
- //printf("第%d个的位置是%d\r\n",i,liney[i]);
- }
- /// 绘制轮廓
- Mat drawing = Mat::zeros(matSrc.size(), CV_8UC1);
- for (int i = 0; i < contours.size(); i++)
- {
- Scalar color = Scalar(255);
- //drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
- circle(drawing, mc[i], 4, color, -1, 8, 0);
- }
- int i,j,temp;
- for(j=0;j<=23;j++)//外围循环 循环10次
- { for (i=0;i<22-j;i++)//内层循环 循环 10减去外围的循环的第几次
- if (liney[i]>liney[i+1])//比较 比较 a[i]是不是大于a[i+1]是的话
- { temp=liney[i]; //就吧a[i]和a[i+1]互相交换了 这样 大的数就 随着循环
- liney[i]=liney[i+1]; //排到 后面了
- liney[i+1]=temp;}
- }
- // for(i=0;i<22;i++)
- // printf("%d=%d,",i,liney[i] );//去掉前后两个
- // printf("\r\n");
- // imshow("outImageY",drawing);
-
- }
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。