是否有可能识别 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;
}
我想使用图像评估(分辨率: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;
}