使用函数作为卷积核

3

各位程序员好,

我正在参加今年的 编程降临节活动。在第9天中,我需要找出图像中的一个像素是否具有相邻像素中的最小值。

我一开始非常直观粗暴地解决了这个问题,但是现在经过一段时间的思考,我想知道是否有一种方法可以为opencv的filter2D函数或其他适当的库定义一个卷积核,并将其定义为函数,以便我不仅可以进行线性变换,还可以进行其他变换。

在这个特定的例子中,我想到了一个可以告诉我们中间像素是否具有最小值的卷积核。也许甚至有一种方法可以使用线性变换来实现,但是我无法找到它。

任何帮助都将不胜感激。


2
腐蚀/膨胀,比较,完成。腐蚀/膨胀不是线性的,这就是为什么它们可以解决这个问题。没有任何线性方法可以解决这个问题。 - Christoph Rackwitz
你会相信我昨天在AOC问题上也经历了完全相同的推理过程。最终以“粗暴”的方式解决了它。 - AbbeGijly
@ChristophRackwitz 非常感谢!我不知道这些操作。一直在学习 :) - Lenny Eing
2个回答

1

我自己找到了一个解决方案,只需要使用scipy.ndimage.generic_filter函数。

import numpy as np
from scipy.ndimage import generic_filter

# First define the footprint of the filter you are going to use:
footprint = np.array([[False, True, False],
                     [True, True, True],
                     [False, True, False]])

# Then define the filter you want to use:
def lowpoint_kernel(a):
    return 0 if a[2] < a[0] and a[2] < a[1] and a[2] < a[3] and a[2] < a[4] else 10

# Get your input here
image = ...

# Pad your image
image = np.pad(image, 1, constant_values=10)

lowpoints = generic_filter(image, lowpoint_kernel, footprint=footprint)
lowpoint_indices = lowpoints == 0


这可能是一个非常复杂的解决方案,但也许有人会发现它有用。查看完整的解决方案在这里

0

在Python中使用scipy general filter是一个好主意。 但据我所知,OpenCV没有提供这样一种方式(将自定义函数处理作为过滤器)。因此,如果您想要使用OpenCV函数来实现这个功能,可以首先应用腐蚀形态学操作cv::erode)(使用您所需的窗口大小和二进制掩模),以获得每个像素邻域中的最小值,然后使用cv::compare方法或类似方法比较结果图像与原始图像。
要排除最小值(腐蚀)中心像素,可以将一个自定义二进制核传递给cv::erode,其中在生成的核中,中心像素为零。
总之,您应该这样做:

  1. cv::Mat kernel = cv::Mat::ones(3,3,CV_8UC1);
    kernel.at(1, 1)=0;
  2. cv::erode(src, dst_min, kernel);
  3. cv::compare(src, dst_min, dst, cv::CMP_EQ);

话虽如此,这种方法的唯一限制是在cv::erode函数中计算最小操作时必须针对非零邻居。如果这不是您想要的效果,则可以向src添加偏差,然后将其减去!

最后但并非最不重要的,如果您正在使用cpu(而不是gpu),建议使用cv :: ParallelLoopBody 一次调用即可并行实现所有过程(内存访问)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接