Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;用OpenCV实现两幅移位图像的互相关_C++_Opencv - Fatal编程技术网

C++ C++;用OpenCV实现两幅移位图像的互相关

C++ C++;用OpenCV实现两幅移位图像的互相关,c++,opencv,C++,Opencv,我想对两幅移位的图像进行互相关。一般来说,我会这样做: -加载2个图像 -用这两幅图像进行dft -使用mulSpectrum(opencv)将这些图像相乘 -对乘法的结果进行逆dft -显示结果——在结果图像中必须有频率偏移,这是真实图像的偏移。 我已经用openCV完成了这项工作: #include "opencv2/core/core.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.

我想对两幅移位的图像进行互相关。一般来说,我会这样做: -加载2个图像 -用这两幅图像进行dft -使用mulSpectrum(opencv)将这些图像相乘 -对乘法的结果进行逆dft -显示结果——在结果图像中必须有频率偏移,这是真实图像的偏移。 我已经用openCV完成了这项工作:

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>


using namespace std;
using namespace cv;

void fft_shift(Mat &I, Mat &magI) //shift the origin to the center of the image (taken from OpenCV example of dft)
{
    Mat padded;                            //expand input image to optimal size
    int m = getOptimalDFTSize(I.rows);
    int n = getOptimalDFTSize(I.cols); // on the border add zero values
    copyMakeBorder(I, padded, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, Scalar::all(0));

    Mat planes[] = { Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F) };
    Mat complexI;
    merge(planes, 2, complexI);         // Add to the expanded another plane with zeros

    dft(complexI, complexI);            // this way the result may fit in the source matrix

                                        // compute the magnitude and switch to logarithmic scale
                                        // => log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))
    split(complexI, planes);                   // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))
    magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude
    magI = planes[0];

    magI += Scalar::all(1);                    // switch to logarithmic scale
    log(magI, magI);

    // crop the spectrum, if it has an odd number of rows or columns
    magI = magI(Rect(0, 0, magI.cols & -2, magI.rows & -2));

    // rearrange the quadrants of Fourier image  so that the origin is at the image center
    int cx = magI.cols / 2;
    int cy = magI.rows / 2;

    Mat q0(magI, Rect(0, 0, cx, cy));   // Top-Left - Create a ROI per quadrant
    Mat q1(magI, Rect(cx, 0, cx, cy));  // Top-Right
    Mat q2(magI, Rect(0, cy, cx, cy));  // Bottom-Left
    Mat q3(magI, Rect(cx, cy, cx, cy)); // Bottom-Right

    Mat tmp;                           // swap quadrants (Top-Left with Bottom-Right)
    q0.copyTo(tmp);
    q3.copyTo(q0);
    tmp.copyTo(q3);

    q1.copyTo(tmp);                    // swap quadrant (Top-Right with Bottom-Left)
    q2.copyTo(q1);
    tmp.copyTo(q2);


}

