Opencv 传统形态学对填涂准考证号识别的一个例子
背景:.对于填涂类型的准考证号或则答案,用传统的边框检测,使用合适的阈值,将对象检测出来,然后根据排列,可以得到学号或则填涂的选项。
不足:挺依赖印刷的质量和填涂的规范性,对于大批量的识别,不能保证识别的准确性。
#include <iostream> #include<opencv2/opencv.hpp> using namespace std; using namespace cv; int main() { Mat img = imread("d:\\Images\\stucard\\2.jpg", cv::IMREAD_UNCHANGED); if (img.empty()) { printf("图像无法正常加载\n"); return 0; } Mat gray; if (img.channels() > 1) cv::cvtColor(img, gray, COLOR_RGB2GRAY); else gray = img.clone(); Mat result_Color_img; cvtColor(gray, result_Color_img, COLOR_GRAY2BGR); cv::Ptr<cv::CLAHE> clahe = cv::createCLAHE(2.0, cv::Size(8, 8)); cv::Mat tmpresult; clahe->apply(gray, tmpresult); cv::GaussianBlur(tmpresult, tmpresult, cv::Size(3, 3), 0); cv::Mat binary; cv::threshold(tmpresult, binary, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU); std::vector<std::vector<cv::Point>> contours; cv::findContours(binary, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector<cv::Rect> rectarray; double epsilon = 0.02; for (const auto& contour : contours) { cv::Rect rect = cv::boundingRect(contour); int rectsize = 0; if (rect.width < 60 && rect.height < 36 && rect.width>12 && rect.height >12) { double contourArea = cv::contourArea(contour); double rectArea = rect.width * rect.height; if (contourArea / rectArea > 0.4) { std::vector<cv::Point> approx; cv::approxPolyDP(contour, approx, epsilon * cv::arcLength(contour, true), true); if (approx.size() >= 4) { rectarray.push_back(rect); cv::rectangle(result_Color_img, rect, Scalar(0, 0, 255), 2); } } } } namedWindow("original", WINDOW_FREERATIO); int window_width = 400; resizeWindow("original", Size(window_width, window_width * img.rows / img.cols)); imshow("original", result_Color_img); waitKey(0); destroyAllWindows(); return 0; }
结果:

 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号