Java · Course navigation

Java: finding edges with the Sobel operator

Estimate the horizontal intensity change at each pixel and mark strong edges.

On this page
Before you start

Java two-dimensional arrays and the convolution lesson.

  • Estimate the horizontal intensity change at each pixel and mark strong edges.
  • Predict the sample output and explain the state changes.
  • Complete the practice task and check the boundary cases.

The concept

An edge is a place where brightness changes quickly. The Sobel operator estimates the horizontal change with a 3×3 kernel that subtracts the left column from the right column, giving the middle row double weight. A large absolute value means a strong vertical edge.

The image has a dark left side and a bright right side. At positions where the window straddles the boundary the response is large, and where the window is entirely inside a flat region it is zero. A threshold turns the responses into an edge map. Sobel also has a vertical kernel, and the two are combined to measure edge strength in any direction.

Code example

Java
class Main {
  public static void main(String[] args) {
    int[][] image = {
      {0, 0, 100, 100, 100},
      {0, 0, 100, 100, 100},
      {0, 0, 100, 100, 100},
      {0, 0, 100, 100, 100},
      {0, 0, 100, 100, 100},
    };
    int[][] gx = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}};
    for (int r = 1; r < 4; r++) {
      StringBuilder row = new StringBuilder();
      for (int c = 1; c < 4; c++) {
        int sum = 0;
        for (int kr = 0; kr < 3; kr++) {
          for (int kc = 0; kc < 3; kc++) {
            sum += image[r - 1 + kr][c - 1 + kc] * gx[kr][kc];
          }
        }
        row.append(Math.abs(sum) > 200 ? '#' : '.');
      }
      System.out.println(row);
    }
  }
}
Output
##.
##.
##.

Follow the code

Open the walkthrough to inspect the example one step at a time.

Show guided walkthrough
Guided walkthroughReady
1class Main {
2 public static void main(String[] args) {
3 int[][] image = {
4 {0, 0, 100, 100, 100},
5 {0, 0, 100, 100, 100},
6 {0, 0, 100, 100, 100},
7 {0, 0, 100, 100, 100},
8 {0, 0, 100, 100, 100},
9 };
10 int[][] gx = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}};
11 for (int r = 1; r < 4; r++) {
12 StringBuilder row = new StringBuilder();
13 for (int c = 1; c < 4; c++) {
14 int sum = 0;
15 for (int kr = 0; kr < 3; kr++) {
16 for (int kc = 0; kc < 3; kc++) {
17 sum += image[r - 1 + kr][c - 1 + kc] * gx[kr][kc];
18 }
19 }
20 row.append(Math.abs(sum) > 200 ? '#' : '.');
21 }
22 System.out.println(row);
23 }
24 }
25}

Follow the example

Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.

View the complete dry-run table
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput so far
The kernel subtracts the left neighbours from the right ones.weights sum to 0
—
Weighted sum for the 3×3 window around (r, c). On a vertical step of height 100 the response is 400.window at column 1: 400; at column 2: 400; at column 3: 0
—
A large magnitude, positive or negative, marks an edge pixel.threshold = 200
—
The columns on either side of the step are marked; the flat bright region is not.threshold = 200
##.
##.
##.

Behind the scenes

How Java processes this code

The Java compiler produces bytecode. The JVM loads the class and invokes its main method.

Cost and common mistakes

O(R·C) for a fixed 3×3 kernel.

  • Noise produces many small false edges. Real pipelines blur first, then apply the operator.
  • Using the absolute value matters: a dark-to-bright edge gives a positive sum and a bright-to-dark edge gives a negative one.

Try it yourself

Which direction of edge does the transposed kernel detect?

Reveal answer and reasoning

The transposed kernel measures vertical change, so it responds to horizontal edges.

Further reading