參考這個網站,然后自己 找了張圖片試了一下 http://blog.csdn.net/cp562090732/article/details/47804003
// test.cpp : 定義控制台應用程序的入口點。 // #include "stdafx.h" #include "cv.h" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include "highgui.h" #include "cxcore.h" #include <string> #include <stdlib.h> #include <stdio.h> #include <vector> #include <map> using namespace std; using namespace cv; class RectComp//Rect排序 { 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:\\13.jpg"); Mat srcImage2,srcImage3,srcImage4,srcImage5; //namedWindow("hello-1", 1); //imshow("hello-1",srcImage1); // cv::waitKey(0); //圖片變成灰度圖片 cvtColor(srcImage1,srcImage2,CV_BGR2GRAY); //imshow("hello-2",srcImage2); // cv::waitKey(0); //圖片二值化 threshold(srcImage2,srcImage3,200,255,THRESH_BINARY_INV); imshow("hello-3",srcImage3); cv::waitKey(0); //確定腐蝕和膨脹核的大小 Mat element = getStructuringElement(MORPH_RECT, Size(3, 3)); //腐蝕操作 erode(srcImage3,srcImage4,element); //膨脹操作 dilate(srcImage4,srcImage5,element); namedWindow("hello-5", 1); imshow("hello-5", srcImage5 ); cv::waitKey(0); //確定每張答題卡的ROI區域 Mat imag_ch1 = srcImage5(Rect(2,20,268,40)); namedWindow("img1", 1); imshow("img1",imag_ch1); cv::waitKey(0); //提取已經塗好了的選項 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)); 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()); std::map<int,string>listenAnswer; //判斷這部分的答題卡是否都已塗上 for(int t = 0;t<RectCompList.size();t++) { if(RectCompList.at(t).rm.y<5) { listenAnswer[t] = "A"; } else if((RectCompList.at(t).rm.y>5)&&(RectCompList.at(t).rm.y<16)) { listenAnswer[t] = "B"; } else if(RectCompList.at(t).rm.y>16) { 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; } cv::waitKey(0); return 0; }
感覺腐蝕操作的正方形大小選擇很關鍵,過大過小效果都不好。http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.html