边缘检测(OpenCV)

梯度算子

 

不变矩

边缘检测(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;
    }
}
edgedetection

---------------------continue------------------------------------------

上一篇:OpenCV 图像处理(形态学滤波:腐蚀与膨胀,开运算、闭运算、形态学梯度、顶帽、黑帽)


下一篇:前端面试