- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在尝试复制 this link 的结果在空间域中使用线性卷积。
首先将图像转换为二维double
数组,然后进行卷积。图像和内核大小相同。图像在卷积之前被填充,并在卷积之后被相应地裁剪。
与基于 FFT 的卷积相比,输出很奇怪而且不正确。
我该如何解决这个问题?
请注意,我从 Matlab 获得了以下与我的 C# FFT 输出匹配的图像输出:
.
Update-1:根据@Ben Voigt 的评论,我更改了 Rescale()
函数以替换 255.0
与 1
,因此输出得到了显着改善。但是,输出仍然与 FFT 输出不匹配(这是正确的输出)。
.
Update-2:根据@Cris Luengo的评论,我通过拼接填充图像,然后进行空间卷积。结果如下:
所以,输出比上一个差。但是,这与 linked answer 的第二个输出有相似之处。这意味着循环卷积不是解决方案。
.
Update-3:我使用了@Cris Luengo 的回答中提出的Sum()
函数。结果是 **Update-1**
的改进版本:
但是,它仍然不是 100% 类似于 FFT 版本。
.
Update-4:根据@Cris Luengo 的评论,我减去两个结果以查看差异:
,
<支持> 1.空间负频域
2.频率减空间域
看起来,差异很大,这意味着空间卷积没有正确完成。
.
源代码:
(如果您需要查看更多源代码,请通知我。)
public static double[,] LinearConvolutionSpatial(double[,] image, double[,] mask)
{
int maskWidth = mask.GetLength(0);
int maskHeight = mask.GetLength(1);
double[,] paddedImage = ImagePadder.Pad(image, maskWidth);
double[,] conv = Convolution.ConvolutionSpatial(paddedImage, mask);
int cropSize = (maskWidth/2);
double[,] cropped = ImageCropper.Crop(conv, cropSize);
return conv;
}
static double[,] ConvolutionSpatial(double[,] paddedImage1, double[,] mask1)
{
int imageWidth = paddedImage1.GetLength(0);
int imageHeight = paddedImage1.GetLength(1);
int maskWidth = mask1.GetLength(0);
int maskHeight = mask1.GetLength(1);
int convWidth = imageWidth - ((maskWidth / 2) * 2);
int convHeight = imageHeight - ((maskHeight / 2) * 2);
double[,] convolve = new double[convWidth, convHeight];
for (int y = 0; y < convHeight; y++)
{
for (int x = 0; x < convWidth; x++)
{
int startX = x;
int startY = y;
convolve[x, y] = Sum(paddedImage1, mask1, startX, startY);
}
}
Rescale(convolve);
return convolve;
}
static double Sum(double[,] paddedImage1, double[,] mask1, int startX, int startY)
{
double sum = 0;
int maskWidth = mask1.GetLength(0);
int maskHeight = mask1.GetLength(1);
for (int y = startY; y < (startY + maskHeight); y++)
{
for (int x = startX; x < (startX + maskWidth); x++)
{
double img = paddedImage1[x, y];
double msk = mask1[x - startX, y - startY];
sum = sum + (img * msk);
}
}
return sum;
}
static void Rescale(double[,] convolve)
{
int imageWidth = convolve.GetLength(0);
int imageHeight = convolve.GetLength(1);
double maxAmp = 0.0;
for (int j = 0; j < imageHeight; j++)
{
for (int i = 0; i < imageWidth; i++)
{
maxAmp = Math.Max(maxAmp, convolve[i, j]);
}
}
double scale = 1.0 / maxAmp;
for (int j = 0; j < imageHeight; j++)
{
for (int i = 0; i < imageWidth; i++)
{
double d = convolve[i, j] * scale;
convolve[i, j] = d;
}
}
}
public static Bitmap ConvolveInFrequencyDomain(Bitmap image1, Bitmap kernel1)
{
Bitmap outcome = null;
Bitmap image = (Bitmap)image1.Clone();
Bitmap kernel = (Bitmap)kernel1.Clone();
//linear convolution: sum.
//circular convolution: max
uint paddedWidth = Tools.ToNextPow2((uint)(image.Width + kernel.Width));
uint paddedHeight = Tools.ToNextPow2((uint)(image.Height + kernel.Height));
Bitmap paddedImage = ImagePadder.Pad(image, (int)paddedWidth, (int)paddedHeight);
Bitmap paddedKernel = ImagePadder.Pad(kernel, (int)paddedWidth, (int)paddedHeight);
Complex[,] cpxImage = ImageDataConverter.ToComplex(paddedImage);
Complex[,] cpxKernel = ImageDataConverter.ToComplex(paddedKernel);
// call the complex function
Complex[,] convolve = Convolve(cpxImage, cpxKernel);
outcome = ImageDataConverter.ToBitmap(convolve);
outcome = ImageCropper.Crop(outcome, (kernel.Width/2)+1);
return outcome;
}
最佳答案
您当前的输出看起来更像是自相关函数,而不是 Lena 与她自己的卷积。我认为问题可能出在您的 Sum
函数中。
如果您查看 convolution sum 的定义,您会看到内核(或图像,无关紧要)已镜像:
sum_m( f[n-m] g[m] )
对于一个函数,m
以加号出现,而对于另一个函数,它以减号出现。
您需要修改 Sum
函数以按正确的顺序读取 mask1
图像:
static double Sum(double[,] paddedImage1, double[,] mask1, int startX, int startY)
{
double sum = 0;
int maskWidth = mask1.GetLength(0);
int maskHeight = mask1.GetLength(1);
for (int y = startY; y < (startY + maskHeight); y++)
{
for (int x = startX; x < (startX + maskWidth); x++)
{
double img = paddedImage1[x, y];
double msk = mask1[maskWidth - x + startX - 1, maskHeight - y + startY - 1];
sum = sum + (img * msk);
}
}
return sum;
}
另一种选择是将 mask1
的镜像版本传递给此函数。
关于c# - 空间域图像卷积,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51262986/
我正在尝试构建不同(但每个同质)类型的可遍历项的多个交叉产品。所需的返回类型是元组的可遍历对象,其类型与输入可遍历对象中的类型相匹配。例如: List(1, 2, 3) cross Seq("a",
import java.util.Scanner; public class BooleanProduct { public static void main(String[] args) {
任务 - 数字的最大 K 积 时间限制:1 内存限制:64 M 给定一个整数序列 N(1 ≤ N ≤ 10 月,| A i | ≤ 2.10 9)和数量 K(1 ≤ K ≤ N)。找出乘积最大的 K
考虑一个大小为 48x16 的 float 矩阵 A 和一个大小为 1x48 的 float vector b。 请建议一种在常见桌面处理器 (i5/i7) 上尽可能快地计算 b×A 的方法。 背景。
假设我有一个 class Rectangle(object): def __init__(self, len
设 A 为 3x3 阶矩阵。判断矩阵A的 boolean 积可以组成多少个不同的矩阵。 这是我想出的: #include int main() { int matri
背景 生成随机权重列表后: sizes = [784,30,10] weights = [np.random.randn(y, x) for x, y in zip(sizes[:-1],sizes[
我正在开发一个 python 项目并使用 numpy。我经常需要通过单位矩阵计算矩阵的克罗内克积。这些是我代码中的一个相当大的瓶颈,所以我想优化它们。我必须服用两种产品。第一个是: np.kron(n
有人可以提供一个例子说明如何使用 uBLAS 产品来乘法吗?或者,如果有更好的 C++ 矩阵库,您可以推荐我也欢迎。这正在变成一个令人头疼的问题。 这是我的代码: vector myVec(scala
我正在尝试开发一个Javascript程序,它会提示用户输入两个整数,然后显示这两个整数的和、乘积、差和商。现在它只显示总和。我实际上不知道乘法、减法和除法命令是否正在执行。这是 jsfiddle 的
如何使用 la4j 计算 vector (叉)积? vector 乘积为 接受两个 vector 并返回 vector 。 但是他们有scalar product , product of all e
在 C++ 中使用 Lapack 让我有点头疼。我发现为 fortran 定义的函数有点古怪,所以我尝试在 C++ 上创建一些函数,以便我更容易阅读正在发生的事情。 无论如何,我没有让矩阵 vecto
是否可以使用 Apple 的 Metal Performance Shaders 执行 Hadamard 产品?我看到可以使用 this 执行普通矩阵乘法,但我特别在寻找逐元素乘法,或者一种构造乘法的
我正在尝试使用 open mp 加速稀疏矩阵 vector 乘积,代码如下: void zAx(double * z, double * data, long * colind, long * row
有没有一种方法可以使用 cv::Mat OpenCV 中的数据结构? 我检查过 the documentation并且没有内置功能。但是我在尝试将标准矩阵乘法表达式 (*) 与 cv::Mat 类型的
我是一名优秀的程序员,十分优秀!