• 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; }

     

     

  • 相关阅读:
    [原创] 分享一些linux教程
    [转] linux中pam模块
    [转] 虚拟机VMware3种网络模式(桥接、nat、Host-only)的工作原理
    [转] linux中常用的命令
    dede调用指定的多个栏目导航
    dede留言板BUG解决
    织梦如何实现二级栏目导航的仿制
    DEDE数据库修改
    任务管理器磁盘显示100%
    再次改版轮播图
  • 原文地址:https://www.cnblogs.com/xingyuanzier/p/13280050.html
Copyright © 2020-2023  润新知