Image Smoother
EasyUpdated: Jul 26, 2025
Practice on:
Problem
An image smoother is a filter of the size 3 x 3 that can be applied to each cell of an image by rounding down the average of the cell and the eight surrounding cells (i.e., the average of the nine cells in the blue smoother).
If one or more of the surrounding cells of a cell is not present, we do not consider it in the average (i.e., the average of the four cells in the red smoother).

Given an m x n integer matrix img representing the grayscale of an image, return the image after applying the smoother on each cell of it.
Examples
Example 1
\Huge
\begin{array}{|c|c|c|}
\hline
1 & 1 & 1 \\\
\hline
1 & 0 & 1 \\\
\hline
1 & 1 & 1 \\\
\hline
\end{array}
\xrightarrow{\text{Image Smoother}}
\begin{array}{|c|c|c|}
\hline
0 & 0 & 0 \\\
\hline
0 & 0 & 0 \\\
\hline
0 & 0 & 0 \\\
\hline
\end{array}
Input: img = [[1,1,1],[1,0,1],[1,1,1]]
Output: [[0,0,0],[0,0,0],[0,0,0]]
Explanation:
For the points (0,0), (0,2), (2,0), (2,2): floor(3/4) = floor(0.75) = 0
For the points (0,1), (1,0), (1,2), (2,1): floor(5/6) = floor(0.83333333) = 0
For the point (1,1): floor(8/9) = floor(0.88888889) = 0
Example 2
\Huge
\begin{array}{|c|c|c|}
\hline
100 & 200 & 100 \\\
\hline
200 & 50 & 200 \\\
\hline
100 & 200 & 100 \\\
\hline
\end{array}
\xrightarrow{\text{Image Smoother}}
\begin{array}{|c|c|c|}
\hline
137 & 141 & 137 \\\
\hline
141 & 138 & 141 \\\
\hline
137 & 141 & 137 \\\
\hline
\end{array}
Input: img = [[100,200,100],[200,50,200],[100,200,100]]
Output: [[137,141,137],[141,138,141],[137,141,137]]
Explanation:
For the points (0,0), (0,2), (2,0), (2,2): floor((100+200+200+50)/4) = floor(137.5) = 137
For the points (0,1), (1,0), (1,2), (2,1): floor((200+200+50+200+100+100)/6) = floor(141.666667) = 141
For the point (1,1): floor((50+200+200+200+200+100+100+100+100)/9) = floor(138.888889) = 138
Constraints
m == img.lengthn == img[i].length1 <= m, n <= 2000 <= img[i][j] <= 255
Solution
Method 1 – Brute Force with Bounds Checking
Intuition
For each cell, we want the average of itself and its neighbors. We can check all 3x3 cells around each position, sum their values, count them, and take the floor of the average.
Approach
- For each cell (i, j) in the matrix:
- Initialize sum and count to 0.
- For each neighbor (di, dj) in [-1, 0, 1]:
- If (i+di, j+dj) is in bounds, add its value to sum and increment count.
- Set the result cell to sum // count.
- Return the resulting matrix.
Code
C++
class Solution {
public:
vector<vector<int>> imageSmoother(vector<vector<int>>& img) {
int m = img.size(), n = img[0].size();
vector<vector<int>> ans(m, vector<int>(n));
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
int s = 0, c = 0;
for (int di = -1; di <= 1; ++di) {
for (int dj = -1; dj <= 1; ++dj) {
int ni = i + di, nj = j + dj;
if (ni >= 0 && ni < m && nj >= 0 && nj < n) {
s += img[ni][nj];
++c;
}
}
}
ans[i][j] = s / c;
}
}
return ans;
}
};
Go
func imageSmoother(img [][]int) [][]int {
m, n := len(img), len(img[0])
ans := make([][]int, m)
for i := range ans {
ans[i] = make([]int, n)
}
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
s, c := 0, 0
for di := -1; di <= 1; di++ {
for dj := -1; dj <= 1; dj++ {
ni, nj := i+di, j+dj
if ni >= 0 && ni < m && nj >= 0 && nj < n {
s += img[ni][nj]
c++
}
}
}
ans[i][j] = s / c
}
}
return ans
}
Java
class Solution {
public int[][] imageSmoother(int[][] img) {
int m = img.length, n = img[0].length;
int[][] ans = new int[m][n];
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
int s = 0, c = 0;
for (int di = -1; di <= 1; ++di) {
for (int dj = -1; dj <= 1; ++dj) {
int ni = i + di, nj = j + dj;
if (ni >= 0 && ni < m && nj >= 0 && nj < n) {
s += img[ni][nj];
++c;
}
}
}
ans[i][j] = s / c;
}
}
return ans;
}
}
Kotlin
class Solution {
fun imageSmoother(img: Array<IntArray>): Array<IntArray> {
val m = img.size
val n = img[0].size
val ans = Array(m) { IntArray(n) }
for (i in 0 until m) {
for (j in 0 until n) {
var s = 0
var c = 0
for (di in -1..1) {
for (dj in -1..1) {
val ni = i + di
val nj = j + dj
if (ni in 0 until m && nj in 0 until n) {
s += img[ni][nj]
c++
}
}
}
ans[i][j] = s / c
}
}
return ans
}
}
Python
class Solution:
def imageSmoother(self, img: list[list[int]]) -> list[list[int]]:
m, n = len(img), len(img[0])
ans = [[0]*n for _ in range(m)]
for i in range(m):
for j in range(n):
s = c = 0
for di in [-1,0,1]:
for dj in [-1,0,1]:
ni, nj = i+di, j+dj
if 0 <= ni < m and 0 <= nj < n:
s += img[ni][nj]
c += 1
ans[i][j] = s // c
return ans
Rust
impl Solution {
pub fn image_smoother(img: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
let m = img.len();
let n = img[0].len();
let mut ans = vec![vec![0; n]; m];
for i in 0..m {
for j in 0..n {
let mut s = 0;
let mut c = 0;
for di in -1..=1 {
for dj in -1..=1 {
let ni = i as isize + di;
let nj = j as isize + dj;
if ni >= 0 && ni < m as isize && nj >= 0 && nj < n as isize {
s += img[ni as usize][nj as usize];
c += 1;
}
}
}
ans[i][j] = s / c;
}
}
ans
}
}
TypeScript
class Solution {
imageSmoother(img: number[][]): number[][] {
const m = img.length, n = img[0].length;
const ans = Array.from({length: m}, () => Array(n).fill(0));
for (let i = 0; i < m; ++i) {
for (let j = 0; j < n; ++j) {
let s = 0, c = 0;
for (let di = -1; di <= 1; ++di) {
for (let dj = -1; dj <= 1; ++dj) {
const ni = i + di, nj = j + dj;
if (ni >= 0 && ni < m && nj >= 0 && nj < n) {
s += img[ni][nj];
c++;
}
}
}
ans[i][j] = Math.floor(s / c);
}
}
return ans;
}
}
Complexity
- ⏰ Time complexity:
O(mn), where m and n are the dimensions of the image, since we visit each cell and its neighbors. - 🧺 Space complexity:
O(mn), for the output matrix.