Java: finding edges with the Sobel operator
Estimate the horizontal intensity change at each pixel and mark strong edges.
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);
}
}
}##. ##. ##.
Explanation
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.
Explore the dry run
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); } }}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
| Step / line | What happens | State after step | Output 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 | ##. ##. ##. |
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.