Because my knowledge is still shallow, I can't use python deep learning to identify the numbers here, so I completely use opencv to identify the numbers, and then share and record what I saw and thought in the learning process here
Problems to be solved
This is a number to be recognized. I first extract the ROI of the image, and only the number is left in the extraction result, excluding other unimportant elements,
This is the ROI picture. All we have to do is identify the numbers in the picture,
Ideas for solving problems
1. First, divide the numbers in this picture into five small pictures. Each picture contains a number. Why do you want to divide it? Because we can't let the computer know how much this number is, we can only let the computer identify the features according to the features, and then each feature corresponds to a value. First, post the program for dividing the picture, and then there will be a section of thought explanation below the program
#include <opencv2/core/core.hpp> #include <opencv.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/features2d/features2d.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> #include <ctime> using namespace std ; using namespace cv; #include <map> Mat src_threshold; Mat src_dil; int sunImage(Mat &image); vector<Mat>ROI_image;//Picture to be tested int main() { clock_t start ,finish; start=clock(); Mat src; src=imread("D:\\vspic\\picture\\number6.jpg"); resize(src,src,Size(src.cols/7,src.rows/7)); imshow("src",src); Mat src_gray; cvtColor(src,src_gray,COLOR_BGR2GRAY); //imshow("gsrc_ray",src_gray); Mat src_blur; blur(src_gray,src_blur,Size(9,9)); //GaussianBlur(src_gray,src_blur,Size(11,11),1,1); Mat src_threshold; threshold(src_blur,src_threshold,150,255,THRESH_OTSU); //imshow("src_threshold",src_threshold); Mat src_canny; Canny(src_threshold,src_canny,125,255,3); //imshow("src_canny",src_canny); vector<vector<Point>>contours_src; vector<Vec4i>hierarchy_src(contours_src.size()); findContours(src_canny,contours_src,hierarchy_src,RETR_EXTERNAL,CHAIN_APPROX_NONE); Rect rect_s; Rect choose_rect; for (size_t i=0;i<contours_src.size();i++) { rect_s=boundingRect(contours_src[i]); double width=rect_s.width; double height= rect_s.height; double bizhi=width/height; if (bizhi>1.5&&height>50) { /*rectangle(src,rect_s.tl(),rect_s.br(),Scalar(255,255,255),1,1,0);*/ choose_rect=Rect(rect_s.x+20,rect_s.y+30,rect_s.x-30,rect_s.y-108); } } Mat roi; roi=src(choose_rect); //imshow("src_",roi); Mat img =roi; Mat gray_img; // Generate gray image cvtColor(img, gray_img, CV_BGR2GRAY); // Gaussian blur Mat img_gau; GaussianBlur(gray_img, img_gau, Size(3, 3), 0, 0); // Threshold segmentation Mat img_seg; threshold(img_gau, img_seg, 0, 255, THRESH_BINARY + THRESH_OTSU); Mat element; element=getStructuringElement(MORPH_RECT,Size(8,8)); erode(img_seg,src_dil,element); //imshow("src_dil",src_dil); // Edge detection, contour extraction Mat img_canny; Canny(src_dil, img_canny, 200, 100); //imshow("canny",img_canny); vector<vector<Point>> contours; vector<Vec4i> hierarchy(contours.size()); findContours(img_canny, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point());//Find contour int size = (int)(contours.size());//Number of contours //cout<<size<<endl; 6 // Saves the sequence number of the symbol border vector<int> num_order;//Define an integer int container map<int, int> num_map;//Container requires two template parameters: keyword and template object. Here, an int is defined as the index and has an associated pointer to int for (int i = 0; i < size; i++) { // Get border data Rect number_rect = boundingRect(contours[i]); int width = number_rect.width;//Gets the width of the rectangle int height = number_rect.height;//Gets the height of the rectangle // Remove the small interference frame and filter out the appropriate area if (width > img.cols/20 ) { rectangle(img,number_rect.tl(),number_rect.br(),Scalar(255,255,255),1,1,0);//draw rectangle imshow("img",img);//Show rectangle num_order.push_back(number_rect.x);//Put the x coordinate of the rectangle into number_ In the order container, add a new element to the end of the vector, //The position is the next element of the current element num_map[number_rect.x] = i;//Store the key value pair, number, into the map_ Rect. X is the keyword and i is the value /*Put the x coordinate of the rectangular box together with the corresponding i value into the map container to form a one-to-one corresponding key value pair */ } } // Extract in symbolic order sort(num_order.begin(), num_order.end());/*Put number_ The contents of the order container are arranged from small to large, which is the coordinate of X*/ for (int i = 0; i < num_order.size(); i++) { Rect number_rect = boundingRect(contours[num_map.find(num_order[i])->second]);//num_ There are coordinates in order //cout<<"num_ The value of map is: "< < num"_ map.find(num_ order[i])->second<<endl; Rect choose_rect(number_rect.x, 0, number_rect.width, img.rows);//The coordinates of X and Y in the upper left corner of the rectangle and the width and height of the rectangle Mat number_img = img(choose_rect); resize(number_img,number_img,Size(30,100));//Normalized size ROI_image.push_back(number_img);//Save as picture to be tested //imshow("number" + to_string(i), number_img); char name[50]; sprintf_s(name,"D:\\vs2012\\model\\%d.jpg",i);//Save template imwrite(name, number_img); } cout<<"Image segmentation completed"<<endl; //Load template vector<Mat>temptImage;//Storage template for (int i=0;i<4;i++) { char name[50]; sprintf_s(name,"D:\\vs2012\\model\\%d.jpg",i); Mat temp; temp=imread(name); //Cout < < number of channels to load template pictures: < < temp. Channels() < < endl; temptImage.push_back(temp); } vector<int>seq;//Storage sequence results for (int i=0;i<ROI_image.size();i++) { Mat subImage; int sum=0; int min=50000; int seq_min=0;//Record the smallest and corresponding numbers for (int j=0;j<4;j++) { absdiff(ROI_image[i],temptImage[j],subImage);//Subtract template picture pixels from picture pixels to be tested sum=sunImage(subImage);//Statistical pixel sum if (sum<min) { min=sum; seq_min=j; } sum=0; } seq.push_back(seq_min); } cout<<"Output digital matching results:";//endl means line feed for (int i=0;i<seq.size();i++)//Output the result with the decimal point fixed in the third place { cout<<seq[i]; if (i==1) { cout<<"."; } } finish=clock(); double all_time=double(finish-start)/CLOCKS_PER_SEC; /*cout<<"The total running time is: "< < all"_ time<<endl;*/ waitKey(0); return 0; } //Calculate pixel sum int sunImage(Mat &image) { int sum=0; for (int i=0;i<image.cols;i++) { for (int j=0;j<image.rows;j++) { sum+=image.at<uchar>(j,i); } } return sum; }
The overall idea is like this: the 10 numbers 0-9 have been segmented and saved, that is, the template. Then we segment the pictures to be tested, and then read the template pictures from the 0-9 template folder. Let the segmented pictures to be tested be subtracted from the 10 templates one by one, and then count their pixels and, If this is the lowest of the 10, then they are the same number, and then the output value can be. After segmentation, it is probably like this
The above is the first method, and then there is the second method, which is the threading method, which is identified according to the digital characteristics of transistors
This is the characteristic of transistor numbers. Each 0-9 number is different. We will introduce it in detail in the next article