Image Processing - Implementing Sobel Filter

后端 未结 8 1735
梦毁少年i
梦毁少年i 2020-12-13 02:46

I\'ve got a task to implement Sobel filter which is, as you know, an image processing filter for edge detection. But unfortunately, I\'ve got no experience in image processi

相关标签:
8条回答
  • 2020-12-13 03:06

    Sobel Operator Wikipedia page is well descriptive about how to perform it. There other operators such as Roberts cross and Prewitt

    Using convolution operation, you can switch the approach by changing the kernel matrix. Below, the implementation of Sobel and Convolution using Marvin Framework may help you.

    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;
        }
    
    }
    
    0 讨论(0)
  • 2020-12-13 03:14

    I use Octave 4.4.1 for image processing and edge detection. Octave is an open source software which provides functionality of MatLab. I have used the following code from "https://in.mathworks.com/" Let us consider that the image is 'k1.jpg' To implement Sobel edge operator i=imread('k1.jpg');//To read the image pkg load image//Loading image processing Tool Box g=rgb2gray(i)//Conversion of image to grayscale S=edge(g,'Sobel');//Applying Sobel edge detector to g imshow(S);//To display the image Original image Segmented Image

    0 讨论(0)
  • 2020-12-13 03:20

    All the above mentioned steps in a R markdown file. Hopefully this makes it more visual and easier to understand. I needed to implement a sobel filter and this page helped me understand the concepts still I had some trouble in getting it done. So putting it all in one place hopefully it helps.

    http://rpubs.com/ghub_24/420754

    0 讨论(0)
  • 2020-12-13 03:22

    Of course, you could use OpenCV for this:

    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)
    

    Input / Output:

    0 讨论(0)
  • 2020-12-13 03:26

    The most simple explanation of the Sobel operator I've seen to this date is from Saush's blog, a tech enthusiast who once met Sobel himself:

    enter image description here

    The post describes in (not too many) details how to implement the filter, and shares Ruby source-code for demonstration purposes:

    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:

    0 讨论(0)
  • 2020-12-13 03:26

    You can do this in R with the raster package (oriented towards geographic data)

    library(raster)
    sobel <- function(r) {
        fy <- matrix(c(1,0,-1,2,0,-2,1,0,-1)/4, nrow=3)
        fx <- matrix(c(-1,-2,-1,0,0,0,1,2,1)/4 , nrow=3)
        rx <- focal(r, fx)
        ry <- focal(r, fy)
        sqrt(rx^2 + ry^2)
    }
    
    b <- brick("https://i.stack.imgur.com/Bnxa6.jpg")
    plotRGB(b)
    s <- stack(lapply(1:3, function(i) sobel(b[[i]])))
    plotRGB(s)
    
    # or
    ss <- mean(s)
    plot(ss, col=gray(1:10/10))
    
    # or
    bb <- mean(b)
    sss <- sobel(bb)
    plot(sss, col=gray(1:10/10))
    
    0 讨论(0)
提交回复
热议问题