首页 文章

图像处理 - 实现Sobel滤波器

提问于
浏览
30

我有一个任务来实现Sobel滤波器,正如你所知,它是一个用于边缘检测的图像处理滤波器 . 但不幸的是,我没有图像处理领域的经验,我甚至不知道图像在计算机中的表现方式 . 完全没有这个领域的知识 .

我已经阅读了一些论文和PDF,但他们关注的很多主题我认为我可能不需要它们来完成我的任务 .

我很乐意知道您的建议,或者是否有任何特定的论文,PDF,教程或快速指南 .

谢谢

编辑:

谢谢大家:)我们的工作成果可以从here下载 .

6 回答

  • 19

    这很简单,您只需要使用Sobel滤镜对图像进行卷积 . Sobel滤波器有两个内核,x方向内核和y方向内核 . x方向内核检测水平边缘,y方向内核检测垂直边缘 .

    x方向内核(大小为3x3)

    float kernelx[3][3] = {{-1, 0, 1}, 
                           {-2, 0, 2}, 
                           {-1, 0, 1}};
    

    y方向内核

    float kernely[3][3] = {{-1, -2, -1}, 
                            {0,  0,  0}, 
                            {1,  2,  1}};
    

    要计算像素(x,y)处的卷积,请定义大小等于内核大小的窗口(用于计算x中的幅度和y中的幅度的源代码是相同的):

    double magX = 0.0; // this is your magnitude
    
    for(int a = 0; a < 3; a++)
    {
        for(int b = 0; b < 3; b++)
        {            
            int xn = x + a - 1;
            int yn = y + b - 1;
    
            int index = xn + yn * width;
            magX += image[index] * kernelx[a][b];
        }
     }
    

    请注意,输入是灰度图像,它可以表示为1D的double数组(这只是一个技巧,因为可以使用index = [x y * width]访问坐标(x,y)中的像素值)

    在给定magX和magY的情况下计算像素(x,y)的大小:

    mag = sqrt( magX^2 + magY^2 )

  • 0

    我见过这个日期的最简单的解释来自Saush's blog,一位曾经见过Sobel的技术爱好者:

    enter image description here

    The post描述了(不是太多)有关如何实现过滤器的详细信息,并为演示目的共享Ruby源代码:

    require 'chunky_png'
    
    class ChunkyPNG::Image
      def at(x,y)
        ChunkyPNG::Color.to_grayscale_bytes(self[x,y]).first
      end
    end
    
    img = ChunkyPNG::Image.from_file('engine.png')
    
    sobel_x = [[-1,0,1],
               [-2,0,2],
               [-1,0,1]]
    
    sobel_y = [[-1,-2,-1],
               [0,0,0],
               [1,2,1]]
    
    edge = ChunkyPNG::Image.new(img.width, img.height, ChunkyPNG::Color::TRANSPARENT)
    
    for x in 1..img.width-2
      for y in 1..img.height-2
        pixel_x = (sobel_x[0][0] * img.at(x-1,y-1)) + (sobel_x[0][1] * img.at(x,y-1)) + (sobel_x[0][2] * img.at(x+1,y-1)) +
                  (sobel_x[1][0] * img.at(x-1,y))   + (sobel_x[1][1] * img.at(x,y))   + (sobel_x[1][2] * img.at(x+1,y)) +
                  (sobel_x[2][0] * img.at(x-1,y+1)) + (sobel_x[2][1] * img.at(x,y+1)) + (sobel_x[2][2] * img.at(x+1,y+1))
    
        pixel_y = (sobel_y[0][0] * img.at(x-1,y-1)) + (sobel_y[0][1] * img.at(x,y-1)) + (sobel_y[0][2] * img.at(x+1,y-1)) +
                  (sobel_y[1][0] * img.at(x-1,y))   + (sobel_y[1][1] * img.at(x,y))   + (sobel_y[1][2] * img.at(x+1,y)) +
                  (sobel_y[2][0] * img.at(x-1,y+1)) + (sobel_y[2][1] * img.at(x,y+1)) + (sobel_y[2][2] * img.at(x+1,y+1))
    
        val = Math.sqrt((pixel_x * pixel_x) + (pixel_y * pixel_y)).ceil
        edge[x,y] = ChunkyPNG::Color.grayscale(val)
      end
    end
    
    edge.save('engine_edge.png')
    

    Input/Output

  • 4

    Sobel Operator维基百科页面描述了如何执行它 . 有其他运营商,如Roberts crossPrewitt

    使用卷积运算,您可以通过更改内核矩阵来切换方法 . 下面,使用Marvin Framework实施Sobel和Convolution可能对您有所帮助 .

    Sobel:

    public class Sobel extends MarvinAbstractImagePlugin{
    
        // Definitions
        double[][] matrixSobelX = new double[][]{
                {1,     0,  -1},
                {2,     0,  -2},
                {1,     0,  -1}
        };
        double[][] matrixSobelY = new double[][]{
                {-1,    -2,     -1},
                {0,     0,      0},
                {1,     2,      1}
        };
    
        private MarvinImagePlugin   convolution;
    
        public void load(){
            convolution = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.convolution.jar");
        }
    
        public MarvinAttributesPanel getAttributesPanel(){
            return null;
        }
        public void process
        (
            MarvinImage imageIn, 
            MarvinImage imageOut,
            MarvinAttributes attrOut,
            MarvinImageMask mask, 
            boolean previewMode
        )
        {
            convolution.setAttribute("matrix", matrixSobelX);
            convolution.process(imageIn, imageOut, null, mask, previewMode);
            convolution.setAttribute("matrix", matrixSobelY);
            convolution.process(imageIn, imageOut, null, mask, previewMode);
        }
    }
    

    Convolution:

    public class Convolution extends MarvinAbstractImagePlugin{
    
        private MarvinAttributesPanel   attributesPanel;
        private MarvinAttributes        attributes;
    
        public void process
        (
            MarvinImage imageIn, 
            MarvinImage imageOut,
            MarvinAttributes attributesOut,
            MarvinImageMask mask, 
            boolean previewMode
        )
        {
            double[][] matrix = (double[][])attributes.get("matrix");
    
            if(matrix != null && matrix.length > 0){
                for(int y=0; y<imageIn.getHeight(); y++){
                    for(int x=0; x<imageIn.getWidth(); x++){
                        applyMatrix(x, y, matrix, imageIn, imageOut);
                    }
                }
            }
        }
    
        private void applyMatrix
        (
            int x,
            int y,
            double[][] matrix,
            MarvinImage imageIn,
            MarvinImage imageOut
        ){
    
            int nx,ny;
            double resultRed=0;
            double resultGreen=0;
            double resultBlue=0;
    
            int xC=matrix[0].length/2;
            int yC=matrix.length/2;
    
            for(int i=0; i<matrix.length; i++){
                for(int j=0; j<matrix[0].length; j++){
                    if(matrix[i][j] != 0){      
                        nx = x + (j-xC);
                        ny = y + (i-yC);
    
                        if(nx >= 0 && nx < imageOut.getWidth() && ny >= 0 && ny < imageOut.getHeight()){
    
                            resultRed   +=  (matrix[i][j]*(imageIn.getIntComponent0(nx, ny)));
                            resultGreen +=  (matrix[i][j]*(imageIn.getIntComponent1(nx, ny)));
                            resultBlue  +=  (matrix[i][j]*(imageIn.getIntComponent2(nx, ny)));
                        }
    
    
                    }
    
    
    
                }
            }
    
            resultRed   = Math.abs(resultRed);
            resultGreen = Math.abs(resultGreen);
            resultBlue = Math.abs(resultBlue);
    
            // allow the combination of multiple appications
            resultRed   += imageOut.getIntComponent0(x,y);
            resultGreen += imageOut.getIntComponent1(x,y);
            resultBlue  += imageOut.getIntComponent2(x,y);
    
            resultRed   = Math.min(resultRed, 255);
            resultGreen = Math.min(resultGreen, 255);
            resultBlue  = Math.min(resultBlue, 255);
    
            resultRed   = Math.max(resultRed, 0);
            resultGreen = Math.max(resultGreen, 0);
            resultBlue  = Math.max(resultBlue, 0);
    
            imageOut.setIntColor(x, y, imageIn.getAlphaComponent(x, y), (int)resultRed, (int)resultGreen, (int)resultBlue);
        }
    
        public void load(){
            attributes = getAttributes();
            attributes.set("matrix", null);
        }
    
        public MarvinAttributesPanel getAttributesPanel(){
            if(attributesPanel == null){
                attributesPanel = new MarvinAttributesPanel();
                attributesPanel.addMatrixPanel("matrixPanel", "matrix", attributes, 3, 3);
            }
            return attributesPanel;
        }
    
    }
    
  • 3

    Gx估计x方向(列)的梯度,Gy估计y方向的梯度(行) . 因此,Gy检测水平线,Gx检测垂直线 .

  • 2

    当然,您可以使用OpenCV:

    import cv2
    import numpy as np
    
    img = cv2.imread(INPUT_IMAGE)
    img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY).astype(float)
    
    edge_x = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
    edge_y = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)    
    edge = np.sqrt(edge_x**2 + edge_y**2)    # image can be normalized to 
                                             # fit into 0..255 color space
    cv2.imwrite(OUTPUT_IMAGE, edge)
    

    输入输出:

  • 27

    R markdown 文件中的所有上述步骤 . 希望这使它更直观,更容易理解 . 我需要实现一个sobel过滤器,这个页面帮助我理解了我在完成它时遇到一些麻烦的概念 . 所以把它放在一个地方希望它有所帮助 .

    http://rpubs.com/ghub_24/420754

相关问题