【问题标题】:CrossCorrelation of images图像的互相关
【发布时间】:2018-04-19 01:01:24
【问题描述】:

我使用 Accord 框架来实现两个图像之间的互相关。我的目标是找出与第一个图像相比,第二个图像移动了多少(多少像素,以及在哪个方向)。

我使用的基本公式如下:

  • corr(a, b) = ifft(fft(a_and_zeros) * conj(fft(b_and_zeros)))

我会将整个代码放在消息的末尾,一切都发生在 Click 事件上。我的初始图像存储在 1024*768 位图中。所以这是我采取的步骤:

  1. 我将 2 个图像裁剪成 4 个对我来说很有趣的区域 (ExpInit, ExpFinal, RefInit, RefFinal),我想将它们两个两个关联起来(ExpInitExpFinalRefInitRefFinal)。裁剪后的图片尺寸为 1024*131。
  2. 我将这些裁剪后的图像放在具有 2^n 维 (2048*512) 的新位图的中心。
  3. 应用Grayscaling 过滤器得到8bppIndexed PixelFormat
  4. 将每张图片转换为ComplexImage格式并对4张图片应用前向FFT。
  5. 复共轭RefFinalExpFinal 傅立叶变换ComplexImage 中的每个元素。
  6. 在我想要交叉关联的 ComplexImageobjects 之间执行逐元素乘法(ExpInitExpFinalRefInit wit RefFinal)。
  7. 将反向 FFT 应用于逐元素乘法的乘积。 Tadaaa,我的互相关完成了,我有两个 Complex[,] 对象,它们的图像尺寸(2048*512 像素)

现在我想回答我最初的问题:与 ExpInit(分别为 ExpFinal)相比,ExpFinal(分别为 RefFinal)图像移动了多少(多少像素,以及在哪个方向)。在这里,我感到很困惑。

我有直觉我应该用我的Complex[,] 对象绘制一个 3D 图,其中 x 和 y 是数组中的索引,z 是索引处的值,然后搜索最大值,但是怎么做我用复数做到这一点?我只使用 Re 部分吗?只有 Im 部分?幅度 ?还是我完全弄错了?

额外问题:绘制此类图表的好库是什么?

