Opencv識別答題卡

轉自:http://blog.csdn.net/cp562090732/article/details/47804003#comments

OpenCV處理答題卡的軟件,用於統計答題卡中選擇題的得分。

1. 主要步驟

  •     讀取圖片
  •     圖片轉化爲灰度圖
  •     圖片設定閾值
  •     開運算(先腐蝕,後膨脹)
  •     指定答題區域
  •     找到塗選框
  •     根據塗選框的座標確定所塗選的選項及題號

2. 具體實現

#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include "opencv2/imgproc.hpp"
#include <opencv2/highgui.hpp>
#include <iostream>

using namespace cv;
using namespace std;

#include <map>

class RectComp
{  
public:
	Rect rm;  
	RectComp(Rect rms)  
	{  
		rm = rms;  
	}  
	bool operator < (const RectComp& ti) const  
	{  
		return rm.x< ti.rm.x;  
	}  
};

int main()  
{  
	//裝載圖片  
	Mat srcImage1= imread("D:\\opencv_image\\images\\20150820103614491.png");   
	namedWindow("hello-1", 1);  
	imshow("hello-1", srcImage1 ); 
	Mat srcImage2,srcImage3,srcImage4,srcImage5;  

	//圖片變成灰度圖片  
	cvtColor(srcImage1,srcImage2,CV_BGR2GRAY);  
	//圖片二值化  
	threshold(srcImage2,srcImage3,200,255,THRESH_BINARY_INV);  

	//確定腐蝕和膨脹核的大小  
	Mat element = getStructuringElement(MORPH_RECT, Size(4, 4));  
	//腐蝕操作  
	erode(srcImage3,srcImage4,element);  
	//膨脹操作  
	dilate(srcImage4,srcImage5,element);  

	namedWindow("hello-5", 1);  
	imshow("hello-5", srcImage5 );  

	//確定每張答題卡的ROI區域  
	Mat imag_ch1 = srcImage5(Rect(0,30,100,60));  
	namedWindow("img1", 1);  
	imshow("img1",imag_ch1);  

	//提取已經塗好了的選項  
	std::vector<std::vector<cv::Point> > chapter1;  
	findContours(imag_ch1,chapter1,RETR_EXTERNAL,CHAIN_APPROX_SIMPLE);  
	Mat result(imag_ch1.size(), CV_8U , cv::Scalar(255)) ;  
	cv::drawContours(result,chapter1,-1,cv::Scalar(0),2);  
	namedWindow("resultImage", 1);  
	cv::imshow("resultImage" , result);  

	vector<RectComp>RectCompList;  
	for(int i = 0;i<chapter1.size();i++)  
	{  
		Rect rm= cv::boundingRect(cv::Mat(chapter1[i]));  
		RectComp *ti = new RectComp(rm);  
		RectCompList.push_back(*ti);  
		//         printf("Rect %d x = %d,y = %d \n",i,rm.x,rm.y);  
	}  
	sort(RectCompList.begin(),RectCompList.end());  
	map<int,string>listenAnswer;  
	//判斷這部分的答題卡是否都已塗上  
	for(int t = 0;t<RectCompList.size();t++)  
	{  
		if(RectCompList.at(t).rm.y<=22)  
		{  
			listenAnswer[t] = "A";  
		}  
		else if((RectCompList.at(t).rm.y>22)&&(RectCompList.at(t).rm.y<=34))  
		{  
			listenAnswer[t] = "B";  
		}  
		else if(RectCompList.at(t).rm.y>34)  
		{  
			listenAnswer[t] = "C";  
		}  
		printf("sorted %d x = %d,y = %d \n",t,RectCompList.at(t).rm.x,RectCompList.at(t).rm.y);  
	}  
	for(map<int,string>::iterator it = listenAnswer.begin();it!=listenAnswer.end();++it)  
	{  
		cout<<"num:"<<it->first+1<<","<<"answer:"<<it->second<<endl;  
	}  

	waitKey(0);  
	return 0;  
}  


3. 結果




發佈了111 篇原創文章 · 獲贊 30 · 訪問量 57萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章