邊緣檢測(OpenCV)
阿新 • • 發佈:2020-10-29
梯度運算元
不變矩
#include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp> #include <iostream> #include <cmath> using namespace std; using namespace cv; //原圖,原圖的灰度版,目標圖 Mat g_srcImage, g_srcGrayImage, g_dstImage; //Canny邊緣檢測相關變數 Mat g_cannyDetectedEdges; int g_cannyLowThreshold = 1edgedetection;//TrackBar位置引數 //Sobel邊緣檢測相關變數 Mat g_sobelGradient_X, g_sobelGradient_Y; Mat g_sobelAbsGradient_X, g_sobelAbsGradient_Y; int g_sobelKernelSize = 1;//TrackBar位置引數 //Scharr濾波器相關變數 Mat g_scharrGradient_X, g_scharrGradient_Y; Mat g_scharrAbsGradient_X, g_scharrAbsGradient_Y; static void ShowHelpText();static void on_Canny(int, void*);//Canny邊緣檢測視窗滾動條的回撥函式 static void on_Sobel(int, void*);//Sobel邊緣檢測視窗滾動條的回撥函式 void Scharr();// 封裝了Scharr邊緣檢測相關程式碼的函式 void laplacian(); // 封裝了laplacian邊緣檢測相關程式碼的函式 /* 不變矩 */ void hu(Mat image); /* 輪廓 */ Mat src, dst, drawImage; const char* result = "moments_demo"; int threshold_value = 120; int threshold_max = 255; RNG rng(12345); void Moments_demo(int, void*); void moments_demo_start(); int main(int argc, char** argv) { ShowHelpText(); g_srcImage = imread("1.png"); if (!g_srcImage.data) { printf("Oh,no,讀取srcImage錯誤~! \n"); return false; } namedWindow("【原始圖】"); imshow("【原始圖】", g_srcImage); g_dstImage.create(g_srcImage.size(), g_srcImage.type()); cvtColor(g_srcImage, g_srcGrayImage, COLOR_BGR2GRAY); namedWindow("【效果圖】Canny邊緣檢測", WINDOW_AUTOSIZE); namedWindow("【效果圖】Sobel邊緣檢測", WINDOW_AUTOSIZE); createTrackbar("引數值:", "【效果圖】Canny邊緣檢測", &g_cannyLowThreshold, 120, on_Canny); createTrackbar("引數值:", "【效果圖】Sobel邊緣檢測", &g_sobelKernelSize, 3, on_Sobel); on_Canny(0, 0); on_Sobel(0, 0); Scharr(); laplacian(); // moments_demo_start(); waitKey(); return 0; } static void ShowHelpText() { printf("當前使用的OpenCV版本為:" CV_VERSION); printf("\n執行成功,請調整滾動條觀察影象效果\n"); } void on_Canny(int, void*) { // 先使用 3x3核心來降噪 blur(g_srcGrayImage, g_cannyDetectedEdges, Size(3, 3)); // 執行我們的Canny運算元 Canny(g_cannyDetectedEdges, g_cannyDetectedEdges, g_cannyLowThreshold, g_cannyLowThreshold * 3, 3); //先將g_dstImage內的所有元素設定為0 g_dstImage = Scalar::all(0); //使用Canny運算元輸出的邊緣圖g_cannyDetectedEdges作為掩碼,來將原圖g_srcImage拷到目標圖g_dstImage中 g_srcImage.copyTo(g_dstImage, g_cannyDetectedEdges); //顯示效果圖 imshow("【效果圖】Canny邊緣檢測", g_dstImage); //計算邊緣影象不變矩 hu(g_dstImage); } void on_Sobel(int, void*) { Sobel(g_srcImage, g_sobelGradient_X, CV_16S, 1, 0, (2 * g_sobelKernelSize + 1), 1, 1, BORDER_DEFAULT); convertScaleAbs(g_sobelGradient_X, g_sobelAbsGradient_X);//計算絕對值,並將結果轉換成8位 Sobel(g_srcImage, g_sobelGradient_Y, CV_16S, 0, 1, (2 * g_sobelKernelSize + 1), 1, 1, BORDER_DEFAULT); convertScaleAbs(g_sobelGradient_Y, g_sobelAbsGradient_Y);//計算絕對值,並將結果轉換成8位 addWeighted(g_sobelAbsGradient_X, 0.5, g_sobelAbsGradient_Y, 0.5, 0, g_dstImage); imshow("【效果圖】Sobel邊緣檢測", g_dstImage); } void Scharr() // { Scharr(g_srcImage, g_scharrGradient_X, CV_16S, 1, 0, 1, 0, BORDER_DEFAULT); convertScaleAbs(g_scharrGradient_X, g_scharrAbsGradient_X);//計算絕對值,並將結果轉換成8位 Scharr(g_srcImage, g_scharrGradient_Y, CV_16S, 0, 1, 1, 0, BORDER_DEFAULT); convertScaleAbs(g_scharrGradient_Y, g_scharrAbsGradient_Y);//計算絕對值,並將結果轉換成8位 addWeighted(g_scharrAbsGradient_X, 0.5, g_scharrAbsGradient_Y, 0.5, 0, g_dstImage); imshow("【效果圖】Scharr濾波器", g_dstImage); } void laplacian() { Mat result; int ksize = 5; // 當ksize==1時,3*3的拉普拉斯運算元 int depth = CV_16S; // 目標影象的深度,當depth==-1時,為原圖影象深度 Laplacian(g_srcImage, g_dstImage, depth, ksize); // imshow("【效果圖】laplacian濾波器", g_dstImage); convertScaleAbs(g_dstImage, result); // (3 + 1) * 0.25 imshow("Laplacian", result); } void Moments_demo(int, void*) { //提取影象邊緣 Mat canny_out; Canny(dst, canny_out, threshold_value, threshold_value * 2, 3, false); //imshow("canny image", canny_out); //發現輪廓,找到影象輪廓 vector<vector<Point>> contours; vector<Vec4i> hierachy; findContours(canny_out, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0)); //計算每個輪廓物件的矩 vector< Moments> contours_moments(contours.size()); vector<Point2f> centers(contours.size()); for (size_t i = 0; i < contours.size(); i++) { //計算矩 contours_moments[i] = moments(contours[i]); //moments(InputArray array,//輸入資料 //bool binaryImage = false // 是否為二值影象 centers[i] = Point(static_cast<float>(contours_moments[i].m10 / contours_moments[i].m00), static_cast<float>(contours_moments[i].m01 / contours_moments[i].m00)); //影象中心Center(x0, y0)=(m10/m00,m01/m00) } src.copyTo(drawImage); for (size_t i = 0; i < contours.size(); i++) { printf("centers point x:%.2f,y:%.2f\n", centers[i].x, centers[i].y); printf("contours %d Area:%.2f Arc length:%.2f \n", i, contourArea(contours[i]), arcLength(contours[i], true)); Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)); drawContours(drawImage, contours, i, color, 2, LINE_AA, hierachy, 0, Point(0, 0));//繪製輪廓 circle(drawImage, centers[i], 2, color, 2, LINE_AA);//繪製圖形中心 } imshow(result, drawImage); return; } void moments_demo_start() { src = imread("1.png"); if (!src.data) { printf("could not load image...\n"); } char input[] = "gray image"; namedWindow(input, WINDOW_AUTOSIZE); namedWindow(result, WINDOW_AUTOSIZE); //輸入影象轉為灰度影象 cvtColor(src, dst, COLOR_BGR2GRAY); GaussianBlur(dst, dst, Size(3, 3), 0, 0); imshow(input, dst); const char* thresh = "threshold value"; createTrackbar(thresh, result, &threshold_value, threshold_max, Moments_demo); Moments_demo(0, 0); } void hu(Mat image) { cvtColor(image, image, COLOR_BGR2GRAY); Moments mts = moments(image); double hu[7]; HuMoments(mts, hu); cout << endl << "Canny運算元處理後的影象的不變矩 :" << endl; for (int i = 0; i < 7; i++) { cout << "η" << i+1 << '=' << abs(log(abs(hu[i]))) << endl; } }
---------------------continue------------------------------------------