这是所描述的互相关的完整代码:

        private void crosscorrButton_Click(object sender, EventArgs e)
    {
        // Cropping all 4 sections (RefInit, ExpInit, RefFinal, ExpFinal) and placing them in the center of new Bitmaps with 2^n dimensions
        Rectangle rExp = new Rectangle(1, 157, 1024, 131);
        Bitmap ExpInitCrop = new Bitmap(rExp.Width, rExp.Height);
        Graphics g = Graphics.FromImage(ExpInitCrop);
        g.DrawImage(BMInit, -rExp.X, -rExp.Y);
        Bitmap ExpInitLarge = new Bitmap(2048, 512);
        using (Graphics largeGraphics = Graphics.FromImage(ExpInitLarge))
        {
            largeGraphics.DrawImage(ExpInitCrop, 513, 190);
        }
        Rectangle rRef = new Rectangle(1, 484, 1024, 131);
        Bitmap RefInitCrop = new Bitmap(rRef.Width, rRef.Height);
        Graphics h = Graphics.FromImage(RefInitCrop);
        h.DrawImage(BMInit, -rRef.X, -rRef.Y);
        Bitmap RefInitLarge = new Bitmap(2048, 512);
        using (Graphics largeGraphics = Graphics.FromImage(RefInitLarge))
        {
            largeGraphics.DrawImage(RefInitCrop, 513, 190);
        }
        Bitmap ExpFinalCrop = new Bitmap(rExp.Width, rExp.Height);
        Graphics i = Graphics.FromImage(ExpFinalCrop);
        i.DrawImage(BMFinal, -rExp.X, -rExp.Y);
        Bitmap ExpFinalLarge = new Bitmap(2048, 512);
        using (Graphics largeGraphics = Graphics.FromImage(ExpFinalLarge))
        {
            largeGraphics.DrawImage(ExpFinalCrop, 513, 190);
        }
        Bitmap RefFinalCrop = new Bitmap(rRef.Width, rRef.Height);
        Graphics j = Graphics.FromImage(RefFinalCrop);
        j.DrawImage(BMFinal, -rRef.X, -rRef.Y);
        Bitmap RefFinalLarge = new Bitmap(2048, 512);
        using (Graphics largeGraphics = Graphics.FromImage(RefFinalLarge))
        {
            largeGraphics.DrawImage(RefFinalCrop, 513, 190);
        }

        // Grayscalling the 4 sections to get 8bppIndexed PixelFormat
        Accord.Imaging.Filters.Grayscale filterGS = new Accord.Imaging.Filters.Grayscale(0.2125, 0.7154, 0.0721);
        Bitmap RefFinalLargeGS = filterGS.Apply(RefFinalLarge);
        Bitmap ExpFinalLargeGS = filterGS.Apply(ExpFinalLarge);
        Bitmap RefInitLargeGS = filterGS.Apply(RefInitLarge);
        Bitmap ExpInitLargeGS = filterGS.Apply(ExpInitLarge);

        // FFT on the 4 sections
        Accord.Imaging.ComplexImage ExpInitComplex = Accord.Imaging.ComplexImage.FromBitmap(ExpInitLargeGS);
        ExpInitComplex.ForwardFourierTransform();
        Accord.Imaging.ComplexImage RefInitComplex = Accord.Imaging.ComplexImage.FromBitmap(RefInitLargeGS);
        RefInitComplex.ForwardFourierTransform();
        Accord.Imaging.ComplexImage ExpFinalComplex = Accord.Imaging.ComplexImage.FromBitmap(ExpFinalLargeGS);
        ExpFinalComplex.ForwardFourierTransform();
        Accord.Imaging.ComplexImage RefFinalComplex = Accord.Imaging.ComplexImage.FromBitmap(RefFinalLargeGS);
        RefFinalComplex.ForwardFourierTransform();

        //Conjugating the ExpFinal and RefFinal section
        Complex[,] CompConjExpFinal = new Complex[ExpFinalComplex.Height, ExpFinalComplex.Width];
        Complex[,] CompConjRefFinal = new Complex[RefFinalComplex.Height, RefFinalComplex.Width];
        for (int l = 0; l < ExpFinalComplex.Height; l++)
        {
            for (int m = 0; m < ExpFinalComplex.Width; m++)
            {
                CompConjExpFinal[l, m] = System.Numerics.Complex.Conjugate(ExpFinalComplex.Data[l, m]);
                ExpFinalComplex.Data[l, m] = CompConjExpFinal[l, m];
            }
        }
        for (int l = 0; l < RefFinalComplex.Height; l++)
        {
            for (int m = 0; m < RefFinalComplex.Width; m++)
            {
                CompConjRefFinal[l, m] = System.Numerics.Complex.Conjugate(RefFinalComplex.Data[l, m]);
                RefFinalComplex.Data[l, m] = CompConjRefFinal[l, m];
            }
        }

        //Element-wise multiplication of the complex arrays two by two
        Complex[,] ExpMultipliedMatrix = new Complex[ExpFinalComplex.Height, ExpFinalComplex.Width];
        Complex[,] RefMultipliedMatrix = new Complex[RefFinalComplex.Height, RefFinalComplex.Width];
        for (int l = 0; l < ExpFinalComplex.Height; l++)
        {
            for (int m = 0; m < ExpFinalComplex.Width; m++)
            {
                ExpMultipliedMatrix[l, m] = System.Numerics.Complex.Multiply(ExpInitComplex.Data[l, m], ExpFinalComplex.Data[l, m]);
                RefMultipliedMatrix[l, m] = System.Numerics.Complex.Multiply(RefInitComplex.Data[l, m], RefFinalComplex.Data[l, m]);
            }
        }

        //InverseFFT
        Complex[,] CrossCorrExpMatrix = new Complex[ExpFinalComplex.Height, ExpFinalComplex.Width];
        Complex[,] CrossCorrRefMatrix = new Complex[RefFinalComplex.Height, RefFinalComplex.Width];
        Accord.Math.FourierTransform.FFT2(ExpMultipliedMatrix, FourierTransform.Direction.Backward);
        Accord.Math.FourierTransform.FFT2(RefMultipliedMatrix, FourierTransform.Direction.Backward);
        CrossCorrExpMatrix = ExpMultipliedMatrix;
        CrossCorrRefMatrix = RefMultipliedMatrix;
    }

非常感谢!

【问题讨论】:

    标签: c# fft correlation complex-numbers


    【解决方案1】:

    结果的虚部应为 0(或在数值误差范围内)。要找到偏移,您应该查看相关幅度峰值的位置(但除非您有一个是另一个的负图像,否则可能对应于相关实部的峰值)。需要注意的主要事项:由于您将两个图像都居中,因此将引入额外的移位(图像大小的一半)。

    至于查看图表,您可以相当轻松地将结果映射到灰度图像并使用您喜欢的图像查看器进行查看。

    【讨论】:

    • 我要测试一下,谢谢。至于您提到的额外移位,我可以通过在位图的左上角对齐我的图像来摆脱它吗?如果互相关有问题吗?
    • 您可以通过环绕左上角的图像中心来消除额外的移位(这样您就可以在位图的 4 个角中获得图像的 1/4以交换的方式),就像使用 matlab 的 fftshift..
    猜你喜欢
    • 1970-01-01
    • 2014-04-11
    • 2014-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多