当前位置:   article > 正文

答题卡改卷_vc 答题卡改卷代码

vc 答题卡改卷代码

 当初用C++写的, 高考答题卡 大概原理是先进行模板匹配  得到四个顶点,然后分割出下图这两根线

 

 

读取端点,然后判断目标点上有没有涂黑。

  1. #include <opencv2/opencv.hpp>
  2. #include <iostream>
  3. #include <stdio.h>
  4. #include <conio.h>
  5. #include <stack>
  6. using namespace std;
  7. using namespace cv;
  8. vector<char*> listFiles(const char * dir);
  9. void cuttingX();
  10. void cuttingY();
  11. void HSVthreshold ();//HSV阈值分割
  12. int linex[16]={0};
  13. int liney[22]={0};
  14. //for循环 用%10求余来得到余值加2便可以
  15. /**************请在此处输入正确答案*************************/
  16. int a[60]={15,15,14,14,16,//1-5
  17. 15,14,14,16,15,//6-10
  18. 16,15,16,14,16,//11-15
  19. 15,16,14,15,14,//16-20
  20. 13,11,12,10,12,//21-25
  21. 12,11,10,12,13,//26-30
  22. 11,13,12,10,11,//31-35
  23. 12,10,11,8,7,//36-40
  24. 5,3,6,4,6,//41-45
  25. 6,4,5,4,3,//46-50
  26. 6,5,4,5,3,//51-55
  27. 5,6,6,3,4 //56-60
  28. };
  29. int main()
  30. {
  31. /***************拍照***************/
  32. VideoCapture capture(0);
  33. waitKey(50);
  34. capture.set(CV_CAP_PROP_FRAME_WIDTH, 1920);
  35. capture.set(CV_CAP_PROP_FRAME_HEIGHT, 1080);
  36. while(1)
  37. {
  38. Mat src;
  39. while (1)
  40. {
  41. capture >> src;
  42. Mat src1=src.clone();
  43. int x0 = src1.cols / 4;
  44. int x1 = src1.cols * 9/10;
  45. int y0 = src1.rows / 4-140;
  46. int y1 = src1.rows * 9/10;
  47. //画线的坐标,起始坐标和终止坐标
  48. cv::Point p0 = cv::Point(x0,y0);
  49. cv::Point p1 = cv::Point(x1, y0);
  50. cv::Point p2 = cv::Point(x1, y1);
  51. cv::line(src1, p0, p1, cv::Scalar(0, 0, 255), 3, 4);
  52. cv::line(src1, p1, p2, cv::Scalar(0, 0, 255), 3, 4);
  53. cv::namedWindow("对齐", CV_WINDOW_NORMAL);
  54. cv::imshow("对齐", src1);
  55. waitKey(10);
  56. if(kbhit( ))
  57. {
  58. int k1=getch();
  59. break;
  60. }}
  61. imwrite("保存的图像.jpg", src);
  62. /***************模板匹配***************/
  63. //Mat src= imread("±£´æ.jpg",1);
  64. Mat mattmp= imread("3.jpg", 1);
  65. Mat imagematch;
  66. Point minLoc;
  67. Point maxLoc01,maxLoc02,maxLoc03,maxLoc04,judje0;
  68. Point anchor01,anchor02,anchor03,anchor04;
  69. double minVal;
  70. double maxVal2;
  71. //Mat src = imread("C:/answercard/1.jpg",0);//¶ÁÈëºÚ°×ԭʼͼÏñ
  72. int srcRows = src.rows;
  73. int srcCols = src.cols;
  74. Mat src01 = src(Rect(0,0,srcCols/2,srcRows/2));
  75. Mat src02 = src(Rect(srcCols/2,0,srcCols/2,srcRows/2));
  76. Mat src03 = src(Rect(0,srcRows/2,srcCols/2,srcRows/2));
  77. Mat src04 = src(Rect(srcCols/2,srcRows/2,srcCols/2,srcRows/2));
  78. //imshow("src01",src01);imshow("src02",src02);imshow("src03",src03);imshow("src04",src04);
  79. matchTemplate( mattmp, src01, imagematch, 5 );
  80. normalize( imagematch, imagematch, 0, 1, NORM_MINMAX, -1, Mat() );
  81. minMaxLoc( imagematch, &minVal, &maxVal2, &minLoc, &maxLoc01, Mat() );
  82. anchor01 = maxLoc01;
  83. maxLoc01.x=maxLoc01.x+28;
  84. maxLoc01.y=maxLoc01.y+25;
  85. circle(src,maxLoc01,3,Scalar(0,255,0),3);
  86. matchTemplate( mattmp, src02, imagematch, 5 );
  87. normalize( imagematch, imagematch, 0, 1, NORM_MINMAX, -1, Mat() );
  88. minMaxLoc( imagematch, &minVal, &maxVal2, &minLoc, &maxLoc02, Mat() );
  89. anchor02 = Point(maxLoc02.x+srcCols/2,maxLoc02.y);
  90. anchor02.x=anchor02.x+28;
  91. anchor02.y=anchor02.y+25;
  92. circle(src,anchor02,3,Scalar(0,255,0),3);
  93. matchTemplate( mattmp, src03, imagematch, 5 );
  94. normalize( imagematch, imagematch, 0, 1, NORM_MINMAX, -1, Mat() );
  95. minMaxLoc( imagematch, &minVal, &maxVal2, &minLoc, &maxLoc03, Mat() );
  96. anchor03 = Point(maxLoc03.x,maxLoc03.y+srcRows/2);
  97. anchor03.x=anchor03.x+28;
  98. anchor03.y=anchor03.y+27;
  99. circle(src,anchor03,3,Scalar(0,255,0),3);
  100. matchTemplate( mattmp, src04, imagematch, 5 );
  101. normalize( imagematch, imagematch, 0, 1, NORM_MINMAX, -1, Mat() );
  102. minMaxLoc( imagematch, &minVal, &maxVal2, &minLoc, &maxLoc04, Mat() );
  103. anchor04 = Point(maxLoc04.x+srcCols/2,maxLoc04.y+srcRows/2);
  104. anchor04.x=anchor04.x+28;
  105. anchor04.y=anchor04.y+27;
  106. circle(src,anchor04,3,Scalar(0,255,0),3);
  107. //cv::namedWindow("原图", CV_WINDOW_NORMAL);
  108. //cv::imshow("原图", src);
  109. imwrite("保存图像.jpg", src);
  110. HSVthreshold ();//HSV阈值分割
  111. src = imread("img.jpg", 0);
  112. /***************区域切割***************/
  113. threshold(src, src, 16, 255, THRESH_BINARY);
  114. // imshow("二值图",src);
  115. GaussianBlur(src, src, Size(9,9), 0);
  116. Mat element = getStructuringElement(MORPH_RECT, Size(3,4));
  117. dilate(src, src, element);
  118. //element = getStructuringElement(MORPH_RECT, Size(5,4));
  119. erode(src, src, element);
  120. GaussianBlur(src, src, Size(7,7), 0);
  121. GaussianBlur(src, src, Size(7,7), 0);
  122. //morphologyEx(img, img, MORPH_OPEN, element);
  123. //morphologyEx(img, img, MORPH_CLOSE, element);
  124. //morphologyEx(img, img, MORPH_OPEN, element);
  125. threshold(src, src, 150, 255, THRESH_BINARY);
  126. // cv::namedWindow("camera", CV_WINDOW_NORMAL);//CV_WINDOW_NORMAL¾ÍÊÇ0
  127. // cv::imshow("camera", src);
  128. IplImage imgTmp = src;
  129. IplImage* image = cvCloneImage(&imgTmp);//以上两行为深拷贝
  130. cvSetImageROI(image,cvRect(maxLoc01.x,anchor02.y-10,anchor02.x-maxLoc01.x,20));//x、y、长、宽
  131. //cvShowImage("imageROIX",image);//X轴
  132. cvSaveImage("imageROIX.jpg",image);
  133. image = cvCloneImage(&imgTmp);
  134. cvSetImageROI(image,cvRect(anchor02.x-10,anchor02.y,20,anchor04.y-anchor02.y));//x、y、长、宽
  135. //cvShowImage("imageROIY",image);//Y轴
  136. cvSaveImage("imageROIY.jpg",image);
  137. cuttingX();
  138. cuttingY();
  139. /****************答案获取************************/
  140. //选择题20道 1.5分 1-20
  141. //21-35 2 36-40是2分一道 7个选项
  142. //41-60 2
  143. //用for循环对于某一点的右下角区域进行考察15*15
  144. //若白色区域大于50 则认为进行了填涂,且为对。且用绿色标注
  145. //否则为错,并用红色对该点进行标注
  146. //用for循环开始判断 x位置为linex【a【题号】】 y的位置为题号%liney【10+2】
  147. cvSetImageROI(image,cvRect(maxLoc01.x,anchor02.y,anchor02.x-maxLoc01.x,anchor04.y-maxLoc02.y));//x、y、长、宽
  148. cvSaveImage("imageROI.jpg",image);
  149. Mat srcXY = imread("imageROI.jpg", 1);
  150. float sum1=0,sum2=0,sum3=0;
  151. for (int tihao=0;tihao<60;tihao++)//判断每一题的正确与错误
  152. {
  153. int whitesum=0;
  154. for (int x=0;x<16;x++)
  155. {
  156. for (int y=0;y<16;y++)
  157. {
  158. Vec3b &p = srcXY.at<Vec3b>(liney[tihao%20+2]+y , (linex[a[tihao]-1]+x) );
  159. //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]);
  160. //printf("第%d个的答案是%d\r\n",x+y,a[x+y]);
  161. if (p[0]>128)
  162. {
  163. whitesum++;
  164. }
  165. // p[0] = 255;//p1蓝色 用于判断
  166. // p[1] = 255; //P2 绿色
  167. // p[2] = 255; //P3 红色
  168. }
  169. }
  170. judje0.x=linex[a[tihao]-1];
  171. judje0.y=liney[tihao%20+2];
  172. //printf("第%d道题目位置是(%d,%d)\r\n",tihao,judje0.x,judje0.y);
  173. if (whitesum>20)
  174. {
  175. circle(srcXY,judje0,3,Scalar(0,255,0),3);
  176. if (0<=tihao&tihao<=19) sum1++;
  177. if (40<=tihao&tihao<=59) sum3++;
  178. if (20<=tihao&tihao<=39) sum2++;
  179. }
  180. else
  181. {
  182. circle(srcXY,judje0,3,Scalar(0,0,255),3);
  183. }
  184. // printf("一共有%d个白色像素\n",whitesum);
  185. }
  186. imshow("指定点",srcXY);
  187. imwrite("指定点.jpg",srcXY);
  188. //cvSaveImage("imageROI.jpg",srcXY);
  189. printf("该同学1-20得分%.1f\n",(1.5*sum1));
  190. printf("21-40得分%.1f\n",(sum2*2));
  191. printf("41-60得分%.1f\n",sum3*1.5);
  192. printf("总分为%.1f\n",(1.5*sum1+2*sum2+1.5*sum3));
  193. }
  194. }
  195. void HSVthreshold ()//HSV阈值分割
  196. {
  197. Mat img;
  198. Mat bgr;
  199. Mat hsv;
  200. Mat dst;
  201. //输入图像
  202. img = imread("保存图像.jpg", IMREAD_COLOR);
  203. //imshow("原图", img);
  204. //彩色图像的灰度值归一化
  205. img.convertTo(bgr, CV_32FC3, 1.0 / 255, 0);
  206. //颜色空间转换
  207. cvtColor(bgr, hsv, COLOR_BGR2HSV);
  208. dst = Mat::zeros(img.size(), CV_32FC3);
  209. //掩码
  210. Mat mask;
  211. inRange(hsv, Scalar(0, 0 / float(255) , 0 / float(255)) , Scalar(360 , 255 / float(255) , 142 / float(255)), mask);
  212. // hmin,smin/float(smin_Max), vmin / float(vmin_Max)), Scalar(hmax, smax / float(smax_Max), vmax / float(vmax_Max)
  213. //只保留
  214. for (int r = 0; r < bgr.rows; r++)
  215. {
  216. for (int c = 0; c < bgr.cols; c++)
  217. {
  218. if (mask.at<uchar>(r, c) == 255)
  219. {
  220. dst.at<Vec3f>(r, c) = bgr.at<Vec3f>(r, c);
  221. }
  222. }
  223. }
  224. //输出图像
  225. //imshow("3HSV阈值计算", dst);
  226. //保存图像
  227. dst.convertTo(dst, CV_8UC3, 255.0, 0);
  228. imwrite("img.jpg", dst);
  229. dst.release();//释放内存
  230. //waitKey(0);
  231. }
  232. void cuttingX( )
  233. {
  234. //一共有15个点 后期进行位置排序 并且去掉第一个和最后一个
  235. Mat matSrc = imread("imageROIX.jpg", 0);
  236. //threshold(matSrc, matSrc, 135, 254, THRESH_BINARY_INV);
  237. GaussianBlur(matSrc, matSrc, Size(7,7), 0);
  238. vector<vector<Point> > contours;//contours的类型,双重的vector
  239. vector<Vec4i> hierarchy;//Vec4i是指每一个vector元素中有四个int型数据。
  240. //阈值
  241. threshold(matSrc, matSrc, 70, 255, THRESH_BINARY);
  242. //imshow("阈值",matSrc);
  243. //寻找轮廓,这里注意,findContours的输入参数要求是二值图像,二值图像的来源大致有两种,第一种用threshold,第二种用canny
  244. findContours(matSrc.clone(), contours, hierarchy,CV_RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));
  245. /// 计算矩
  246. vector<Moments> mu(contours.size());
  247. for (int i = 0; i < contours.size(); i++)
  248. {
  249. mu[i] = moments(contours[i], false);
  250. }
  251. /// 计算中心矩:
  252. vector<Point2f> mc(contours.size());
  253. for (int i = 0; i < contours.size(); i++)
  254. {
  255. mc[i] = Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);
  256. linex[i]=int (mu[i].m10 / mu[i].m00);
  257. //printf("第 %d 个的位置是 %d\r\n",i,linex[i]);
  258. }
  259. /// 绘制轮廓
  260. Mat drawing = Mat::zeros(matSrc.size(), CV_8UC1);
  261. for (int i = 0; i < contours.size(); i++)
  262. {
  263. Scalar color = Scalar(255);
  264. //drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
  265. circle(drawing, mc[i], 4, color, -1, 8, 0);
  266. }
  267. int i,j,temp;
  268. for(j=0;j<=17;j++)//外围循环 循环10次
  269. {
  270. for (i=0;i<16-j;i++)//内层循环 循环 10减去外围的循环的第几次
  271. if (linex[i]>linex[i+1])//比较 比较 a[i]是不是大于a[i+1]是的话
  272. {
  273. temp=linex[i]; //就吧a[i]和a[i+1]互相交换了 这样 大的数就 随着循环
  274. linex[i]=linex[i+1]; //排到 后面了
  275. linex[i+1]=temp;}
  276. }
  277. //for(i=0;i<16;i++)
  278. // printf("%d=%d,",i,linex[i] );//去掉前后两个
  279. // printf("\r\n");
  280. // imshow("outImageX",drawing);
  281. }
  282. void cuttingY( )
  283. {
  284. Mat matSrc = imread("imageROIY.jpg", 0);
  285. //threshold(matSrc, matSrc, 120, 254, THRESH_BINARY_INV);
  286. GaussianBlur(matSrc, matSrc, Size(7, 7), 0);
  287. vector<vector<Point> > contours;//contours的类型,双重的vector
  288. vector<Vec4i> hierarchy;//Vec4i是指每一个vector元素中有四个int型数据。
  289. //阈值
  290. threshold(matSrc, matSrc, 70, 255, THRESH_BINARY);
  291. //寻找轮廓,这里注意,findContours的输入参数要求是二值图像,二值图像的来源大致有两种,第一种用threshold,第二种用canny
  292. findContours(matSrc.clone(), contours, hierarchy,CV_RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));
  293. /// 计算矩
  294. vector<Moments> mu(contours.size());
  295. for (int i = 0; i < contours.size(); i++)
  296. {
  297. mu[i] = moments(contours[i], false);
  298. }
  299. /// 计算中心矩:
  300. vector<Point2f> mc(contours.size());
  301. for (int i = 0; i < contours.size(); i++)
  302. {
  303. mc[i] = Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);
  304. liney[i]=int (mu[i].m01 / mu[i].m00);
  305. //printf("第%d个的位置是%d\r\n",i,liney[i]);
  306. }
  307. /// 绘制轮廓
  308. Mat drawing = Mat::zeros(matSrc.size(), CV_8UC1);
  309. for (int i = 0; i < contours.size(); i++)
  310. {
  311. Scalar color = Scalar(255);
  312. //drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
  313. circle(drawing, mc[i], 4, color, -1, 8, 0);
  314. }
  315. int i,j,temp;
  316. for(j=0;j<=23;j++)//外围循环 循环10次
  317. { for (i=0;i<22-j;i++)//内层循环 循环 10减去外围的循环的第几次
  318. if (liney[i]>liney[i+1])//比较 比较 a[i]是不是大于a[i+1]是的话
  319. { temp=liney[i]; //就吧a[i]和a[i+1]互相交换了 这样 大的数就 随着循环
  320. liney[i]=liney[i+1]; //排到 后面了
  321. liney[i+1]=temp;}
  322. }
  323. // for(i=0;i<22;i++)
  324. // printf("%d=%d,",i,liney[i] );//去掉前后两个
  325. // printf("\r\n");
  326. // imshow("outImageY",drawing);
  327. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/768275
推荐阅读
相关标签
  

闽ICP备14008679号