661.图片平滑器

题目:

图像平滑器 是大小为 3 x 3 的过滤器,用于对图像的每个单元格平滑处理,平滑处理后单元格的值为该单元格的平均灰度。

每个单元格的  平均灰度 定义为:该单元格自身及其周围的 8 个单元格的平均值,结果需向下取整。(即,需要计算蓝色平滑器中 9 个单元格的平均值)。

如果一个单元格周围存在单元格缺失的情况,则计算平均灰度时不考虑缺失的单元格(即,需要计算红色平滑器中 4 个单元格的平均值)。

给你一个表示图像灰度的 m x n 整数矩阵 img ,返回对图像的每个单元格平滑处理后的图像 。

示例 1:

输入:img = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[0, 0, 0],[0, 0, 0], [0, 0, 0]]
解释:
对于点 (0,0), (0,2), (2,0), (2,2): 平均(3/4) = 平均(0.75) = 0
对于点 (0,1), (1,0), (1,2), (2,1): 平均(5/6) = 平均(0.83333333) = 0
对于点 (1,1): 平均(8/9) = 平均(0.88888889) = 0

示例 2:

输入: img = [[100,200,100],[200,50,200],[100,200,100]]
输出: [[137,141,137],[141,138,141],[137,141,137]]
解释:
对于点 (0,0), (0,2), (2,0), (2,2): floor((100+200+200+50)/4) = floor(137.5) = 137
对于点 (0,1), (1,0), (1,2), (2,1): floor((200+200+50+200+100+100)/6) = floor(141.666667) = 141
对于点 (1,1): floor((50+200+200+200+200+100+100+100+100)/9) = floor(138.888889) = 138

提示:

  • m == img.length
  • n == img[i].length
  • 1 <= m, n <= 200
  • 0 <= img[i][j] <= 255

解题思路:

 构建一个新的矩阵在原矩阵的基础上加入填充,类似于卷积神经网络加入pedding的想法,然后判断加入的值是否在边缘,用9-边缘个数即可得到需要求均值的个数

代码:

class Solution:
    def imageSmoother(self, img: List[List[int]]) -> List[List[int]]:
        m = len(img)
        n = len(img[0])
        outputs = [[0]*(n+2) for _ in range(m+2)]
        # 先将图像矩阵四周加入0进行填充
        for i in range(m):
            for j in range(n):
                outputs[i+1][j+1] = img[i][j]
        for i in range(m):
            for j in range(n):
                k = 0
                ans = 0
                for flag1 in range(3):
                    for flag2 in range(3):
                        ans += outputs[i+flag1][j+flag2]
                        if i+flag1 == 0 or i+flag1==m+1 or j+flag2==0 or j+flag2==n+1:
                            k+=1
                img[i][j] = int(ans/(9-k))
        return img

### 关于二维前缀和的示例题目及其解法 #### 示例题目:LeetCode 304. 二维区域和检索 - 矩阵不可变 此题要求实现一个数据结构 `NumMatrix`,用于快速计算给定矩形区域内元素的总和。该类应支持初始化时传入整数矩阵 `matrix` 并提供方法 `sumRegion(row1, col1, row2, col2)` 来返回左上角位于 `(row1,col1)` 右下角位于 `(row2,col2)` 的子矩阵内的所有元素之和。 为了高效解决这个问题,可以预先计算并保存每个位置到原点(0,0)之间所有元素构成的矩形区域内的累积和作为辅助工具,在后续调用过程中利用这些已知的结果加速运算过程[^1]。 ```python class NumMatrix: def __init__(self, matrix: List[List[int]]): if not matrix or not matrix[0]: self.sums = None return m, n = len(matrix), len(matrix[0]) self.sums = [[0]*(n+1) for _ in range(m+1)] for i in range(1,m+1): for j in range(1,n+1): self.sums[i][j]=self.sums[i-1][j]+self.sums[i][j-1]-self.sums[i-1][j-1]+matrix[i-1][j-1] def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int: if self.sums is None: return 0 A=self.sums[row2+1][col2+1] B=self.sums[row1][col2+1] C=self.sums[row2+1][col1] D=self.sums[row1][col1] return A-B-C+D # Your NumMatrix object will be instantiated and called as such: # obj = NumMatrix(matrix) # param_1 = obj.sumRegion(row1,col1,row2,col2) ``` 上述代码实现了基于二维前缀和的数据结构,通过提前构建好累加表使得每次查询操作可以在常量时间内完成。具体来说就是先遍历整个输入矩阵一次建立一个新的二维数组用来记录从坐标 (0,0) 到当前坐标的矩形范围内所有数值相加之和;之后每当需要获取任意指定范围内的值的时候只需要做简单的四则运算即可得出结果[^4]。 #### 示例题目:LeetCode 661. 图片平滑器 本题旨在对图像中的每一个像素进行处理得到新的颜色强度值,新值等于它自己以及周围八个方向上的邻居们的平均灰度值(如果某个方向不存在有效邻接点,则忽略)。这里同样可以通过构造二维前缀和的方式来简化边界情况下的判断逻辑,并提高整体性能表现。 ```cpp vector<vector<int>> imageSmoother(vector<vector<int>>& M) { vector<vector<int>> res(M.size(), vector<int>(M[0].size())); // 构建二维前缀和 vector<vector<int>> prefixSum(M.size() + 1, vector<int>(M[0].size() + 1)); for(int i=1; i<=M.size(); ++i){ for(int j=1; j<=M[0].size(); ++j){ prefixSum[i][j] = M[i-1][j-1] + prefixSum[i-1][j] + prefixSum[i][j-1] - prefixSum[i-1][j-1]; } } auto getSum = [&](int r1,int c1,int r2,int c2)->int{ return prefixSum[r2+1][c2+1] - prefixSum[r1][c2+1] - prefixSum[r2+1][c1] + prefixSum[r1][c1]; }; for(size_t i=0;i<M.size();++i){ for(size_t j=0;j<M[0].size();++j){ int cnt = 0; int sr = max((int)i-1,0); int sc = max((int)j-1,0); int er = min(i+1,(int)(M.size()-1)); int ec = min(j+1,(int)(M[0].size()-1)); res[i][j]=(getSum(sr,sc,er,ec)/(pow(er-sr+1,2))); } } return res; } ``` 这段 C++ 实现展示了如何应用二维前缀和技术来优化图片平滑化的过程。首先创建了一个额外的空间存储原始图象经过转换后的前缀和形式;接着定义了帮助函数 `getSum()` 方便提取特定区间内部的所有元素合计;最后按照规则更新目标输出矩阵中对应位置的新亮度值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值