【基於特徵點的矯正和輪廓二維碼檢測】
阿新 • • 發佈:2018-11-05
參考牧野大仙的實現過程,自己在其基礎上進行了相關改進。
二維碼的檢測過程一般要用到矯正過程,而矯正需要得到相關透視變換的變換矩陣H;變換矩陣H則是由特徵角點得到。具體如下:
#include<opencv2\opencv.hpp> #include <iostream> using namespace std; using namespace cv; int main(int argc, char*argv[]){ Mat imageSource = imread("123.PNG", 0); Mat image; imageSource.copyTo(image); GaussianBlur(image, image, Size(3, 3), 0); //濾波 threshold(image, image, 100, 255, CV_THRESH_BINARY); //二值化 imshow("二值化", image); Mat element = getStructuringElement(2, Size(7, 7)); //膨脹腐蝕核 //morphologyEx(image,image,MORPH_OPEN,element); for (int i = 0;i<10;i++){ erode(image, image, element); i++; } imshow("腐蝕s", image); Mat image1; erode(image, image1, element); image1 = image - image1; imshow("邊界", image1); //尋找直線 邊界定位也可以用findContours實現 vector<Vec2f>lines; HoughLines(image1, lines, 1, CV_PI / 150, 250, 0, 0); Mat DrawLine = Mat::zeros(image1.size(), CV_8UC1); for (int i = 0;i<lines.size();i++) { float rho = lines[i][0]; float theta = lines[i][1]; Point pt1, pt2; double a = cos(theta), b = sin(theta); double x0 = a*rho, y0 = b*rho; pt1.x = cvRound(x0 + 1000 * (-b)); pt1.y = cvRound(y0 + 1000 * a); pt2.x = cvRound(x0 - 1000 * (-b)); pt2.y = cvRound(y0 - 1000 * a); line(DrawLine, pt1, pt2, Scalar(255), 1, CV_AA); } imshow("直線", DrawLine); Point2f P1[4]; Point2f P2[4]; vector<Point2f>corners; goodFeaturesToTrack(DrawLine, corners, 4, 0.1, 10, Mat()); //角點檢測 for (int i = 0;i<corners.size();i++) { circle(DrawLine, corners[i], 3, Scalar(255), 3); P1[i] = corners[i]; } imshow("交點", DrawLine); int width = P1[1].x - P1[0].x; int hight = P1[2].y - P1[0].y; P2[0] = P1[0]; P2[1] = Point2f(P2[0].x + width, P2[0].y); P2[2] = Point2f(P2[0].x, P2[1].y + hight); P2[3] = Point2f(P2[1].x, P2[2].y); Mat elementTransf; elementTransf = getAffineTransform(P1, P2); warpAffine(imageSource, imageSource, elementTransf, imageSource.size(), 1, 0, Scalar(255)); imshow("校正", imageSource); namedWindow("Source Window", 0); imshow("Source Window", imageSource); vector<vector<Point> > contours; vector<Vec4i> hierarchy; /// 閾值化檢測邊界 /// 尋找輪廓 bitwise_not(imageSource, imageSource); Point2f p[4]; findContours(imageSource, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); vector<RotatedRect>minrect(contours.size()); Mat drawing = Mat::zeros(imageSource.size(), imageSource.type()); for (int i = 0;i < contours.size();i++) { RotatedRect rec = minAreaRect(Mat(contours[i])); rec.points(p); for (int j = 0; j < 4; j++) { line(imageSource, p[j],p[(j + 1) % 4], Scalar(255,244,55), 1, 8); cout << p[j].x << " " <<p[j].y << endl; } } imshow("drawing", imageSource); waitKey(); return 0; }
這裡我們採用RotatedRect函式對查詢的輪廓進行覆蓋,這裡主要對父輪廓進行了查詢;
原圖:
矯正圖:
效果圖:查詢
參考部落格: https://www.cnblogs.com/skyfsm/p/7324346.html