zoukankan      html  css  js  c++  java
  • 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; }

     

     

  • 相关阅读:
    解决SharePoint 文档库itemadded eventhandler导致的上传完成后,编辑页面保持报错的问题,错误信息为“该文档已经被编辑过 the file has been modified by...”
    解决SharePoint 2013 designer workflow 在发布的报错“负载平衡没有设置”The workflow files were saved but cannot be run.
    随机实例,随机值
    Spring4笔记
    struts2笔记(3)
    struts2笔记(2)
    获取文本的编码类型(from logparse)
    FileUtil(from logparser)
    DateUtil(SimpleDateFormat)
    struts2笔记
  • 原文地址:https://www.cnblogs.com/xingyuanzier/p/13280050.html
Copyright © 2011-2022 走看看