行远-自迩

导航

7.边缘提取

一、算法原理

滤波器从效果分:平滑和锐化。

  

 

 

 二、核函数设计

       1. sobel 梯度算子

 

 

       算法实现:

Mat sobel_filter(Mat img, bool horizontal)
{
    int height = img.rows;
    int width = img.cols;
    cv::Mat out = cv::Mat::zeros(height, width, CV_8UC1);

    double kernel[kernel_size][kernel_size] = { 1,2,1,0,0,0,-1,-2,-1 };
    if (horizontal)
    {
        kernel[0][1] = 0;
        kernel[2][1] = 0;
        kernel[1][0] = 2;
        kernel[1][2] = -2;
    }
    int pad = floor(kernel_size / 2);

    double v = 0;
    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            v = 0;
            for (int dy = -pad; dy < pad + 1; dy++)
            {
                for (int dx = -pad; dx < pad + 1; dx++)
                {
                    if ((y + dy) >= 0 && (x + dx) >= 0 && (y + dy) < height && (x + dx) < width)
                        v += img.at<uchar>(y + dy, x + dx) * kernel[dy + pad][dy + pad];
                }
            }
            v = fmax(v, 0);
            v = fmin(v, 255);
            out.at<uchar>(y, x) = (uchar)v;
        }
    }
    return out;
}

2.prewitt 算子

 

 

 算法实现:

Mat prewitt_filter(const Mat& img, bool horizontal)
{
    int height = img.rows;
    int width = img.cols;

    // prepare output
    cv::Mat out = cv::Mat::zeros(height, width, CV_8UC1);

    double kernel[3][3] = { -1,-1,-1,0,0,0,1,1,1 };
    if (horizontal)
    {
        kernel[0][1] = 0;
        kernel[0][2] = 1;
        kernel[1][0] = -1;
        kernel[1][2] = 1;
        kernel[2][0] = -1;
        kernel[2][1] = 0;
    }
    int pad = floor(3 / 2);
    double v = 0;

    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            v = 0;
            for (int dy = -pad; dy < pad + 1; dy++)
            {
                for (int dx = -pad; dx < pad + 1; dx++)
                {
                    if ((y + dy) >= 0 && (x + dx) >= 0 && (y + dy) < height && (x + dx) < width)
                    {
                        v += img.at<uchar>(y + dy, x + dx) * kernel[dy + pad][dx + pad];
                    }
                }
            }
            v = fmax(v, 0);
            v = fmin(v, 255);
            out.at<uchar>(y, x) = (uchar)v;
        }
    }
    return out;
}

3.Laplace 算子

 

 

       算法实现

Mat laplascian_filter(Mat& img)
{
    int height = img.rows;
    int width = img.cols;

    // prepare output
    cv::Mat out = cv::Mat::zeros(height, width, CV_8UC1);
    double kernel[3][3] = { 0,1,0,1,-4,1,0,1,0 };
    int pad = floor(3 / 2);
    double v = 0;

    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            v = 0;
            for (int dy = -pad; dy < pad + 1; dy++)
            {
                for (int dx = -pad; dx < pad + 1; dx++)
                {
                    if ((y + dy) >= 0 && (x + dx) >= 0 && (y + dy) < height && (x + dx) < width)
                    {
                        v += img.at<uchar>(y + dy, x + dx) * kernel[dy + pad][dx + pad];
                    }
                }
            }
            v = fmax(v, 0);
            v = fmin(v, 255);
            out.at<uchar>(y, x) = (uchar)v;
        }
    }
    return out;
}

4. robert 算子

 

 

5.差分滤波器

 

 

 算法实现

Mat diff_filter(const Mat& img, bool horizontal)
{
    int height = img.rows;
    int width = img.cols;
    cv::Mat out = cv::Mat::zeros(height, width, CV_8UC1);

    //纵向
    double kernel[kernel_size][kernel_size] = { {0, -1, 0}, {0, 1, 0}, {0, 0, 0} };
    
    //横向
    if (horizontal) {
        kernel[0][1] = 0;
        kernel[1][0] = -1;
    }

    int pad = floor(kernel_size / 2);
    double v = 0;

    // filtering  
    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            v = 0;
            for (int dy = -pad; dy < pad + 1; dy++)
            {
                for (int dx = -pad; dx < pad + 1; dx++)
                {
                    if (((y + dy) >= 0) && ((x + dx) >= 0) && ((y + dy) < height) && ((x + dx) < width))
                    {
                        v += img.at<uchar>(y + dy, x + dx) * kernel[dy + pad][dx + pad];
                    }
                }
            }
            v = fmax(v, 0);
            v = fmin(v, 255);
            out.at<uchar>(y, x) = (uchar)v;
        }
    }
    return out;
}

6.Emboss 滤波

        

 

 

       算法实现

Mat emboss_filter(Mat& img)
{
    int height = img.rows;
    int width = img.cols;

    // prepare output
    cv::Mat out = cv::Mat::zeros(height, width, CV_8UC1);
    double kernel[3][3] = { -2,-1,0,-1,1,1,0,1,2};
    int pad = floor(3 / 2);
    double v = 0;

    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            v = 0;
            for (int dy = -pad; dy < pad + 1; dy++)
            {
                for (int dx = -pad; dx < pad + 1; dx++)
                {
                    if ((y + dy) >= 0 && (x + dx) >= 0 && (y + dy) < height && (x + dx) < width)
                    {
                        v += img.at<uchar>(y + dy, x + dx) * kernel[dy + pad][dx + pad];
                    }
                }
            }
            v = fmax(v, 0);
            v = fmin(v, 255);
            out.at<uchar>(y, x) = (uchar)v;
        }
    }
    return out;
}

7. loG滤波

 

 算法实现

Mat log_filter(Mat& img,float sigma)
{
    int height = img.rows;
    int width = img.cols;

    // prepare output
    double kernel[kernel_size][kernel_size] = { 0};
    cv::Mat out = cv::Mat::zeros(height, width, CV_8UC1);
    int pad = floor(kernel_size / 2);
    double kernel_sum = 0;
    double y = 0;
    double x = 0;
    for (int i = 0; i < kernel_size; i++)
    {
        for (int j = 0; j < kernel_size; j++)
        {
            y = i - pad;
            x = j - pad;
            kernel[i][j] = (y*y + x * x - sigma * sigma) / (2 * M_pi*pow(sigma, 6))*exp(-(y*y + x * x) / (2 * sigma*sigma));
            kernel_sum += kernel[i][j];
            cout << kernel[i][j] << "   ";
        }
        cout << endl;
    }

//做了归一化处理,此处如果没有,得到结果不尽人意,甚至出现全黑,或者全白
for (int y = 0; y < kernel_size; y++) { for (int x = 0; x < kernel_size; x++) { kernel[y][x] /= kernel_sum; cout << kernel[y][x] << " "; } cout << endl; } double v = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { v = 0; for (int dy = -pad; dy < pad + 1; dy++) { for (int dx = -pad; dx < pad + 1; dx++) { if ((y + dy) >= 0 && (x + dx) >= 0 && (y + dy) < height && (x + dx) < width) { v += img.at<uchar>(y + dy, x + dx) * kernel[dy + pad][dx + pad]; } } } v = fmax(v, 0); v = fmin(v, 255); out.at<uchar>(y, x) = (uchar)v; } } return out; }

 

 

 

 

 

 

 

posted on 2020-07-10 16:50  行远-自迩  阅读(237)  评论(0编辑  收藏  举报