To improve the robustness and application area of the algorithm, we further improve the algorithm.
Possible problems we may encounter are:
Shape of target is not rectangle
Dirty marks or obstacles
Incomplete shape of targets
Partly connected with other objects
Focusing on these problems, we improved the algorithm by adding double contour detection, adjusting optimal threshold and so on.
code:
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <time.h> #include <opencv2/core/core.hpp> #include <opencv2/opencv.hpp> using namespace cv; using namespace std; /**************Definitons*************/ #define MAXRECT 100 #define BUF_SIZE 256 #define CLIENT_ADDRESS "10.220.12.109" #define LISTEN_PORT 2000 #define ID "50-0503334900" #define THRESH 15 #define AREALIMIT 3000.0 /**************Variables**************/ vector<RotatedRect> rectProfile; vector< vector<Point> > contoursRect; vector< vector<Point> > contours; vector<int> selected; char buf[BUF_SIZE]; /**************Functions**************/ bool Check(vector<Point> con){ double area = abs(contourArea(con, 1)); printf("%lf\n", area); if (area < AREALIMIT) return false; return true; } void ImageProcess(){ Mat img = imread("total.jpg", CV_LOAD_IMAGE_GRAYSCALE);//sample00012_5.BMP Mat imgCanny; Canny(img, imgCanny, THRESH, THRESH * 3); imshow("imgCanny", imgCanny); imwrite("1.ImageCanny.jpg",imgCanny); //dilate and erode to connect seperate contour lines Mat img_dilate,img_erode; dilate ( imgCanny, img_dilate, Mat()); imshow("Imagedilate", img_dilate); imwrite("2.Imagedilate.jpg",img_dilate); erode ( img_dilate, img_erode, Mat()); imshow("Imageerode", img_erode); imwrite("3.Imageerode.jpg",img_erode); img_dilate.release(); waitKey(); findContours(img_erode, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); img_erode.release(); Mat cc = Mat::zeros(imgCanny.rows, imgCanny.cols, CV_8UC3); for (int j = 0; j < contours.size(); j++){ Scalar color(rand()&255, rand()&255, rand()&255); drawContours(cc, contours, j, color); } imshow("ImageContours", cc); imwrite("4.ImageContours.jpg",cc); cc.release(); int n = 0; contoursRect.clear(); for (unsigned int i = 0; i < contours.size(); i++){ //check size if (Check(contours[i])){ contoursRect.push_back(contours[i]); n++; selected.push_back(i); } } printf("%d\n", n); Mat ccc = Mat::zeros(imgCanny.rows, imgCanny.cols, CV_8UC3); for (int i = 0; i < n; i++){ Scalar color(rand()&255, rand()&255, rand()&255); drawContours(ccc, contoursRect, i, color,CV_FILLED); } imshow("ImageRecQualified", ccc); imwrite("5.ImageRecSizeQualified.jpg",ccc); waitKey(); destroyAllWindows(); rectProfile.clear(); //MORPH_OPEN to seperate connected rect Mat minrect= Mat::zeros(imgCanny.rows, imgCanny.cols, CV_8UC3); Mat element = getStructuringElement(MORPH_ELLIPSE, Size(28,28)); morphologyEx(ccc,minrect,MORPH_OPEN,element); imshow("MORPH_OPEN", minrect); imwrite("6.ImageMORPH_OPEN.jpg",minrect); ccc.release(); waitKey(); //find contour again Mat minrectgrey=Mat::zeros(imgCanny.rows, imgCanny.cols, CV_8UC1);; cvtColor(minrect,minrectgrey,CV_BGR2GRAY); Mat imgCanny2= Mat::zeros(imgCanny.rows, imgCanny.cols, CV_8UC1);; Canny(minrectgrey, imgCanny2, 1,10); imshow("imgCanny2", imgCanny2); imwrite("7.ImageCanny2.jpg",imgCanny2); contours.clear(); findContours(imgCanny2, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); n = 0; contoursRect.clear(); for (unsigned int i = 0; i < contours.size(); i++){ if (Check(contours[i])){ contoursRect.push_back(contours[i]); n++; selected.push_back(i); } } printf("%d\n", n); Mat ccc2 = Mat::zeros(imgCanny.rows, imgCanny.cols, CV_8UC3); for (int i = 0; i < n; i++){ Scalar color(rand()&255, rand()&255, rand()&255); drawContours(ccc2, contoursRect, i, color,CV_FILLED); } imshow("ImageRecQualified2", ccc2); imwrite("8.ImageRecQualified2.jpg",ccc2); waitKey(); img = imread("total.jpg"); Point2f vertices[4]; for (int i = 0; i < n; i++) { rectProfile.push_back(minAreaRect(contoursRect[i])); rectProfile[i].points(vertices); Scalar color(rand()&255, rand()&255, rand()&255); for (int i = 0; i < 4; i++){ line(img, vertices[i], vertices[(i+1)%4], color,5); } rectangle(img,Point((vertices[0].x+vertices[2].x)/2-1,(vertices[0].y+vertices[2].y)/2-1),Point((vertices[0].x+vertices[2].x)/2+1,(vertices[0].y+vertices[2].y)/2+1),color,5); } imshow("ImageRec", img); imwrite("9.ImageRec.jpg",img); waitKey(); } int main(){ contours.reserve(100000*sizeof(Point)); ImageProcess(); }
This article is among the series of FDUROP project. More information: http://104.131.150.53/thinkcmfx/index.php?g=&m=article&a=index&id=17