- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我几乎没有关于 Scharr 导数及其 OpenCV 实现的问题。
我对具有 (3X3) 内核的二阶图像导数感兴趣。我从 Sobel 二阶导数开始,它未能在图像中找到一些细线。看完this page底部的Sobel和Charr比较,我决定通过更改此行来尝试 Scharr:
Sobel(gray, grad, ddepth, 2, 2, 3, scale, delta, BORDER_DEFAULT);
到这一行:
Scharr(img, gray, ddepth, 2, 2, scale, delta, BORDER_DEFAULT);
我的问题是,似乎 cv::Scharr 一次只允许执行一个偏导数的一阶,所以我得到以下错误:
错误:函数 getScharrKernels 中的 (-215) dx >= 0 && dy >= 0 && dx+dy == 1
(参见断言行 here )
根据这个限制,我有一些关于 Scharr 衍生物的几个问题:
dx+dy == 1
?如果我要为每个轴调用 Scharr 两次,合并结果的正确方法是什么?我目前正在使用:
addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );
但我不确定 Sobel 函数是如何结合两个轴的,以及对于所有 4 个导数应该以什么顺序完成。
如果我要使用 4 个不同的内核来计算 (dx=2,dy=2) 导数,我想在将所有 4 个内核应用到图像之前将其统一为 1 来减少处理时间(我假设这就是 cv::Sobel 所做的)。是否有一种合理的方法来创建这样的组合 Shcarr 内核并将其与我的图像进行卷积?
谢谢!
最佳答案
我从未读过原始的 Scharr
论文(论文在 German 中)所以我不知道为什么 Scharr()
函数不允许高阶导数。可能是因为我在下面 #3 中提出的第一点?
Scharr
函数应该是一个导数。多变量函数 f(x) = f(x0, ..., xN)
的全导数是
df/dx = dx0*df/dx0 + ... + dxN*df/dxN
也就是说,每个部分的总和乘以变化。当然,在图像的情况下,输入中的变化 dx
是单个像素,因此它相当于 1。换句话说,只需对部分求和即可;没有将它们加权一半。您可以使用 addWeighted()
并将 1 作为权重,或者您可以将它们相加,但要确保您不会使图像饱和,您需要将其转换为 float 或 16 位图像第一。但是,如果您尝试获取梯度而不是导数,那么计算导数的欧几里得量级也很常见。
然而,这只是一阶导数。对于更高的订单,您需要应用一些链条。参见 here有关合并第二个订单的详细信息。
请注意,一阶导数的优化内核不一定是二阶导数的最佳内核,因为它应用了两次。 Scharr自己有一篇关于优化二阶导数核的论文,可以看看here .
话虽如此,过滤器被分成 x
和 y
方向以制作线性可分离过滤器,这基本上将您的 2d 卷积问题转化为两个具有较小内核的 1d 卷积。想一想 Sobel
和 Scharr
内核:对于 x
方向,它们都只有两边的单列具有相同的值(除了一个是负面的)。当您在图像上滑动内核时,在第一个位置,您将第一列和第三列乘以内核中的值。然后两步之后,你将第三步和第五步相乘。但是第三个已经计算出来了,所以很浪费。相反,由于两边相同,只需将每一列乘以 vector ,因为您知道您需要这些值,然后您可以只查找第 1 列和第 3 列中结果的值并减去它们。
简而言之,我认为您不能将它们与内置的可分离过滤函数结合使用,因为某些值有时为正,否则为负;知道何时线性应用过滤器的唯一方法是分别进行。但是,我们可以检查应用这两种过滤器的结果,看看它们如何影响单个像素,构建 2D 内核,然后与 OpenCV 进行卷积。
假设我们有一个 3x3 的图像:
image
=====
a b c
d e f
g h i
我们有 Scharr
内核:
kernel_x
========
-3 0 3
-10 0 10
-3 0 3
kernel_y
========
-3 -10 -3
0 0 0
3 10 3
将每个内核应用于此图像的结果为我们提供:
image * kernel_x
================
-3a -10b -3c
+0d +0e +0f
+3g +10h +3i
image * kernel_y
================
-3a +0b +3c
-10d +0e +10f
-3g +0h +3i
将这些值相加并放入像素 e
中。由于这两者的总和是全导数,我们在一天结束时将所有这些值加到像素 e
中。
image * kernel_x + image * kernel y
===================================
-3a -10b -3c +3g +10h +3i
-3a +3c -10d +10f -3g +3i
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
-6a -10b +0c -10d +10f +0g +10h +6i
这与我们乘以内核得到的结果相同
kernel_xy
=============
-6 -10 0
-10 0 10
0 10 6
所以有一个 2D 内核执行单阶导数。注意到什么有趣的事了吗?这只是两个内核的相加。这令人惊讶吗?不是真的,因为 x(a+b) = ax + bx
。现在我们可以将其传递给 filter2D()
计算导数的加法。这实际上会给出相同的结果吗?
import cv2
import numpy as np
img = cv2.imread('cameraman.png', 0).astype(np.float32)
kernel = np.array([[-6, -10, 0],
[-10, 0, 10],
[0, 10, 6]])
total_first_derivative = cv2.filter2D(img, -1, kernel)
scharr_x = cv2.Scharr(img, -1, 1, 0)
scharr_y = cv2.Scharr(img, -1, 0, 1)
print((total_first_derivative == (scharr_x + scharr_y)).all())
True
是的。现在我想你可以做两次。
关于c++ - 在 opencv 中组合 Scharr 导数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46140823/
我有一个随时间变化的数据流。如何使用 C# 确定变化率? 自从上微积分课已经很长时间了,但现在是我第一次真正需要它(15 年来)。现在,当我搜索“衍生品”这个词时,我会得到金融方面的东西,以及我认为并
假设我有以下数据和命令: clc;clear; t = [0:0.1:1]; t_new = [0:0.01:1]; y = [1,2,1,3,2,2,4,5,6,1,0]; p = interp1(
假设我有以下数据和命令: clc;clear; t = [0:0.1:1]; t_new = [0:0.01:1]; y = [1,2,1,3,2,2,4,5,6,1,0]; p = interp1(
我曾经使用这个公式来计算每秒记录的信号的导数,然后对其应用滚动平均值。 df.rolling(rollingWindow, center=True).mean().diff(rollingWindow
通过这里的一些帮助,我想出了一个函数,它似乎将索贝尔导数应用于 X 方向的图像 F(x,y) = F(x+1,y) - F( x,y)我无法使用任何 OpenCV 函数,并且我需要 2D 输出数组比
对于神经网络库,我实现了一些激活函数和损失函数及其衍生物。它们可以任意组合,输出层的导数只是损失导数和激活导数的乘积。 但是,我未能独立于任何损失函数实现 Softmax 激活函数的导数。由于归一化,
我要在使用 ReLU 的神经网络上进行反向传播。 在我之前的一个项目中,我在一个使用 Sigmoid 激活函数的网络上做了,但现在我有点困惑,因为 ReLU 没有导数。 这是一个 image关于 we
我的任务是制作自己的 Sobel 方法,而不是使用 OpenCV 中的 cv::Sobel。我尝试实现我在 Programming techniques 找到的一个 但是,当我运行该程序时,cv::M
我愿意计算一个不完全明确的函数的 Frechet/Gateaux 导数,我的问题是:最有效的方法是什么?您会推荐我使用哪种语言? 准确地说,我的问题是我有一个函数,比如 F,它是多维函数对(即从 R^
我想使用 Flux.jl 绘制函数及其梯度和 Plots.jl using Flux.Tracker using Plots f(x::Float64) = 3x^2 + 2x + 1 df(x::F
我已将 ReLu 导数实现为: def relu_derivative(x): return (x>0)*np.ones(x.shape) 我也尝试过: def relu_derivativ
我几乎没有关于 Scharr 导数及其 OpenCV 实现的问题。 我对具有 (3X3) 内核的二阶图像导数感兴趣。我从 Sobel 二阶导数开始,它未能在图像中找到一些细线。看完this page底
import numpy as np def relu(z): return np.maximum(0,z) def d_relu(z): z[z>0]=1 z[z 0).as
你好,我用 C++ 创建了一个小的运动模拟。我想向学生展示 Euler、Runge-Kutta 和 MidPoint 方法之间的差异,有些 Material 点在撞击球体时会移动和反弹。 但是当我切换
或者,目标:如何以声明方式从 Nix 不稳定中获取单个包? 我是 NixOS 的新手,目前正在尝试安装比默认版本更新的 Consul 0.5.2我的 NixOS 版本(最新稳定版)。我正在尝试通过覆盖
我已经为此苦苦挣扎了很长一段时间。我想要的只是一个 torch.diff() 函数。然而,许多矩阵运算似乎并不容易与张量运算兼容。 我已经尝试了大量不同的 pytorch 操作组合,但它们都不起作用。
我试图了解如何在 Swift 中创建 Vector,因为当我执行 CGVectorMake() 时,它告诉我将 dx 和 dy(导数)作为 CGFloat 传递。如何创建仅包含该信息的向量(线)? 谁
我希望你能帮助我。 我正在使用 QT 并尝试对图像的边缘进行简单检测。但是当我启动时我的程序崩溃了 cv::GaussianBlur( src, src, cv::Size(3,3), 0, 0, c
我正在计算信号的一阶和二阶导数,然后进行绘图。我选择了在 SciPy(信号模块)中实现的 Savitzky-Golay 滤波器。我想知道是否需要缩放输出 - 在同一过滤器的 Matlab 实现中,指定
我是一名优秀的程序员,十分优秀!