参考:
原理:http://www.360doc.com/content/18/0301/16/18306241_733458609.shtml
使用:https://blog.csdn.net/wujuxKkoolerter/article/details/113068318
最近在弄一个图像拼接的东西,总体上类似把一个面阵相机当成线阵相机那样用,把连续拍摄的图片拼接起来。
但是难点在于拍摄的物体并不是匀速运动的,也没有编码器给出位移的脉冲信号。
所以只能够根据前后两张图片来计算被拍摄物体的位移,然后拼接了。
一开始是用各种方法来找特征、均值、最值什么的,甚至opencv的各种tracking方法都用过了,效果都不好。
然后无意中发现了这个 phaseCorrelate 函数,用了之后发现,居然有奇效。效果好、速度快,完美。
void MainWindow::phaseTest()
{
QStringList mFileList;
QString imgSrc;
if(IMG_SOURCE == 0)
{
imgSrc = "./imgs/left";
}
else
{
imgSrc = "./imgs/right";
}
QDir dir(imgSrc);
dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
dir.setSorting(QDir::Size | QDir::Reversed);
QFileInfoList list = dir.entryInfoList();
for (int i = 0; i < list.size(); ++i)
{
QFileInfo fileInfo = list.at(i);
mFileList.push_back(fileInfo.filePath().toUtf8());
}
QCollator collator;
collator.setNumericMode(true);
std::sort(mFileList.begin(), mFileList.end(),
[& collator](const QString & str1, const QString & str2)
{
return collator.compare(str1, str2) < 0;
}
);
qDebug() << mFileList;
Mat stitchedMat;
for(int i = 0; i < mFileList.length() - 1; i++)
{
Mat img1 = imread(mFileList[i].toStdString(), IMREAD_GRAYSCALE);
Mat img2 = imread(mFileList[i + 1].toStdString(), IMREAD_GRAYSCALE);
cv::Rect roi;
if(IMG_SOURCE == 0)
{
roi = cv::Rect(650, 270, 750, 120);
}
else
{
roi = cv::Rect(640, 194, 210, 178);
}
img1 = img1(roi);
img2 = img2(roi);
if(stitchedMat.empty())
{
stitchedMat = img1.clone();
}
Mat pre32f, cur32f, hann;
// img1.convertTo(pre32f, CV_32F);
// img2.convertTo(cur32f, CV_32F);
GaussianBlur(img1, img1, Size(5,5), 0, 0, BORDER_DEFAULT);
GaussianBlur(img2, img2, Size(5,5), 0, 0, BORDER_DEFAULT);
cv::Laplacian(img1, pre32f, CV_32F, 3);
cv::Laplacian(img2, cur32f, CV_32F, 3);
imshow("lap", pre32f);
QTime begin = QTime::currentTime();
auto offset2d = phaseCorrelate(pre32f, cur32f);
qDebug() << "interval:" << begin.msecsTo(QTime::currentTime());
qDebug() << offset2d.x << offset2d.y;
int offset = offset2d.y + 0.5;
if(offset > 1)
{
Mat out;
OptimizeSeam(img2, stitchedMat, offset, out);
stitchedMat = out;
}
imshow("img", img2);
imshow("拼接图像", stitchedMat);
cv::waitKey(1);
}
}
后记:后来实际部署到产线之后,效果还是不如之前用的sobel+模板的方式好。唉,离线分析和实际生产区别还是挺大的。