int main()
{

//load images and convert them to greyscale
    Mat I = imread("original_Image.png");
    cv::cvtColor(I, I, CV_BGR2GRAY);
    Mat II = imread("shifted_Image.png");
    cv::cvtColor(II, II, CV_BGR2GRAY);
    if (I.empty())
        return -1;

    // call the fft_shift function and multiply this to spectrum
    Mat mag1, mag1_shift, mag3,mag4;
    fft_shift(I,mag1);
    fft_shift(II, mag1_shift);
    mulSpectrums(mag1, mag1_shift,mag3, 0, 1);

    //perform an inverse dft and shift it, then normalize is for displaying
    cv::dft(mag3, mag3, cv::DFT_INVERSE | cv::DFT_REAL_OUTPUT);
    fft_shift(mag3, mag4);    
    normalize(mag4, mag4, 0, 1, CV_MINMAX);    
    imshow("spectrum shift", mag4);
    waitKey();

    return 0;
} 
#包括“opencv2/core/core.hpp”
#包括“opencv2/imgproc/imgproc.hpp”
#包括“opencv2/highgui/highgui.hpp”
#包括
使用名称空间std;
使用名称空间cv;
void fft_shift(Mat&I,Mat&magI)//将原点移到图像的中心(取自OpenCV的dft示例)
{
Mat padded;//将输入图像扩展到最佳大小
int m=getOptimalDFTSize(即行);
int n=getOptimalDFTSize(I.cols);//在边框上添加零值
copyMakeBorder(I,padded,0,m-I.rows,0,n-I.cols,BORDER_常量,Scalar::all(0));
Mat平面[]={Mat_u(padded),Mat::zeros(padded.size(),CV_32F)};
席状复合体;
合并(平面,2,复杂);//添加到扩展的另一个带有零的平面
dft(complexI,complexI);//这样,结果可以适合源矩阵
//计算震级并切换到对数刻度
//=>log(1+sqrt(Re(DFT(I))^2+Im(DFT(I))^2))
拆分(复数,平面);//平面[0]=Re(DFT(I),平面[1]=Im(DFT(I))
幅值(平面[0],平面[1],平面[0]);//平面[0]=幅值
magI=平面[0];
magI+=Scalar::all(1);//切换到对数刻度
日志(magI,magI);
//如果光谱的行数或列数为奇数,则裁剪光谱
magI=magI(Rect(0,0,magI.cols&-2,magI.rows&-2));
//重新排列傅里叶图像的象限,使原点位于图像中心
int cx=magI.cols/2;
int cy=magI.rows/2;
Mat q0(magI,Rect(0,0,cx,cy));//左上角-为每个象限创建一个ROI
Mat q1(magI,Rect(cx,0,cx,cy));//右上角
Mat q2(magI,Rect(0,cy,cx,cy));//左下角
Mat q3(magI,Rect(cx,cy,cx,cy));//右下角
Mat tmp;//交换象限(左上角与右下角)
q0.copyTo(tmp);
q3.复制到(q0);
tmp.copyTo(第三季度);
q1.copyTo(tmp);//交换象限(右上角与左下角)
q2.抄袭(q1);
tmp.copyTo(第2季度);
}
int main()
{
//加载图像并将其转换为灰度
Mat I=imread(“original_Image.png”);
cv::cvtColor(I,I,cv_bgr2灰色);
Mat II=imread(“shifted_Image.png”);
cv::CVT颜色(II,II,cv_bgr2灰色);
if(I.empty())
返回-1;
//调用fft_移位函数并将其乘以频谱
Mat mag1、mag1_移位、mag3、mag4;
fft_移位(I,mag1);
fft_移位(II,mag1_移位);
多光谱(mag1,mag1_移位,mag3,0,1);
//执行反向dft并将其移位,然后“规格化”用于显示
cv::dft(mag3,mag3,cv::dft_逆| cv::dft_实输出);
fft_移位(mag3,mag4);
正常化(mag4、mag4、0、1、CV_MINMAX);
imshow(“光谱偏移”,mag4);
waitKey();
返回0;
} 
以下是此计算的结果:结果

这是我期望的结果:期望的结果


这个结果是从Python程序中取出的:我试着把这个代码翻译成C++,这是上面的代码,但是它不起作用。有人知道,我在这里做了什么错事吗?< /P> < p>我从本页的第二篇文章中找到了一个解决方案: 该代码的结果是:

现在我必须规范化这个图像,只看到移位点

因此,在进行ifft之前,必须规范化多光谱的结果(从上面的链接中截取的代码):

在此之后,必须交换象限,如openCV示例中所示:

