最小外接矩形(ROI)
阿新 • • 發佈:2019-02-08
//---------------------------------【標頭檔案、名稱空間包含部分】---------------------------- // 描述:包含程式所使用的標頭檔案和名稱空間 //------------------------------------------------------------------------------------------------ #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> using namespace cv; using namespace std; //-----------------------------------【巨集定義部分】-------------------------------------------- // 描述:定義一些輔助巨集 //------------------------------------------------------------------------------------------------ #define WINDOW_NAME1 "【原始圖】" //為視窗標題定義的巨集 #define WINDOW_NAME2 "【影象外界矩形輪廓】" //為視窗標題定義的巨集 #define WINDOW_NAME3 "【輪廓提取影象】" //-----------------------------------【全域性變數宣告部分】-------------------------------------- // 描述:全域性變數的宣告 //----------------------------------------------------------------------------------------------- Mat g_srcImage; Mat g_grayImage; RNG g_rng(12345); Mat g_cannyMat_output; vector<vector<Point> > g_vContours; vector<Vec4i> g_vHierarchy; vector<Point> contour; int g_nThick = 0; Scalar color; Mat dst = Mat::zeros(g_cannyMat_output.rows, g_cannyMat_output.cols, CV_8UC3); vector<vector<Point> > contours_poly(g_vContours.size()); //-----------------------------------【全域性變數宣告部分】-------------------------------------- // 描述:全域性變數的宣告 //----------------------------------------------------------------------------------------------- void on_ThreshChange(int, void*); //-----------------------------------【main( )函式】-------------------------------------------- // 描述:控制檯應用程式的入口函式,我們的程式從這裡開始執行 //----------------------------------------------------------------------------------------------- int main(int argc, char** argv) { //【0】改變console字型顏色 system("color 9F"); // 讀入原影象, 返回3通道影象資料 g_srcImage = imread("32.jpg", 1); if (!g_srcImage.data) { printf("讀取圖片錯誤,請確定目錄下是否有imread函式指定圖片存在~! \n"); return false; } imshow(WINDOW_NAME1, g_srcImage); imwrite("原始圖.jpg", g_srcImage);
// 把原影象轉化成灰度影象並進行平滑 cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY); //二值化 threshold(g_grayImage, g_grayImage, 145, 255, 1); //imshow("二值化", g_grayImage); //imwrite("二值化.jpg", g_grayImage); //膨脹操作 Mat element = getStructuringElement(MORPH_RECT, Size(3, 3)); erode(g_grayImage, g_grayImage, element); dilate(g_grayImage, g_grayImage, element); dilate(g_grayImage, g_grayImage, element); dilate(g_grayImage, g_grayImage, element);
//去噪操作
blur(g_grayImage, g_grayImage, Size(3, 3));
imshow("腐膨", g_grayImage);
//呼叫on_ThreshChange函式
on_ThreshChange(0, 0);
waitKey(0); return(0); } //-----------------------------------【on_ThreshChange( )函式】------------------------------- // 描述:回撥函式 //----------------------------------------------------------------------------------------------- void on_ThreshChange(int, void*) { // 使用Canndy檢測邊緣 Canny(g_grayImage, g_cannyMat_output, 150, 255, 3); namedWindow("邊緣檢測", WINDOW_AUTOSIZE); imshow("邊緣檢測", g_cannyMat_output); // imwrite("最終輪廓.jpg", g_cannyMat_output); Mat dst = Mat::zeros(g_cannyMat_output.rows, g_cannyMat_output.cols, CV_8UC3); // 找到輪廓 findContours(g_cannyMat_output, g_vContours, g_vHierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point(0, 0)); int m = g_vContours.size();//得到輪廓的數量 int n = 0; vector<RotatedRect> minRect(g_vContours.size()); Mat DstImg; for (int i = 0; i < m; ++i) { n = g_vContours[i].size(); for (int j = 0; j<n; ++j) { contour.push_back(g_vContours[i][j]);//讀取每個輪廓的點 } double Length = arcLength(g_vContours[i], true); //取得輪廓周長 minRect[i] = minAreaRect(Mat(g_vContours[i])); if (Length>1000 && Length < 1200)//只畫出符合周長範圍的輪廓 { Scalar color(255, 255, 255); drawContours(dst, g_vContours, i, color, 1, 8, g_vHierarchy);//繪製輪廓 Point2f rect_points[4]; minRect[i].points(rect_points); /* for (int j = 0; j < 4; j++) { line(dst, rect_points[j], rect_points[(j + 1) % 4], color, 1, 8); }*/ CvPoint2D32f rectpoints[4]; cvBoxPoints(minRect[i], rectpoints); cout << "angle:\n" << (float)minRect[i].angle << endl;//輸出角度 cout << "center:\n" << minRect[i].center << endl;//輸出外接矩形的中心 cout << "size:\n" << minRect[i].size << endl;//矩形的寬和高 cout << "(x0,y0):\n" << rect_points[0] << endl;//獲取矩形的四個點 cout << "(x1,y1):\n" << rect_points[1] << endl; cout << "(x2,y2):\n" << rect_points[2] << endl; cout << "(x3,y3):\n" << rect_points[3] << endl; float a = rect_points[0].x;//獲取外接矩形的左上X座標的值 float b = rect_points[0].y; float c = rect_points[1].x; float d = rect_points[1].y; float e = rect_points[2].x; float f = rect_points[2].y; float g = rect_points[3].x; float h = rect_points[3].y; float angle = minRect[i].angle; Rect brect = minRect[i].boundingRect(); rectangle(g_srcImage, brect, Scalar(255, 0, 0)); imshow(WINDOW_NAME2, g_srcImage); // namedWindow("DstImg", 1); g_srcImage(brect).copyTo(DstImg); imwrite("DstImg.jpg", DstImg); imshow(WINDOW_NAME3, DstImg); } contour.clear(); } namedWindow("src", 1); imshow("src", dst); }
輸出的外接矩形資訊圖
符合周長範圍的輪廓
在原圖上標出最小外接矩形以及輸出最小外接矩形
根據 findContours 函式寫的一個小程式,可能有許多不到位的,期待大家批評指正,相互交流!