webentwicklung-frage-antwort-db.com.de

Bildverarbeitung - Implementierung des Sobel-Filters

Ich habe die Aufgabe, den Sobel-Filter zu implementieren, der, wie Sie wissen, ein Bildverarbeitungsfilter für die Kantenerkennung ist. Leider habe ich keine Erfahrung im Bereich der Bildverarbeitung, so dass ich nicht einmal weiß, wie Bilder im Computer dargestellt werden. Völlig keine Kenntnisse auf diesem Gebiet.

Ich habe einige Artikel und PDFs gelesen, aber sie konzentrieren sich auf viele Themen, die ich für meine Aufgabe möglicherweise nicht benötige.

Ich würde mich freuen, Ihre Vorschläge zu erfahren oder wenn es zu diesem Zweck ein bestimmtes Papier, PDF, Tutorial oder eine Kurzanleitung gibt.

Vielen Dank

BEARBEITEN:

Vielen Dank an alle :) Das Ergebnis unserer Arbeit kann von hier heruntergeladen werden.

30
Ahmad Siavosh

Es ist ziemlich einfach, Sie müssen Ihr Bild nur mit einem Sobel-Filter falten. Ein Sobel-Filter hat zwei Kernel, einen Kernel in x-Richtung und einen Kernel in y-Richtung. Der Kernel in x-Richtung erkennt horizontale Kanten und der Kernel in y-Richtung erkennt vertikale Kanten.

x-direction kernel (die größe ist 3x3)

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

kernel in y-Richtung

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

Um die Faltung bei Pixel (x, y) zu berechnen, definieren Sie ein Fenster mit einer Größe, die der Kernelgröße entspricht (der Quellcode zur Berechnung der Größe in x und der Größe in y ist identisch):

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

Beachten Sie, dass die Eingabe ein Graustufenbild ist und als 1D-Array von double dargestellt werden kann (Dies ist nur ein Trick, da auf einen Pixelwert in der Koordinate (x, y) mit index = [x + y * width] zugegriffen werden kann.)

So berechnen Sie die Größe in Pixel (x, y) bei magX und magY:

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

28
azer89

Die einfachste Erklärung für den Sobel-Operator , den ich bis jetzt gesehen habe, stammt aus Saushs Blog , ein Technikbegeisterter, der Sobel einmal persönlich kennengelernt hat:

enter image description here

The post beschreibt in (nicht zu vielen) Details, wie der Filter implementiert wird, und teilt Ruby Quellcode zu Demonstrationszwecken:

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')

Eingabe/Ausgabe :

19
karlphillip

Sobel Operator Die Wikipedia-Seite beschreibt genau, wie sie ausgeführt wird. Es gibt andere Operatoren wie Roberts Cross und Prewitt

Mit der Faltungsoperation können Sie den Ansatz ändern, indem Sie die Kernelmatrix ändern. Im Folgenden wird die Implementierung von Sobel und Convolution mit Marvin Framework möglicherweise hilfreich sein.

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

Faltung:

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

}

Gx schätzt den Gradienten in x-Richtung (Spalten) und Gy den Gradienten in y-Richtung (Zeilen). Also erkennt Gy horizontale Linien und Gx vertikale Linien.

3

Natürlich können Sie dafür OpenCV verwenden:

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:

3
Andriy Makukha

Alle oben genannten Schritte in einer R-Abschrift Datei. Hoffentlich wird es dadurch visueller und verständlicher. Ich musste einen Sobel-Filter implementieren, und diese Seite half mir, die Konzepte zu verstehen, obwohl ich Probleme hatte, sie zu realisieren. Also, hoffentlich hilft es, alles an einem Ort zu platzieren.

http://rpubs.com/ghub_24/420754

0
ghub24