是否有可能识别 OpenCV 中嘈杂图像之间如此微小的变化?

Is it possible to recognize so minimal changes between noisy images in OpenCV?

我想使用图像评估(分辨率:31x512,图像速率:每秒 1000 张)来检测传送带的极小运动。皮带启动的时刻对我来说很重要。

如果我在两个后续图像之间做 cv::absdiff,我会得到非常嘈杂的结果:

根据电机的机械旋转传感器,运动从这里开始:

我试图用级联的腐蚀和膨胀来对 abs-diff 图像进行阈值处理,但我可以在这张图像中检测到最早的变化超过第二秒:

能不能早点找到零钱? 这是没有变化的图像序列(根据电机传感器):

在此序列中,移动从中间图像开始:

看来我找到了适用于我的情况的解决方案。 不要比较 space 域中的图像变化,而应应用互相关:

我将两个图像都转换为 DFT,乘以 DFT-Mats 并转换回来。最大像素值是相关性的中心。只要图像相同,最大像素保持在相同位置,否则移动。

实际工作代码使用3张图像,图像1,2和2,3之间的2个DFT乘法结果:

Mat img1_( 512, 32, CV_16UC1 );
Mat img2_( 512, 32, CV_16UC1 );
Mat img3_( 512, 32, CV_16UC1 );
//read the  data in the images wohever you want. I read from MHD-file

//Set ROI (if required)
Mat img1 = img1_(cv::Rect(0,200,32,100));
Mat img2 = img2_(cv::Rect(0,200,32,100));
Mat img3 = img3_(cv::Rect(0,200,32,100));

//Float mats for DFT
Mat img1f;
Mat img2f;
Mat img3f;

//DFT and produtcts mats
Mat dft1,dft2,dft3,dftproduct,dftproduct2;

//Calculate DFT of both images
img1.convertTo(img1f, CV_32FC1);
cv::dft(img1f, dft1);

img2.convertTo(img3f, CV_32FC1);
cv::dft(img3f, dft3);

img3.convertTo(img2f, CV_32FC1);
cv::dft(img2f, dft2);

//Multiply DFT Mats
cv::mulSpectrums(dft1,dft2,dftproduct,true);
cv::mulSpectrums(dft2,dft3,dftproduct2,true);

//Convert back to space domain
cv::Mat result,result2;
cv::idft(dftproduct,result);
cv::idft(dftproduct2,result2);

//Not sure if required, I needed it for visualizing 
cv::normalize( result, result, 0, 255, NORM_MINMAX, CV_8UC1);
cv::normalize( result2, result2, 0, 255, NORM_MINMAX, CV_8UC1);



//Find maxima positions
double dummy;
Point locdummy; Point maxLoc1; Point maxLoc2;
cv::minMaxLoc(result, &dummy, &dummy, &locdummy, &maxLoc1);
cv::minMaxLoc(result2, &dummy, &dummy, &locdummy, &maxLoc2);

//Calculate products simply fot having one value to compare
int maxlocProd1 = maxLoc1.x*maxLoc1.y;
int maxlocProd2 = maxLoc2.x*maxLoc2.y;

//Calculate absolute difference of the products. Not 0 means movement
int absPosDiff = std::abs(maxlocProd2-maxlocProd1);


if ( absPosDiff>0 )
{
   std::cout << id<< std::endl;
   break;
}