我想使用一个基于条件表达式执行像素操作的内核。
假设我有这个灰度图像(6x6 分辨率):
并且我使用 3x3 像素内核,如何更改中心内核像素(中心)的值当且仅当中心像素是局部最小值或者 3x3 内核中的最大值?
例如,假设我想将中心内核像素设置为周围 8 个像素的平均值值,如下所示:
有没有办法用OpenCV
来做到这一点?
编辑:另一个更详细的示例 GIF - 9 遍实现我的示例:
这是使用以下公式在 Excel 中生成的(不是相对单元格引用 - 它们显示焦点“picell”周围 3x3 的内核形状:
=IF(OR(C55=MIN(B54:D56),C55=MAX(B54:D56)),(SUM(B54:D56)-C55)/8,C55)
这里是表格的左上角,其中包含第一遍的源值(这些值控制单元格颜色):
该表引用另一个源表。 GIF 中的每一帧都是下一个计算出的颜色表。每个图像帧之间有 3 个公式表。以下是更多背景信息:
最佳答案
你问:
[...] how would I change the value of the centre kernel pixel (centre) IF AND ONLY IF the centre pixel is the local minimum or maximum within the 3x3 kernel? For example, say I wanted to set the centre kernel pixel to the average value of the surrounding 8 pixels [...]
我将首先演示一些内容。我将使用 16 x 16 的小阵列。我将放大它们,以便您可以方便地观察像素。当我谈论这些图像时,我指的是 16x16 数据,而不是本文中的可视化。
让我们从随机噪声开始,因为这是您首先呈现的。
noise = np.random.randint(0, 256, size=(16, 16), dtype=np.uint8)
现在您需要了解形态学运算。腐 eclipse 和膨胀正在计算局部最小值/最大值。
local_max_values = cv.dilate(noise_img, None, iterations=1)
local_min_values = cv.erode(noise_img, None, iterations=1)
那有什么用?您可以比较像素值。如果一个像素等于局部极值,那么它一定是a局部极值。它不是唯一的,因为假设两个相邻像素具有相同的低/高值。它们都是极值。
让我们比较一下:
is_min = (noise_img == local_min_values)
is_max = (noise_img == local_max_values)
is_extremum = is_min | is_max
那些是面具。它们是二进制的、 bool 值的。您可以将它们用于索引或乘法。您可以想象当您将元素乘以 0 或 1 或使用反转掩码时会发生什么。
我将演示索引,但首先我需要本地平均值。
averaged = cv.blur(noise_img, (3, 3))
现在我可以复制输入(或者我可以直接对其进行处理),然后用这些位置的平均值覆盖所有极值像素。
denoised = noise_img.copy()
denoised[is_extremum] = averaged[is_extremum]
是的,这会计算所有像素的平均值,即使您不需要它。实际上,仅计算部分平均值不会节省任何时间。
如果您在此图像和源图像之间来回切换,您将看到局部极值被删除。其他曾经处于“第二位”的像素现在已经成为极值。另一轮将逐渐平滑整个图片,直到一切都变得相当平坦。
关于python - 有没有办法在 openCV 中使用条件内核,仅在条件为真时才更改图像上的像素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77428847/