Canny,先Scharr得梯度再Canny,三通道黑色背景展示结果(OpenCV案例源码edge.cpp)

时间:2022-04-18 00:56:56

有所更改,参数不求完备,但求实用。源码参考D:sourceopencv-3.4.9samplescppedge.cpp

#include<opencv2opencv.hpp>
#include<iostream>

using namespace cv;
using namespace std;

int edgeThresh = 1;
int edgeThreshScharr = 1;

Mat image, gray, blurImage, edge1, edge2, cedge;

const string window_name1 = "Edge map : Canny default (Sobel gradient)";
const string window_name2 = "Edge map : Canny with custom gradient (Scharr)";

static void onTrackbar(int, void*) //滑动条的响应函数,格式必须这样
{
    blur(gray, blurImage, Size(3, 3)); //均值滤波
    //直接用Canny
    Canny(blurImage, edge1, edgeThresh, edgeThresh * 3); //图,结果图(二值图),低阈值,高阈值
    
    cedge = Scalar::all(0); //刷新黑色背景
    image.copyTo(cedge, edge1); //image与二值图edge1得到的彩色边缘图,赋值给cedge(三通道黑色矩阵)
    imshow(window_name1, cedge);
    imshow("edge", edge1);
    /// 先用Scharr得到x、y方向的梯度图(灰度图),再用Canny
    Mat dx, dy;
    Scharr(blurImage, dx, CV_16S, 1, 0); //输入图,结果图,颜色深度(16位),x方向梯度(差分阶数),y方向梯度(差分阶数)
    Scharr(blurImage, dy, CV_16S, 0, 1);
    Canny(dx, dy, edge2, edgeThreshScharr, edgeThreshScharr * 3);//x方向输入图(必须16位),y方向输入图,输出图(8位单通道二值图),低阈值,高阈值

    cedge = Scalar::all(0);
    image.copyTo(cedge, edge2);//image与二值图edge1得到的彩色边缘图,赋值给cedge(三通道黑色矩阵)
    imshow(window_name2, cedge);

    //Scharr(blurImage, dx, CV_8U, 1, 0);
    //imshow("x", dx); //x梯度方向灰度图(突出竖条)
    //Scharr(blurImage, dy, CV_8U, 0, 1);
    //imshow("y", dy); //y梯度方向灰度图(突出横条)
}

int main()
{
    image = imread("D:/lena.jpg");
    cedge.create(image.size(), image.type()); //创建与image等大同类型的模板(矩阵)
    //cedge = Scalar::all(0); //矩阵赋值为0,即黑色模板。(注意放到响应函数中执行,每次刷新背景)

    cvtColor(image, gray, COLOR_BGR2GRAY);

    // Create a window
    namedWindow(window_name1, 1); //先创建窗体,再创建滑动条
    namedWindow(window_name2, 1);

    // create a toolbar
    createTrackbar("Canny threshold default", window_name1, &edgeThresh, 100, onTrackbar); //滑动条标签,窗体,起始,终止,响应函数
    createTrackbar("Canny threshold Scharr", window_name2, &edgeThreshScharr, 400, onTrackbar);

    // Show the image
    onTrackbar(0, 0); //执行一次响应函数,格式必须这样

    waitKey(0);
    return 0;
}