// crop the spectrum, if it has an odd number of rows or columns
    fft1 = fft1(Rect(0, 0, fft1.cols & -2, fft1.rows & -2));
    // rearrange the quadrants of Fourier image  so that the origin is at the image center
    int cx = fft1.cols / 2;
    int cy = fft1.rows / 2;

    Mat q0(fft1, Rect(0, 0, cx, cy));   // Top-Left - Create a ROI per quadrant
    Mat q1(fft1, Rect(cx, 0, cx, cy));  // Top-Right
    Mat q2(fft1, Rect(0, cy, cx, cy));  // Bottom-Left
    Mat q3(fft1, Rect(cx, cy, cx, cy)); // Bottom-Right

    Mat tmp;                           // swap quadrants (Top-Left with Bottom-Right)
    q0.copyTo(tmp);
    q3.copyTo(q0);
    tmp.copyTo(q3);

    q1.copyTo(tmp);                    // swap quadrant (Top-Right with Bottom-Left)
    q2.copyTo(q1);
    tmp.copyTo(q2);
现在,结果与python代码中的结果类似:

或者我可以只使用:

Point2d phaseCorrelate(InputArray src1、InputArray src2、InputArray window=noArray())


这为我做了所有的事情

你可能会在逆fft的比例上出错,因为你
多光谱
,你需要除以(宽度*高度)^2以获得正确的结果,而不是将其标准化

你可以拿我的食谱:

cv::Mat XCorrelation(cv::Mat const&I,cv::Mat const&I1)
{
int-width=cv::getoptimizedftsize(std::max(I.cols,I1.cols));
int height=cv::getoptimizedftsize(std::max(I.rows,I1.rows));
cv::Mat fft1;
cv::Mat fft2;
cv::copyMakeBorder(I,fft1,0,高度-I.rows,0,宽度-I.cols,cv::BORDER_常量,cv::Scalar::all(0));
cv::copyMakeBorder(I1,fft2,0,height-I.rows,0,width-I.cols,cv::BORDER_常量,cv::Scalar::all(0));
fft1.convertTo(fft1,CV_32F);
fft2.convertTo(fft2,CV_32F);
cv::dft(fft1,fft1,0,I.行);
cv::dft(fft2,fft2,0,I1.行);
cv::多光谱(fft1,fft2,fft1,0,真);
//此处cv::DFT_比例除以“宽度*高度”1倍
cv::idft(fft1,fft1,cv::DFT_标度| cv::DFT_实输出);
重排(fft1,fft1);
//这里再分一次
返回cv::abs(fft1)/(宽度*高度);
}
重排
功能与您的
fft\u移位
功能相同,如下所示:

void重排(cv::Mat&src,cv::Mat&dst)
{
int cx=src.cols/2;
int cy=src.rows/2;
cv::Mat-tmp;
create(src.size(),src.type());
src(cv::Rect(0,0,cx,cy)).copyTo(tmp(cv::Rect(cx,cy,cx,cy));
src(cv::Rect(cx,cy,cx,cy)).copyTo(tmp(cv::Rect(0,0,cx,cy));
src(cv::Rect(cx,0,cx,cy)).copyTo(tmp(cv::Rect(0,cy,cx,cy));
src(cv::Rect(0,cy,cx,cy)).copyTo(tmp(cv::Rect(cx,0,cx,
// crop the spectrum, if it has an odd number of rows or columns
    fft1 = fft1(Rect(0, 0, fft1.cols & -2, fft1.rows & -2));
    // rearrange the quadrants of Fourier image  so that the origin is at the image center
    int cx = fft1.cols / 2;
    int cy = fft1.rows / 2;

    Mat q0(fft1, Rect(0, 0, cx, cy));   // Top-Left - Create a ROI per quadrant
    Mat q1(fft1, Rect(cx, 0, cx, cy));  // Top-Right
    Mat q2(fft1, Rect(0, cy, cx, cy));  // Bottom-Left
    Mat q3(fft1, Rect(cx, cy, cx, cy)); // Bottom-Right

    Mat tmp;                           // swap quadrants (Top-Left with Bottom-Right)
    q0.copyTo(tmp);
    q3.copyTo(q0);
    tmp.copyTo(q3);

    q1.copyTo(tmp);                    // swap quadrant (Top-Right with Bottom-Left)
    q2.copyTo(q1);
    tmp.copyTo(q2);