边缘检测(OpenCV)
梯度算子
不变矩
#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 = 1;//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; } }
角点检测
#include <opencv2/opencv.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace cv; int main() { //以灰度模式载入图像并显示 Mat srcImage = imread("1.jpg", 0); imshow("原始图", srcImage); //进行Harris角点检测找出角点 Mat cornerStrength; cornerHarris(srcImage, cornerStrength, 2, 3, 0.01); //对灰度图进行阈值操作,得到二值图并显示 Mat harrisCorner; threshold(cornerStrength, harrisCorner, 0.00001, 255, THRESH_BINARY); imshow("角点检测后的二值效果图", harrisCorner); waitKey(0); return 0; }
角点检测综合示例
#include <opencv2/opencv.hpp> #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" using namespace cv; using namespace std; #define WINDOW_NAME1 "【程序窗口1】" //为窗口标题定义的宏 #define WINDOW_NAME2 "【程序窗口2】" //为窗口标题定义的宏 Mat g_srcImage, g_srcImage1, g_grayImage; int thresh = 30; //当前阈值 int max_thresh = 175; //最大阈值 void on_CornerHarris(int, void*);//回调函数 static void ShowHelpText(); int main(int argc, char** argv) { ShowHelpText(); //【1】载入原始图并进行克隆保存 g_srcImage = imread("1.jpg", 1); if (!g_srcImage.data) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); return false; } imshow("原始图", g_srcImage); g_srcImage1 = g_srcImage.clone(); //【2】存留一张灰度图 cvtColor(g_srcImage1, g_grayImage, COLOR_BGR2GRAY); //【3】创建窗口和滚动条 namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE); createTrackbar("阈值: ", WINDOW_NAME1, &thresh, max_thresh, on_CornerHarris); //【4】调用一次回调函数,进行初始化 on_CornerHarris(0, 0); waitKey(0); return(0); } void on_CornerHarris(int, void*) { //---------------------------【1】定义一些局部变量----------------------------- Mat dstImage;//目标图 Mat normImage;//归一化后的图 Mat scaledImage;//线性变换后的八位无符号整型的图 //---------------------------【2】初始化--------------------------------------- //置零当前需要显示的两幅图,即清除上一次调用此函数时他们的值 dstImage = Mat::zeros(g_srcImage.size(), CV_32FC1); g_srcImage1 = g_srcImage.clone(); //---------------------------【3】正式检测------------------------------------- //进行角点检测 cornerHarris(g_grayImage, dstImage, 2, 3, 0.04, BORDER_DEFAULT); // 归一化与转换 normalize(dstImage, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat()); convertScaleAbs(normImage, scaledImage);//将归一化后的图线性变换成8位无符号整型 //---------------------------【4】进行绘制------------------------------------- // 将检测到的,且符合阈值条件的角点绘制出来 for (int j = 0; j < normImage.rows; j++) { for (int i = 0; i < normImage.cols; i++) { if ((int)normImage.at<float>(j, i) > thresh + 80) { circle(g_srcImage1, Point(i, j), 5, Scalar(10, 10, 255), 2, 8, 0); circle(scaledImage, Point(i, j), 5, Scalar(0, 10, 255), 2, 8, 0); } } } //---------------------------【4】显示最终效果--------------------------------- imshow(WINDOW_NAME1, g_srcImage1); imshow(WINDOW_NAME2, scaledImage); } static void ShowHelpText() { printf("当前使用的OpenCV版本为:" CV_VERSION); printf("【欢迎来到Harris角点检测示例程序~】"); printf("\n请调整滚动条观察图像效果"); }
shi_Tomashi角点检测
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> using namespace cv; using namespace std; #define WINDOW_NAME "【Shi-Tomasi角点检测】" //为窗口标题定义的宏 Mat g_srcImage, g_grayImage; int g_maxCornerNumber = 33; int g_maxTrackbarNumber = 500; RNG g_rng(12345);//初始化随机数生成器 void on_GoodFeaturesToTrack(int, void*) { //【1】对变量小于等于1时的处理 if (g_maxCornerNumber <= 1) { g_maxCornerNumber = 1; } //【2】Shi-Tomasi算法(goodFeaturesToTrack函数)的参数准备 vector<Point2f> corners; double qualityLevel = 0.01;//角点检测可接受的最小特征值 double minDistance = 10;//角点之间的最小距离 int blockSize = 3;//计算导数自相关矩阵时指定的邻域范围 double k = 0.04;//权重系数 Mat copy = g_srcImage.clone(); //复制源图像到一个临时变量中,作为感兴趣区域 //【3】进行Shi-Tomasi角点检测 goodFeaturesToTrack(g_grayImage,//输入图像 corners,//检测到的角点的输出向量 g_maxCornerNumber,//角点的最大数量 qualityLevel,//角点检测可接受的最小特征值 minDistance,//角点之间的最小距离 Mat(),//感兴趣区域 blockSize,//计算导数自相关矩阵时指定的邻域范围 false,//不使用Harris角点检测 k);//权重系数 //【4】输出文字信息 cout << "\t>此次检测到的角点数量为:" << corners.size() << endl; //【5】绘制检测到的角点 int r = 4; for (int i = 0; i < corners.size(); i++) { //以随机的颜色绘制出角点 circle(copy, corners[i], r, Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255)), -1, 8, 0); } //【6】显示(更新)窗口 imshow(WINDOW_NAME, copy); } //-----------------------------------【ShowHelpText( )函数】---------------------------------- // 描述:输出一些帮助信息 //---------------------------------------------------------------------------------------------- static void ShowHelpText() { printf("当前使用的OpenCV版本为:" CV_VERSION); printf("欢迎来到【Shi-Tomasi角点检测】示例程序\n"); printf("请调整滑动条观察图像效果\n"); } int main() { ShowHelpText(); //【1】载入源图像并将其转换为灰度图 g_srcImage = imread("1.jpg", 1); cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY); //【2】创建窗口和滑动条,并进行显示和回调函数初始化 namedWindow(WINDOW_NAME, WINDOW_AUTOSIZE); createTrackbar("最大角点数", WINDOW_NAME, &g_maxCornerNumber, g_maxTrackbarNumber, on_GoodFeaturesToTrack); imshow(WINDOW_NAME, g_srcImage); on_GoodFeaturesToTrack(0, 0); waitKey(0); return(0); }
亚像素级角点检测
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> using namespace cv; using namespace std; #define WINDOW_NAME "【亚像素级角点检测】" //为窗口标题定义的宏 Mat g_srcImage, g_grayImage; int g_maxCornerNumber = 33; int g_maxTrackbarNumber = 500; RNG g_rng(12345);//初始化随机数生成器 void on_GoodFeaturesToTrack(int, void*) { //【1】对变量小于等于1时的处理 if (g_maxCornerNumber <= 1) { g_maxCornerNumber = 1; } //【2】Shi-Tomasi算法(goodFeaturesToTrack函数)的参数准备 vector<Point2f> corners; double qualityLevel = 0.01;//角点检测可接受的最小特征值 double minDistance = 10;//角点之间的最小距离 int blockSize = 3;//计算导数自相关矩阵时指定的邻域范围 double k = 0.04;//权重系数 Mat copy = g_srcImage.clone(); //复制源图像到一个临时变量中,作为感兴趣区域 //【3】进行Shi-Tomasi角点检测 goodFeaturesToTrack(g_grayImage,//输入图像 corners,//检测到的角点的输出向量 g_maxCornerNumber,//角点的最大数量 qualityLevel,//角点检测可接受的最小特征值 minDistance,//角点之间的最小距离 Mat(),//感兴趣区域 blockSize,//计算导数自相关矩阵时指定的邻域范围 false,//不使用Harris角点检测 k);//权重系数 //【4】输出文字信息 cout << "\n\t>-------------此次检测到的角点数量为:" << corners.size() << endl; //【5】绘制检测到的角点 int r = 4; for (unsigned int i = 0; i < corners.size(); i++) { //以随机的颜色绘制出角点 circle(copy, corners[i], r, Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255)), -1, 8, 0); } //【6】显示(更新)窗口 imshow(WINDOW_NAME, copy); //【7】亚像素角点检测的参数设置 Size winSize = Size(5, 5); Size zeroZone = Size(-1, -1); //此句代码的OpenCV2版为: //TermCriteria criteria = TermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 40, 0.001 ); //此句代码的OpenCV3版为: TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 40, 0.001); //【8】计算出亚像素角点位置 cornerSubPix(g_grayImage, corners, winSize, zeroZone, criteria); //【9】输出角点信息 for (int i = 0; i < corners.size(); i++) { cout << " \t>>精确角点坐标[" << i << "] (" << corners[i].x << "," << corners[i].y << ")" << endl; } } static void ShowHelpText() { printf("当前使用的OpenCV版本为:" CV_VERSION); printf("欢迎来到【亚像素级角点检测】示例程序\n"); printf("请调整滑动条观察图像效果\n"); } int main() { ShowHelpText(); //【1】载入源图像并将其转换为灰度图 g_srcImage = imread("1.jpg", 1); cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY); //【2】创建窗口和滑动条,并进行显示和回调函数初始化 namedWindow(WINDOW_NAME, WINDOW_AUTOSIZE); createTrackbar("最大角点数", WINDOW_NAME, &g_maxCornerNumber, g_maxTrackbarNumber, on_GoodFeaturesToTrack); imshow(WINDOW_NAME, g_srcImage); on_GoodFeaturesToTrack(0, 0); waitKey(0); return(0); }
---------------------continue------------------------------------------
【zlc】